torture-samr: Improve rpc.samr.passwords.badpwdcount test
[Samba.git] / source4 / torture / rpc / samr.c
blob551cd4539fd335a1e217db7264fa88d1192fa182
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) Jelmer Vernooij 2005-2007
8 Copyright (C) Guenther Deschner 2008-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include <tevent.h>
27 #include "system/time.h"
28 #include "system/network.h"
29 #include "librpc/gen_ndr/lsa.h"
30 #include "librpc/gen_ndr/ndr_netlogon.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
33 #include "librpc/gen_ndr/ndr_lsa_c.h"
34 #include "../lib/crypto/crypto.h"
35 #include "libcli/auth/libcli_auth.h"
36 #include "libcli/security/security.h"
37 #include "torture/rpc/torture_rpc.h"
38 #include "param/param.h"
39 #include "auth/gensec/gensec.h"
40 #include "auth/gensec/gensec_proto.h"
41 #include "../libcli/auth/schannel.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_result(tctx, TORTURE_FAIL, #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_result(tctx, TORTURE_FAIL, "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_result(tctx, TORTURE_FAIL, "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_result(tctx, TORTURE_FAIL, "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 code_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_result(tctx, TORTURE_FAIL, "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 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
668 __location__, __FUNCTION__,
669 newpass, nt_errstr(s.out.result));
670 if (!NT_STATUS_IS_OK(s.out.result)) {
671 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
672 s.in.level, nt_errstr(s.out.result));
673 ret = false;
674 } else {
675 *password = newpass;
678 return ret;
682 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
683 struct policy_handle *handle, uint32_t fields_present,
684 char **password)
686 NTSTATUS status;
687 struct samr_SetUserInfo s;
688 union samr_UserInfo u;
689 bool ret = true;
690 DATA_BLOB session_key;
691 struct dcerpc_binding_handle *b = p->binding_handle;
692 char *newpass;
693 struct samr_GetUserPwInfo pwp;
694 struct samr_PwInfo info;
695 int policy_min_pw_len = 0;
696 pwp.in.user_handle = handle;
697 pwp.out.info = &info;
699 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
700 "GetUserPwInfo failed");
701 if (NT_STATUS_IS_OK(pwp.out.result)) {
702 policy_min_pw_len = pwp.out.info->min_password_length;
704 newpass = samr_rand_pass(tctx, policy_min_pw_len);
706 s.in.user_handle = handle;
707 s.in.info = &u;
708 s.in.level = 23;
710 ZERO_STRUCT(u);
712 u.info23.info.fields_present = fields_present;
714 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
716 status = dcerpc_fetch_session_key(p, &session_key);
717 if (!NT_STATUS_IS_OK(status)) {
718 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
719 s.in.level, nt_errstr(status));
720 return false;
723 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
725 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
727 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
728 "SetUserInfo failed");
729 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
730 __location__, __FUNCTION__,
731 newpass, nt_errstr(s.out.result));
732 if (!NT_STATUS_IS_OK(s.out.result)) {
733 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
734 s.in.level, nt_errstr(s.out.result));
735 ret = false;
736 } else {
737 *password = newpass;
740 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
742 status = dcerpc_fetch_session_key(p, &session_key);
743 if (!NT_STATUS_IS_OK(status)) {
744 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
745 s.in.level, nt_errstr(status));
746 return false;
749 /* This should break the key nicely */
750 session_key.length--;
751 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
753 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
755 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
756 "SetUserInfo failed");
757 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
758 __location__, __FUNCTION__,
759 newpass, nt_errstr(s.out.result));
760 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
761 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
762 s.in.level, nt_errstr(s.out.result));
763 ret = false;
766 return ret;
770 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
771 struct policy_handle *handle, bool makeshort,
772 char **password)
774 NTSTATUS status;
775 struct samr_SetUserInfo s;
776 union samr_UserInfo u;
777 bool ret = true;
778 DATA_BLOB session_key;
779 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
780 uint8_t confounder[16];
781 char *newpass;
782 struct dcerpc_binding_handle *b = p->binding_handle;
783 MD5_CTX ctx;
784 struct samr_GetUserPwInfo pwp;
785 struct samr_PwInfo info;
786 int policy_min_pw_len = 0;
787 pwp.in.user_handle = handle;
788 pwp.out.info = &info;
790 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
791 "GetUserPwInfo failed");
792 if (NT_STATUS_IS_OK(pwp.out.result)) {
793 policy_min_pw_len = pwp.out.info->min_password_length;
795 if (makeshort && policy_min_pw_len) {
796 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
797 } else {
798 newpass = samr_rand_pass(tctx, policy_min_pw_len);
801 s.in.user_handle = handle;
802 s.in.info = &u;
803 s.in.level = 26;
805 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
806 u.info26.password_expired = 0;
808 status = dcerpc_fetch_session_key(p, &session_key);
809 if (!NT_STATUS_IS_OK(status)) {
810 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
811 s.in.level, nt_errstr(status));
812 return false;
815 generate_random_buffer((uint8_t *)confounder, 16);
817 MD5Init(&ctx);
818 MD5Update(&ctx, confounder, 16);
819 MD5Update(&ctx, session_key.data, session_key.length);
820 MD5Final(confounded_session_key.data, &ctx);
822 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
823 memcpy(&u.info26.password.data[516], confounder, 16);
825 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
827 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
828 "SetUserInfo failed");
829 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
830 __location__, __FUNCTION__,
831 newpass, nt_errstr(s.out.result));
832 if (!NT_STATUS_IS_OK(s.out.result)) {
833 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
834 s.in.level, nt_errstr(s.out.result));
835 ret = false;
836 } else {
837 *password = newpass;
840 /* This should break the key nicely */
841 confounded_session_key.data[0]++;
843 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
844 memcpy(&u.info26.password.data[516], confounder, 16);
846 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
848 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
849 "SetUserInfo failed");
850 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
851 __location__, __FUNCTION__,
852 newpass, nt_errstr(s.out.result));
853 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
854 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
855 s.in.level, nt_errstr(s.out.result));
856 ret = false;
857 } else {
858 *password = newpass;
861 return ret;
864 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
865 struct policy_handle *handle, uint32_t fields_present,
866 char **password)
868 NTSTATUS status;
869 struct samr_SetUserInfo s;
870 union samr_UserInfo u;
871 bool ret = true;
872 DATA_BLOB session_key;
873 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
874 MD5_CTX ctx;
875 uint8_t confounder[16];
876 char *newpass;
877 struct dcerpc_binding_handle *b = p->binding_handle;
878 struct samr_GetUserPwInfo pwp;
879 struct samr_PwInfo info;
880 int policy_min_pw_len = 0;
881 pwp.in.user_handle = handle;
882 pwp.out.info = &info;
884 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
885 "GetUserPwInfo failed");
886 if (NT_STATUS_IS_OK(pwp.out.result)) {
887 policy_min_pw_len = pwp.out.info->min_password_length;
889 newpass = samr_rand_pass(tctx, policy_min_pw_len);
891 s.in.user_handle = handle;
892 s.in.info = &u;
893 s.in.level = 25;
895 ZERO_STRUCT(u);
897 u.info25.info.fields_present = fields_present;
899 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
901 status = dcerpc_fetch_session_key(p, &session_key);
902 if (!NT_STATUS_IS_OK(status)) {
903 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
904 s.in.level, nt_errstr(status));
905 return false;
908 generate_random_buffer((uint8_t *)confounder, 16);
910 MD5Init(&ctx);
911 MD5Update(&ctx, confounder, 16);
912 MD5Update(&ctx, session_key.data, session_key.length);
913 MD5Final(confounded_session_key.data, &ctx);
915 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
916 memcpy(&u.info25.password.data[516], confounder, 16);
918 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
920 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
921 "SetUserInfo failed");
922 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
923 __location__, __FUNCTION__,
924 newpass, nt_errstr(s.out.result));
925 if (!NT_STATUS_IS_OK(s.out.result)) {
926 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
927 s.in.level, nt_errstr(s.out.result));
928 ret = false;
929 } else {
930 *password = newpass;
933 /* This should break the key nicely */
934 confounded_session_key.data[0]++;
936 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
937 memcpy(&u.info25.password.data[516], confounder, 16);
939 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
941 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
942 "SetUserInfo failed");
943 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
944 __location__, __FUNCTION__,
945 newpass, nt_errstr(s.out.result));
946 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
947 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
948 s.in.level, nt_errstr(s.out.result));
949 ret = false;
952 return ret;
955 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
956 struct policy_handle *handle, char **password)
958 NTSTATUS status;
959 struct samr_SetUserInfo s;
960 union samr_UserInfo u;
961 bool ret = true;
962 DATA_BLOB session_key;
963 char *newpass;
964 struct dcerpc_binding_handle *b = p->binding_handle;
965 struct samr_GetUserPwInfo pwp;
966 struct samr_PwInfo info;
967 int policy_min_pw_len = 0;
968 uint8_t lm_hash[16], nt_hash[16];
970 pwp.in.user_handle = handle;
971 pwp.out.info = &info;
973 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
974 "GetUserPwInfo failed");
975 if (NT_STATUS_IS_OK(pwp.out.result)) {
976 policy_min_pw_len = pwp.out.info->min_password_length;
978 newpass = samr_rand_pass(tctx, policy_min_pw_len);
980 s.in.user_handle = handle;
981 s.in.info = &u;
982 s.in.level = 18;
984 ZERO_STRUCT(u);
986 u.info18.nt_pwd_active = true;
987 u.info18.lm_pwd_active = true;
989 E_md4hash(newpass, nt_hash);
990 E_deshash(newpass, lm_hash);
992 status = dcerpc_fetch_session_key(p, &session_key);
993 if (!NT_STATUS_IS_OK(status)) {
994 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
995 s.in.level, nt_errstr(status));
996 return false;
1000 DATA_BLOB in,out;
1001 in = data_blob_const(nt_hash, 16);
1002 out = data_blob_talloc_zero(tctx, 16);
1003 sess_crypt_blob(&out, &in, &session_key, true);
1004 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1007 DATA_BLOB in,out;
1008 in = data_blob_const(lm_hash, 16);
1009 out = data_blob_talloc_zero(tctx, 16);
1010 sess_crypt_blob(&out, &in, &session_key, true);
1011 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1014 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
1016 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1017 "SetUserInfo failed");
1018 if (!NT_STATUS_IS_OK(s.out.result)) {
1019 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1020 s.in.level, nt_errstr(s.out.result));
1021 ret = false;
1022 } else {
1023 *password = newpass;
1026 return ret;
1029 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1030 struct policy_handle *handle, uint32_t fields_present,
1031 char **password)
1033 NTSTATUS status;
1034 struct samr_SetUserInfo s;
1035 union samr_UserInfo u;
1036 bool ret = true;
1037 DATA_BLOB session_key;
1038 char *newpass;
1039 struct dcerpc_binding_handle *b = p->binding_handle;
1040 struct samr_GetUserPwInfo pwp;
1041 struct samr_PwInfo info;
1042 int policy_min_pw_len = 0;
1043 uint8_t lm_hash[16], nt_hash[16];
1045 pwp.in.user_handle = handle;
1046 pwp.out.info = &info;
1048 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1049 "GetUserPwInfo failed");
1050 if (NT_STATUS_IS_OK(pwp.out.result)) {
1051 policy_min_pw_len = pwp.out.info->min_password_length;
1053 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1055 s.in.user_handle = handle;
1056 s.in.info = &u;
1057 s.in.level = 21;
1059 E_md4hash(newpass, nt_hash);
1060 E_deshash(newpass, lm_hash);
1062 ZERO_STRUCT(u);
1064 u.info21.fields_present = fields_present;
1066 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1067 u.info21.lm_owf_password.length = 16;
1068 u.info21.lm_owf_password.size = 16;
1069 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1070 u.info21.lm_password_set = true;
1073 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1074 u.info21.nt_owf_password.length = 16;
1075 u.info21.nt_owf_password.size = 16;
1076 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1077 u.info21.nt_password_set = true;
1080 status = dcerpc_fetch_session_key(p, &session_key);
1081 if (!NT_STATUS_IS_OK(status)) {
1082 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1083 s.in.level, nt_errstr(status));
1084 return false;
1087 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1088 DATA_BLOB in,out;
1089 in = data_blob_const(u.info21.lm_owf_password.array,
1090 u.info21.lm_owf_password.length);
1091 out = data_blob_talloc_zero(tctx, 16);
1092 sess_crypt_blob(&out, &in, &session_key, true);
1093 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1096 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1097 DATA_BLOB in,out;
1098 in = data_blob_const(u.info21.nt_owf_password.array,
1099 u.info21.nt_owf_password.length);
1100 out = data_blob_talloc_zero(tctx, 16);
1101 sess_crypt_blob(&out, &in, &session_key, true);
1102 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1105 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1107 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1108 "SetUserInfo failed");
1109 if (!NT_STATUS_IS_OK(s.out.result)) {
1110 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1111 s.in.level, nt_errstr(s.out.result));
1112 ret = false;
1113 } else {
1114 *password = newpass;
1117 /* try invalid length */
1118 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1120 u.info21.nt_owf_password.length++;
1122 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1123 "SetUserInfo failed");
1124 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1125 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1126 s.in.level, nt_errstr(s.out.result));
1127 ret = false;
1131 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1133 u.info21.lm_owf_password.length++;
1135 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1136 "SetUserInfo failed");
1137 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1138 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1139 s.in.level, nt_errstr(s.out.result));
1140 ret = false;
1144 return ret;
1147 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1148 struct torture_context *tctx,
1149 struct policy_handle *handle,
1150 uint16_t level,
1151 uint32_t fields_present,
1152 char **password, uint8_t password_expired,
1153 bool use_setinfo2,
1154 bool *matched_expected_error)
1156 NTSTATUS status;
1157 NTSTATUS expected_error = NT_STATUS_OK;
1158 struct samr_SetUserInfo s;
1159 struct samr_SetUserInfo2 s2;
1160 union samr_UserInfo u;
1161 bool ret = true;
1162 DATA_BLOB session_key;
1163 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1164 MD5_CTX ctx;
1165 uint8_t confounder[16];
1166 char *newpass;
1167 struct dcerpc_binding_handle *b = p->binding_handle;
1168 struct samr_GetUserPwInfo pwp;
1169 struct samr_PwInfo info;
1170 int policy_min_pw_len = 0;
1171 const char *comment = NULL;
1172 uint8_t lm_hash[16], nt_hash[16];
1174 pwp.in.user_handle = handle;
1175 pwp.out.info = &info;
1177 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1178 "GetUserPwInfo failed");
1179 if (NT_STATUS_IS_OK(pwp.out.result)) {
1180 policy_min_pw_len = pwp.out.info->min_password_length;
1182 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1184 if (use_setinfo2) {
1185 s2.in.user_handle = handle;
1186 s2.in.info = &u;
1187 s2.in.level = level;
1188 } else {
1189 s.in.user_handle = handle;
1190 s.in.info = &u;
1191 s.in.level = level;
1194 if (fields_present & SAMR_FIELD_COMMENT) {
1195 comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
1198 ZERO_STRUCT(u);
1200 switch (level) {
1201 case 18:
1202 E_md4hash(newpass, nt_hash);
1203 E_deshash(newpass, lm_hash);
1205 u.info18.nt_pwd_active = true;
1206 u.info18.lm_pwd_active = true;
1207 u.info18.password_expired = password_expired;
1209 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1210 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1212 break;
1213 case 21:
1214 E_md4hash(newpass, nt_hash);
1215 E_deshash(newpass, lm_hash);
1217 u.info21.fields_present = fields_present;
1218 u.info21.password_expired = password_expired;
1219 u.info21.comment.string = comment;
1221 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1222 u.info21.lm_owf_password.length = 16;
1223 u.info21.lm_owf_password.size = 16;
1224 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1225 u.info21.lm_password_set = true;
1228 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1229 u.info21.nt_owf_password.length = 16;
1230 u.info21.nt_owf_password.size = 16;
1231 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1232 u.info21.nt_password_set = true;
1235 break;
1236 case 23:
1237 u.info23.info.fields_present = fields_present;
1238 u.info23.info.password_expired = password_expired;
1239 u.info23.info.comment.string = comment;
1241 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1243 break;
1244 case 24:
1245 u.info24.password_expired = password_expired;
1247 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1249 break;
1250 case 25:
1251 u.info25.info.fields_present = fields_present;
1252 u.info25.info.password_expired = password_expired;
1253 u.info25.info.comment.string = comment;
1255 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1257 break;
1258 case 26:
1259 u.info26.password_expired = password_expired;
1261 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1263 break;
1266 status = dcerpc_fetch_session_key(p, &session_key);
1267 if (!NT_STATUS_IS_OK(status)) {
1268 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1269 s.in.level, nt_errstr(status));
1270 return false;
1273 generate_random_buffer((uint8_t *)confounder, 16);
1275 MD5Init(&ctx);
1276 MD5Update(&ctx, confounder, 16);
1277 MD5Update(&ctx, session_key.data, session_key.length);
1278 MD5Final(confounded_session_key.data, &ctx);
1280 switch (level) {
1281 case 18:
1283 DATA_BLOB in,out;
1284 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1285 out = data_blob_talloc_zero(tctx, 16);
1286 sess_crypt_blob(&out, &in, &session_key, true);
1287 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1290 DATA_BLOB in,out;
1291 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1292 out = data_blob_talloc_zero(tctx, 16);
1293 sess_crypt_blob(&out, &in, &session_key, true);
1294 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1297 break;
1298 case 21:
1299 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1300 DATA_BLOB in,out;
1301 in = data_blob_const(u.info21.lm_owf_password.array,
1302 u.info21.lm_owf_password.length);
1303 out = data_blob_talloc_zero(tctx, 16);
1304 sess_crypt_blob(&out, &in, &session_key, true);
1305 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1307 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1308 DATA_BLOB in,out;
1309 in = data_blob_const(u.info21.nt_owf_password.array,
1310 u.info21.nt_owf_password.length);
1311 out = data_blob_talloc_zero(tctx, 16);
1312 sess_crypt_blob(&out, &in, &session_key, true);
1313 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1315 break;
1316 case 23:
1317 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1318 break;
1319 case 24:
1320 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1321 break;
1322 case 25:
1323 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1324 memcpy(&u.info25.password.data[516], confounder, 16);
1325 break;
1326 case 26:
1327 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1328 memcpy(&u.info26.password.data[516], confounder, 16);
1329 break;
1332 if (use_setinfo2) {
1333 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1334 "SetUserInfo2 failed");
1335 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1336 __location__, __FUNCTION__,
1337 newpass, nt_errstr(s2.out.result));
1338 status = s2.out.result;
1339 } else {
1340 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1341 "SetUserInfo failed");
1342 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1343 __location__, __FUNCTION__,
1344 newpass, nt_errstr(s.out.result));
1345 status = s.out.result;
1348 if (!NT_STATUS_IS_OK(status)) {
1349 if (fields_present == 0) {
1350 expected_error = NT_STATUS_INVALID_PARAMETER;
1352 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1353 expected_error = NT_STATUS_ACCESS_DENIED;
1357 if (!NT_STATUS_IS_OK(expected_error)) {
1358 if (use_setinfo2) {
1359 torture_assert_ntstatus_equal(tctx,
1360 s2.out.result,
1361 expected_error, "SetUserInfo2 failed");
1362 } else {
1363 torture_assert_ntstatus_equal(tctx,
1364 s.out.result,
1365 expected_error, "SetUserInfo failed");
1367 *matched_expected_error = true;
1368 return true;
1371 if (!NT_STATUS_IS_OK(status)) {
1372 torture_result(tctx, TORTURE_FAIL, "SetUserInfo%s level %u failed - %s\n",
1373 use_setinfo2 ? "2":"", level, nt_errstr(status));
1374 ret = false;
1375 } else {
1376 *password = newpass;
1379 return ret;
1382 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1383 struct torture_context *tctx,
1384 struct policy_handle *handle)
1386 struct samr_SetAliasInfo r;
1387 struct samr_QueryAliasInfo q;
1388 union samr_AliasInfo *info;
1389 uint16_t levels[] = {2, 3};
1390 int i;
1391 bool ret = true;
1393 /* Ignoring switch level 1, as that includes the number of members for the alias
1394 * and setting this to a wrong value might have negative consequences
1397 for (i=0;i<ARRAY_SIZE(levels);i++) {
1398 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1400 r.in.alias_handle = handle;
1401 r.in.level = levels[i];
1402 r.in.info = talloc(tctx, union samr_AliasInfo);
1403 switch (r.in.level) {
1404 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1405 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1406 "Test Description, should test I18N as well"); break;
1407 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1410 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1411 "SetAliasInfo failed");
1412 if (!NT_STATUS_IS_OK(r.out.result)) {
1413 torture_result(tctx, TORTURE_FAIL, "SetAliasInfo level %u failed - %s\n",
1414 levels[i], nt_errstr(r.out.result));
1415 ret = false;
1418 q.in.alias_handle = handle;
1419 q.in.level = levels[i];
1420 q.out.info = &info;
1422 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1423 "QueryAliasInfo failed");
1424 if (!NT_STATUS_IS_OK(q.out.result)) {
1425 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
1426 levels[i], nt_errstr(q.out.result));
1427 ret = false;
1431 return ret;
1434 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1435 struct torture_context *tctx,
1436 struct policy_handle *user_handle)
1438 struct samr_GetGroupsForUser r;
1439 struct samr_RidWithAttributeArray *rids = NULL;
1441 torture_comment(tctx, "Testing GetGroupsForUser\n");
1443 r.in.user_handle = user_handle;
1444 r.out.rids = &rids;
1446 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1447 "GetGroupsForUser failed");
1448 torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1450 return true;
1454 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1455 struct lsa_String *domain_name)
1457 struct samr_GetDomPwInfo r;
1458 struct samr_PwInfo info;
1459 struct dcerpc_binding_handle *b = p->binding_handle;
1461 r.in.domain_name = domain_name;
1462 r.out.info = &info;
1464 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1466 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1467 "GetDomPwInfo failed");
1468 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1470 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1471 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1473 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1474 "GetDomPwInfo failed");
1475 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1477 r.in.domain_name->string = "\\\\__NONAME__";
1478 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1480 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1481 "GetDomPwInfo failed");
1482 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1484 r.in.domain_name->string = "\\\\Builtin";
1485 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1487 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1488 "GetDomPwInfo failed");
1489 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1491 return true;
1494 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1495 struct torture_context *tctx,
1496 struct policy_handle *handle)
1498 struct samr_GetUserPwInfo r;
1499 struct samr_PwInfo info;
1501 torture_comment(tctx, "Testing GetUserPwInfo\n");
1503 r.in.user_handle = handle;
1504 r.out.info = &info;
1506 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1507 "GetUserPwInfo failed");
1508 torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1510 return true;
1513 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1514 struct torture_context *tctx,
1515 struct policy_handle *domain_handle, const char *name,
1516 uint32_t *rid)
1518 NTSTATUS status;
1519 struct samr_LookupNames n;
1520 struct lsa_String sname[2];
1521 struct samr_Ids rids, types;
1523 init_lsa_String(&sname[0], name);
1525 n.in.domain_handle = domain_handle;
1526 n.in.num_names = 1;
1527 n.in.names = sname;
1528 n.out.rids = &rids;
1529 n.out.types = &types;
1530 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 return status;
1534 if (NT_STATUS_IS_OK(n.out.result)) {
1535 *rid = n.out.rids->ids[0];
1536 } else {
1537 return n.out.result;
1540 init_lsa_String(&sname[1], "xxNONAMExx");
1541 n.in.num_names = 2;
1542 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1543 if (!NT_STATUS_IS_OK(status)) {
1544 return status;
1546 if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1547 torture_result(tctx, TORTURE_FAIL, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1548 if (NT_STATUS_IS_OK(n.out.result)) {
1549 return NT_STATUS_UNSUCCESSFUL;
1551 return n.out.result;
1554 n.in.num_names = 0;
1555 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 return status;
1559 if (!NT_STATUS_IS_OK(n.out.result)) {
1560 torture_result(tctx, TORTURE_FAIL, "LookupNames[0] failed - %s\n", nt_errstr(status));
1561 return n.out.result;
1564 init_lsa_String(&sname[0], "xxNONAMExx");
1565 n.in.num_names = 1;
1566 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 return status;
1570 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1571 torture_result(tctx, TORTURE_FAIL, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1572 if (NT_STATUS_IS_OK(n.out.result)) {
1573 return NT_STATUS_UNSUCCESSFUL;
1575 return n.out.result;
1578 init_lsa_String(&sname[0], "xxNONAMExx");
1579 init_lsa_String(&sname[1], "xxNONAME2xx");
1580 n.in.num_names = 2;
1581 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1582 if (!NT_STATUS_IS_OK(status)) {
1583 return status;
1585 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1586 torture_result(tctx, TORTURE_FAIL, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1587 if (NT_STATUS_IS_OK(n.out.result)) {
1588 return NT_STATUS_UNSUCCESSFUL;
1590 return n.out.result;
1593 return NT_STATUS_OK;
1596 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1597 struct torture_context *tctx,
1598 struct policy_handle *domain_handle,
1599 const char *name, struct policy_handle *user_handle)
1601 NTSTATUS status;
1602 struct samr_OpenUser r;
1603 uint32_t rid;
1605 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1606 if (!NT_STATUS_IS_OK(status)) {
1607 return status;
1610 r.in.domain_handle = domain_handle;
1611 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1612 r.in.rid = rid;
1613 r.out.user_handle = user_handle;
1614 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 return status;
1618 if (!NT_STATUS_IS_OK(r.out.result)) {
1619 torture_result(tctx, TORTURE_FAIL, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1622 return r.out.result;
1625 #if 0
1626 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1627 struct torture_context *tctx,
1628 struct policy_handle *handle)
1630 NTSTATUS status;
1631 struct samr_ChangePasswordUser r;
1632 bool ret = true;
1633 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1634 struct policy_handle user_handle;
1635 char *oldpass = "test";
1636 char *newpass = "test2";
1637 uint8_t old_nt_hash[16], new_nt_hash[16];
1638 uint8_t old_lm_hash[16], new_lm_hash[16];
1640 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1641 if (!NT_STATUS_IS_OK(status)) {
1642 return false;
1645 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1647 torture_comment(tctx, "old password: %s\n", oldpass);
1648 torture_comment(tctx, "new password: %s\n", newpass);
1650 E_md4hash(oldpass, old_nt_hash);
1651 E_md4hash(newpass, new_nt_hash);
1652 E_deshash(oldpass, old_lm_hash);
1653 E_deshash(newpass, new_lm_hash);
1655 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1656 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1657 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1658 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1659 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1660 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1662 r.in.handle = &user_handle;
1663 r.in.lm_present = 1;
1664 r.in.old_lm_crypted = &hash1;
1665 r.in.new_lm_crypted = &hash2;
1666 r.in.nt_present = 1;
1667 r.in.old_nt_crypted = &hash3;
1668 r.in.new_nt_crypted = &hash4;
1669 r.in.cross1_present = 1;
1670 r.in.nt_cross = &hash5;
1671 r.in.cross2_present = 1;
1672 r.in.lm_cross = &hash6;
1674 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1675 "ChangePasswordUser failed");
1676 if (!NT_STATUS_IS_OK(r.out.result)) {
1677 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1678 ret = false;
1681 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1682 ret = false;
1685 return ret;
1687 #endif
1689 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1690 struct torture_context *tctx,
1691 const char *acct_name,
1692 struct policy_handle *handle, char **password)
1694 NTSTATUS status;
1695 struct samr_ChangePasswordUser r;
1696 bool ret = true;
1697 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1698 struct policy_handle user_handle;
1699 char *oldpass;
1700 uint8_t old_nt_hash[16], new_nt_hash[16];
1701 uint8_t old_lm_hash[16], new_lm_hash[16];
1702 bool changed = true;
1704 char *newpass;
1705 struct samr_GetUserPwInfo pwp;
1706 struct samr_PwInfo info;
1707 int policy_min_pw_len = 0;
1709 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1710 if (!NT_STATUS_IS_OK(status)) {
1711 return false;
1713 pwp.in.user_handle = &user_handle;
1714 pwp.out.info = &info;
1716 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1717 "GetUserPwInfo failed");
1718 if (NT_STATUS_IS_OK(pwp.out.result)) {
1719 policy_min_pw_len = pwp.out.info->min_password_length;
1721 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1723 torture_comment(tctx, "Testing ChangePasswordUser\n");
1725 torture_assert(tctx, *password != NULL,
1726 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1728 oldpass = *password;
1730 E_md4hash(oldpass, old_nt_hash);
1731 E_md4hash(newpass, new_nt_hash);
1732 E_deshash(oldpass, old_lm_hash);
1733 E_deshash(newpass, new_lm_hash);
1735 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1736 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1737 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1738 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1739 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1740 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1742 r.in.user_handle = &user_handle;
1743 r.in.lm_present = 1;
1744 /* Break the NT hash */
1745 hash3.hash[0]++;
1746 r.in.old_lm_crypted = &hash1;
1747 r.in.new_lm_crypted = &hash2;
1748 r.in.nt_present = 1;
1749 r.in.old_nt_crypted = &hash3;
1750 r.in.new_nt_crypted = &hash4;
1751 r.in.cross1_present = 1;
1752 r.in.nt_cross = &hash5;
1753 r.in.cross2_present = 1;
1754 r.in.lm_cross = &hash6;
1756 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1757 "ChangePasswordUser failed");
1758 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1759 __location__, __FUNCTION__,
1760 oldpass, newpass, nt_errstr(r.out.result));
1762 /* Do not proceed if this call has been removed */
1763 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
1764 torture_skip(tctx, "ValidatePassword not supported by server\n");
1767 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1768 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1769 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1772 /* Unbreak the NT hash */
1773 hash3.hash[0]--;
1775 r.in.user_handle = &user_handle;
1776 r.in.lm_present = 1;
1777 r.in.old_lm_crypted = &hash1;
1778 r.in.new_lm_crypted = &hash2;
1779 /* Break the LM hash */
1780 hash1.hash[0]--;
1781 r.in.nt_present = 1;
1782 r.in.old_nt_crypted = &hash3;
1783 r.in.new_nt_crypted = &hash4;
1784 r.in.cross1_present = 1;
1785 r.in.nt_cross = &hash5;
1786 r.in.cross2_present = 1;
1787 r.in.lm_cross = &hash6;
1789 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1790 "ChangePasswordUser failed");
1791 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1792 __location__, __FUNCTION__,
1793 oldpass, newpass, nt_errstr(r.out.result));
1794 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1795 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1796 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1799 /* Unbreak the NT hash */
1800 hash3.hash[0]--;
1802 r.in.user_handle = &user_handle;
1803 r.in.lm_present = 1;
1804 r.in.old_lm_crypted = &hash1;
1805 r.in.new_lm_crypted = &hash2;
1806 r.in.nt_present = 1;
1807 r.in.old_nt_crypted = &hash3;
1808 r.in.new_nt_crypted = &hash4;
1809 r.in.cross1_present = 1;
1810 r.in.nt_cross = &hash5;
1811 r.in.cross2_present = 1;
1812 /* Break the LM cross */
1813 hash6.hash[0]++;
1814 r.in.lm_cross = &hash6;
1816 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1817 "ChangePasswordUser failed");
1818 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1819 __location__, __FUNCTION__,
1820 oldpass, newpass, nt_errstr(r.out.result));
1821 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1822 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1824 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
1825 ret = false;
1828 /* Unbreak the LM cross */
1829 hash6.hash[0]--;
1831 r.in.user_handle = &user_handle;
1832 r.in.lm_present = 1;
1833 r.in.old_lm_crypted = &hash1;
1834 r.in.new_lm_crypted = &hash2;
1835 r.in.nt_present = 1;
1836 r.in.old_nt_crypted = &hash3;
1837 r.in.new_nt_crypted = &hash4;
1838 r.in.cross1_present = 1;
1839 /* Break the NT cross */
1840 hash5.hash[0]++;
1841 r.in.nt_cross = &hash5;
1842 r.in.cross2_present = 1;
1843 r.in.lm_cross = &hash6;
1845 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1846 "ChangePasswordUser failed");
1847 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1848 __location__, __FUNCTION__,
1849 oldpass, newpass, nt_errstr(r.out.result));
1850 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1851 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1853 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
1854 ret = false;
1857 /* Unbreak the NT cross */
1858 hash5.hash[0]--;
1861 /* Reset the hashes to not broken values */
1862 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1863 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1864 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1865 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1866 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1867 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1869 r.in.user_handle = &user_handle;
1870 r.in.lm_present = 1;
1871 r.in.old_lm_crypted = &hash1;
1872 r.in.new_lm_crypted = &hash2;
1873 r.in.nt_present = 1;
1874 r.in.old_nt_crypted = &hash3;
1875 r.in.new_nt_crypted = &hash4;
1876 r.in.cross1_present = 1;
1877 r.in.nt_cross = &hash5;
1878 r.in.cross2_present = 0;
1879 r.in.lm_cross = NULL;
1881 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1882 "ChangePasswordUser failed");
1883 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1884 __location__, __FUNCTION__,
1885 oldpass, newpass, nt_errstr(r.out.result));
1886 if (NT_STATUS_IS_OK(r.out.result)) {
1887 changed = true;
1888 *password = newpass;
1889 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1890 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1891 ret = false;
1894 oldpass = newpass;
1895 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1897 E_md4hash(oldpass, old_nt_hash);
1898 E_md4hash(newpass, new_nt_hash);
1899 E_deshash(oldpass, old_lm_hash);
1900 E_deshash(newpass, new_lm_hash);
1903 /* Reset the hashes to not broken values */
1904 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1905 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1906 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1907 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1908 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1909 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1911 r.in.user_handle = &user_handle;
1912 r.in.lm_present = 1;
1913 r.in.old_lm_crypted = &hash1;
1914 r.in.new_lm_crypted = &hash2;
1915 r.in.nt_present = 1;
1916 r.in.old_nt_crypted = &hash3;
1917 r.in.new_nt_crypted = &hash4;
1918 r.in.cross1_present = 0;
1919 r.in.nt_cross = NULL;
1920 r.in.cross2_present = 1;
1921 r.in.lm_cross = &hash6;
1923 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1924 "ChangePasswordUser failed");
1925 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1926 __location__, __FUNCTION__,
1927 oldpass, newpass, nt_errstr(r.out.result));
1928 if (NT_STATUS_IS_OK(r.out.result)) {
1929 changed = true;
1930 *password = newpass;
1931 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1932 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1933 ret = false;
1936 oldpass = newpass;
1937 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1939 E_md4hash(oldpass, old_nt_hash);
1940 E_md4hash(newpass, new_nt_hash);
1941 E_deshash(oldpass, old_lm_hash);
1942 E_deshash(newpass, new_lm_hash);
1945 /* Reset the hashes to not broken values */
1946 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1947 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1948 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1949 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1950 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1951 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1953 r.in.user_handle = &user_handle;
1954 r.in.lm_present = 1;
1955 r.in.old_lm_crypted = &hash1;
1956 r.in.new_lm_crypted = &hash2;
1957 r.in.nt_present = 1;
1958 r.in.old_nt_crypted = &hash3;
1959 r.in.new_nt_crypted = &hash4;
1960 r.in.cross1_present = 1;
1961 r.in.nt_cross = &hash5;
1962 r.in.cross2_present = 1;
1963 r.in.lm_cross = &hash6;
1965 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1966 "ChangePasswordUser failed");
1967 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1968 __location__, __FUNCTION__,
1969 oldpass, newpass, nt_errstr(r.out.result));
1970 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1971 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1972 } else if (!NT_STATUS_IS_OK(r.out.result)) {
1973 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1974 ret = false;
1975 } else {
1976 changed = true;
1977 *password = newpass;
1980 r.in.user_handle = &user_handle;
1981 r.in.lm_present = 1;
1982 r.in.old_lm_crypted = &hash1;
1983 r.in.new_lm_crypted = &hash2;
1984 r.in.nt_present = 1;
1985 r.in.old_nt_crypted = &hash3;
1986 r.in.new_nt_crypted = &hash4;
1987 r.in.cross1_present = 1;
1988 r.in.nt_cross = &hash5;
1989 r.in.cross2_present = 1;
1990 r.in.lm_cross = &hash6;
1992 if (changed) {
1993 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1994 "ChangePasswordUser failed");
1995 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1996 __location__, __FUNCTION__,
1997 oldpass, newpass, nt_errstr(r.out.result));
1998 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1999 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2000 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2001 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
2002 ret = false;
2007 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
2008 ret = false;
2011 return ret;
2015 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
2016 struct torture_context *tctx,
2017 const char *acct_name,
2018 struct policy_handle *handle, char **password)
2020 struct samr_OemChangePasswordUser2 r;
2021 bool ret = true;
2022 struct samr_Password lm_verifier;
2023 struct samr_CryptPassword lm_pass;
2024 struct lsa_AsciiString server, account, account_bad;
2025 char *oldpass;
2026 char *newpass;
2027 struct dcerpc_binding_handle *b = p->binding_handle;
2028 uint8_t old_lm_hash[16], new_lm_hash[16];
2030 struct samr_GetDomPwInfo dom_pw_info;
2031 struct samr_PwInfo info;
2032 int policy_min_pw_len = 0;
2034 struct lsa_String domain_name;
2036 domain_name.string = "";
2037 dom_pw_info.in.domain_name = &domain_name;
2038 dom_pw_info.out.info = &info;
2040 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
2042 torture_assert(tctx, *password != NULL,
2043 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
2045 oldpass = *password;
2047 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2048 "GetDomPwInfo failed");
2049 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2050 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2053 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2055 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2056 account.string = acct_name;
2058 E_deshash(oldpass, old_lm_hash);
2059 E_deshash(newpass, new_lm_hash);
2061 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2062 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2063 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2065 r.in.server = &server;
2066 r.in.account = &account;
2067 r.in.password = &lm_pass;
2068 r.in.hash = &lm_verifier;
2070 /* Break the verification */
2071 lm_verifier.hash[0]++;
2073 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2074 "OemChangePasswordUser2 failed");
2075 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2076 __location__, __FUNCTION__,
2077 oldpass, newpass, nt_errstr(r.out.result));
2079 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2080 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2081 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2082 nt_errstr(r.out.result));
2083 ret = false;
2086 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2087 /* Break the old password */
2088 old_lm_hash[0]++;
2089 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2090 /* unbreak it for the next operation */
2091 old_lm_hash[0]--;
2092 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2094 r.in.server = &server;
2095 r.in.account = &account;
2096 r.in.password = &lm_pass;
2097 r.in.hash = &lm_verifier;
2099 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2100 "OemChangePasswordUser2 failed");
2101 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2102 __location__, __FUNCTION__,
2103 oldpass, newpass, nt_errstr(r.out.result));
2105 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2106 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2107 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2108 nt_errstr(r.out.result));
2109 ret = false;
2112 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2113 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2115 r.in.server = &server;
2116 r.in.account = &account;
2117 r.in.password = &lm_pass;
2118 r.in.hash = NULL;
2120 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2121 "OemChangePasswordUser2 failed");
2122 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2123 __location__, __FUNCTION__,
2124 oldpass, newpass, nt_errstr(r.out.result));
2126 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2127 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2128 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2129 nt_errstr(r.out.result));
2130 ret = false;
2133 /* This shouldn't be a valid name */
2134 account_bad.string = TEST_ACCOUNT_NAME "XX";
2135 r.in.account = &account_bad;
2137 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2138 "OemChangePasswordUser2 failed");
2139 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2140 __location__, __FUNCTION__,
2141 oldpass, newpass, nt_errstr(r.out.result));
2143 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2144 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2145 nt_errstr(r.out.result));
2146 ret = false;
2149 /* This shouldn't be a valid name */
2150 account_bad.string = TEST_ACCOUNT_NAME "XX";
2151 r.in.account = &account_bad;
2152 r.in.password = &lm_pass;
2153 r.in.hash = &lm_verifier;
2155 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2156 "OemChangePasswordUser2 failed");
2157 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2158 __location__, __FUNCTION__,
2159 oldpass, newpass, nt_errstr(r.out.result));
2161 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2162 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2163 nt_errstr(r.out.result));
2164 ret = false;
2167 /* This shouldn't be a valid name */
2168 account_bad.string = TEST_ACCOUNT_NAME "XX";
2169 r.in.account = &account_bad;
2170 r.in.password = NULL;
2171 r.in.hash = &lm_verifier;
2173 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2174 "OemChangePasswordUser2 failed");
2175 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2176 __location__, __FUNCTION__,
2177 oldpass, newpass, nt_errstr(r.out.result));
2179 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2180 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2181 nt_errstr(r.out.result));
2182 ret = false;
2185 E_deshash(oldpass, old_lm_hash);
2186 E_deshash(newpass, new_lm_hash);
2188 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2189 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2190 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2192 r.in.server = &server;
2193 r.in.account = &account;
2194 r.in.password = &lm_pass;
2195 r.in.hash = &lm_verifier;
2197 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2198 "OemChangePasswordUser2 failed");
2199 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2200 __location__, __FUNCTION__,
2201 oldpass, newpass, nt_errstr(r.out.result));
2203 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2204 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2205 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2206 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2207 ret = false;
2208 } else {
2209 *password = newpass;
2212 return ret;
2216 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2217 const char *acct_name,
2218 char **password,
2219 char *newpass, bool allow_password_restriction)
2221 struct samr_ChangePasswordUser2 r;
2222 bool ret = true;
2223 struct lsa_String server, account;
2224 struct samr_CryptPassword nt_pass, lm_pass;
2225 struct samr_Password nt_verifier, lm_verifier;
2226 char *oldpass;
2227 struct dcerpc_binding_handle *b = p->binding_handle;
2228 uint8_t old_nt_hash[16], new_nt_hash[16];
2229 uint8_t old_lm_hash[16], new_lm_hash[16];
2231 struct samr_GetDomPwInfo dom_pw_info;
2232 struct samr_PwInfo info;
2234 struct lsa_String domain_name;
2236 domain_name.string = "";
2237 dom_pw_info.in.domain_name = &domain_name;
2238 dom_pw_info.out.info = &info;
2240 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2242 torture_assert(tctx, *password != NULL,
2243 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2244 oldpass = *password;
2246 if (!newpass) {
2247 int policy_min_pw_len = 0;
2248 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2249 "GetDomPwInfo failed");
2250 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2251 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2254 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2257 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2258 init_lsa_String(&account, acct_name);
2260 E_md4hash(oldpass, old_nt_hash);
2261 E_md4hash(newpass, new_nt_hash);
2263 E_deshash(oldpass, old_lm_hash);
2264 E_deshash(newpass, new_lm_hash);
2266 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2267 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2268 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2270 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2271 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2272 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2274 r.in.server = &server;
2275 r.in.account = &account;
2276 r.in.nt_password = &nt_pass;
2277 r.in.nt_verifier = &nt_verifier;
2278 r.in.lm_change = 1;
2279 r.in.lm_password = &lm_pass;
2280 r.in.lm_verifier = &lm_verifier;
2282 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2283 "ChangePasswordUser2 failed");
2284 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2285 __location__, __FUNCTION__,
2286 oldpass, newpass, nt_errstr(r.out.result));
2288 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2289 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2290 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2291 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2292 ret = false;
2293 } else {
2294 *password = newpass;
2297 return ret;
2301 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2302 const char *account_string,
2303 int policy_min_pw_len,
2304 char **password,
2305 const char *newpass,
2306 NTTIME last_password_change,
2307 bool handle_reject_reason)
2309 struct samr_ChangePasswordUser3 r;
2310 bool ret = true;
2311 struct lsa_String server, account, account_bad;
2312 struct samr_CryptPassword nt_pass, lm_pass;
2313 struct samr_Password nt_verifier, lm_verifier;
2314 char *oldpass;
2315 struct dcerpc_binding_handle *b = p->binding_handle;
2316 uint8_t old_nt_hash[16], new_nt_hash[16];
2317 uint8_t old_lm_hash[16], new_lm_hash[16];
2318 NTTIME t;
2319 struct samr_DomInfo1 *dominfo = NULL;
2320 struct userPwdChangeFailureInformation *reject = NULL;
2322 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2324 if (newpass == NULL) {
2325 do {
2326 if (policy_min_pw_len == 0) {
2327 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2328 } else {
2329 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2331 } while (check_password_quality(newpass) == false);
2332 } else {
2333 torture_comment(tctx, "Using password '%s'\n", newpass);
2336 torture_assert(tctx, *password != NULL,
2337 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2339 oldpass = *password;
2340 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2341 init_lsa_String(&account, account_string);
2343 E_md4hash(oldpass, old_nt_hash);
2344 E_md4hash(newpass, new_nt_hash);
2346 E_deshash(oldpass, old_lm_hash);
2347 E_deshash(newpass, new_lm_hash);
2349 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2350 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2351 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2353 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2354 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2355 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2357 /* Break the verification */
2358 nt_verifier.hash[0]++;
2360 r.in.server = &server;
2361 r.in.account = &account;
2362 r.in.nt_password = &nt_pass;
2363 r.in.nt_verifier = &nt_verifier;
2364 r.in.lm_change = 1;
2365 r.in.lm_password = &lm_pass;
2366 r.in.lm_verifier = &lm_verifier;
2367 r.in.password3 = NULL;
2368 r.out.dominfo = &dominfo;
2369 r.out.reject = &reject;
2371 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2372 "ChangePasswordUser3 failed");
2373 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2374 __location__, __FUNCTION__,
2375 oldpass, newpass, nt_errstr(r.out.result));
2376 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2377 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2378 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2379 nt_errstr(r.out.result));
2380 ret = false;
2383 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2384 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2385 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2387 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2388 /* Break the NT hash */
2389 old_nt_hash[0]++;
2390 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2391 /* Unbreak it again */
2392 old_nt_hash[0]--;
2393 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2395 r.in.server = &server;
2396 r.in.account = &account;
2397 r.in.nt_password = &nt_pass;
2398 r.in.nt_verifier = &nt_verifier;
2399 r.in.lm_change = 1;
2400 r.in.lm_password = &lm_pass;
2401 r.in.lm_verifier = &lm_verifier;
2402 r.in.password3 = NULL;
2403 r.out.dominfo = &dominfo;
2404 r.out.reject = &reject;
2406 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2407 "ChangePasswordUser3 failed");
2408 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2409 __location__, __FUNCTION__,
2410 oldpass, newpass, nt_errstr(r.out.result));
2411 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2412 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2413 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2414 nt_errstr(r.out.result));
2415 ret = false;
2418 /* This shouldn't be a valid name */
2419 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2421 r.in.account = &account_bad;
2422 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2423 "ChangePasswordUser3 failed");
2424 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2425 __location__, __FUNCTION__,
2426 oldpass, newpass, nt_errstr(r.out.result));
2427 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2428 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2429 nt_errstr(r.out.result));
2430 ret = false;
2433 E_md4hash(oldpass, old_nt_hash);
2434 E_md4hash(newpass, new_nt_hash);
2436 E_deshash(oldpass, old_lm_hash);
2437 E_deshash(newpass, new_lm_hash);
2439 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2440 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2441 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2443 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2444 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2445 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2447 r.in.server = &server;
2448 r.in.account = &account;
2449 r.in.nt_password = &nt_pass;
2450 r.in.nt_verifier = &nt_verifier;
2451 r.in.lm_change = 1;
2452 r.in.lm_password = &lm_pass;
2453 r.in.lm_verifier = &lm_verifier;
2454 r.in.password3 = NULL;
2455 r.out.dominfo = &dominfo;
2456 r.out.reject = &reject;
2458 unix_to_nt_time(&t, time(NULL));
2460 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2461 "ChangePasswordUser3 failed");
2462 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2463 __location__, __FUNCTION__,
2464 oldpass, newpass, nt_errstr(r.out.result));
2466 torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2467 "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2468 __location__,
2469 (dominfo == NULL)? "NULL" : "present",
2470 reject ? "true" : "false",
2471 handle_reject_reason ? "true" : "false",
2472 null_nttime(last_password_change) ? "null" : "not null",
2473 dominfo ? (long long)dominfo->min_password_age : (long long)0);
2475 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2476 && dominfo
2477 && reject
2478 && handle_reject_reason
2479 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2480 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2482 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2483 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2484 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2485 return false;
2489 /* We tested the order of precendence which is as follows:
2491 * pwd min_age
2492 * pwd length
2493 * pwd complexity
2494 * pwd history
2496 Guenther */
2498 if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
2499 (last_password_change - dominfo->min_password_age > t)) {
2501 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2502 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2503 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2504 return false;
2507 } else if ((dominfo->min_password_length > 0) &&
2508 (strlen(newpass) < dominfo->min_password_length)) {
2510 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2511 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2512 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2513 return false;
2516 } else if ((dominfo->password_history_length > 0) &&
2517 strequal(oldpass, newpass)) {
2519 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2520 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2521 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2522 return false;
2524 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2526 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2527 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2528 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2529 return false;
2534 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2535 /* retry with adjusted size */
2536 return test_ChangePasswordUser3(p, tctx, account_string,
2537 dominfo->min_password_length,
2538 password, NULL, 0, false);
2542 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2543 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2544 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2545 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2546 return false;
2548 /* Perhaps the server has a 'min password age' set? */
2550 } else {
2551 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2553 *password = talloc_strdup(tctx, newpass);
2556 return ret;
2559 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2560 const char *account_string,
2561 struct policy_handle *handle,
2562 char **password)
2564 NTSTATUS status;
2565 struct samr_ChangePasswordUser3 r;
2566 struct samr_SetUserInfo s;
2567 union samr_UserInfo u;
2568 DATA_BLOB session_key;
2569 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2570 uint8_t confounder[16];
2571 MD5_CTX ctx;
2573 bool ret = true;
2574 struct lsa_String server, account;
2575 struct samr_CryptPassword nt_pass;
2576 struct samr_Password nt_verifier;
2577 DATA_BLOB new_random_pass;
2578 char *newpass;
2579 char *oldpass;
2580 struct dcerpc_binding_handle *b = p->binding_handle;
2581 uint8_t old_nt_hash[16], new_nt_hash[16];
2582 NTTIME t;
2583 struct samr_DomInfo1 *dominfo = NULL;
2584 struct userPwdChangeFailureInformation *reject = NULL;
2586 new_random_pass = samr_very_rand_pass(tctx, 128);
2588 torture_assert(tctx, *password != NULL,
2589 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2591 oldpass = *password;
2592 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2593 init_lsa_String(&account, account_string);
2595 s.in.user_handle = handle;
2596 s.in.info = &u;
2597 s.in.level = 25;
2599 ZERO_STRUCT(u);
2601 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2603 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2605 status = dcerpc_fetch_session_key(p, &session_key);
2606 if (!NT_STATUS_IS_OK(status)) {
2607 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
2608 s.in.level, nt_errstr(status));
2609 return false;
2612 generate_random_buffer((uint8_t *)confounder, 16);
2614 MD5Init(&ctx);
2615 MD5Update(&ctx, confounder, 16);
2616 MD5Update(&ctx, session_key.data, session_key.length);
2617 MD5Final(confounded_session_key.data, &ctx);
2619 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2620 memcpy(&u.info25.password.data[516], confounder, 16);
2622 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2624 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2625 "SetUserInfo failed");
2626 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2627 __location__, __FUNCTION__,
2628 oldpass, "RANDOM", nt_errstr(s.out.result));
2629 if (!NT_STATUS_IS_OK(s.out.result)) {
2630 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
2631 s.in.level, nt_errstr(s.out.result));
2632 ret = false;
2635 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2637 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2639 new_random_pass = samr_very_rand_pass(tctx, 128);
2641 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2643 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2644 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2645 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2647 r.in.server = &server;
2648 r.in.account = &account;
2649 r.in.nt_password = &nt_pass;
2650 r.in.nt_verifier = &nt_verifier;
2651 r.in.lm_change = 0;
2652 r.in.lm_password = NULL;
2653 r.in.lm_verifier = NULL;
2654 r.in.password3 = NULL;
2655 r.out.dominfo = &dominfo;
2656 r.out.reject = &reject;
2658 unix_to_nt_time(&t, time(NULL));
2660 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2661 "ChangePasswordUser3 failed");
2662 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2663 __location__, __FUNCTION__,
2664 oldpass, "RANDOM", nt_errstr(r.out.result));
2666 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2667 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2668 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2669 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2670 return false;
2672 /* Perhaps the server has a 'min password age' set? */
2674 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2675 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2676 ret = false;
2679 newpass = samr_rand_pass(tctx, 128);
2681 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2683 E_md4hash(newpass, new_nt_hash);
2685 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2686 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2687 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2689 r.in.server = &server;
2690 r.in.account = &account;
2691 r.in.nt_password = &nt_pass;
2692 r.in.nt_verifier = &nt_verifier;
2693 r.in.lm_change = 0;
2694 r.in.lm_password = NULL;
2695 r.in.lm_verifier = NULL;
2696 r.in.password3 = NULL;
2697 r.out.dominfo = &dominfo;
2698 r.out.reject = &reject;
2700 unix_to_nt_time(&t, time(NULL));
2702 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2703 "ChangePasswordUser3 failed");
2704 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2705 __location__, __FUNCTION__,
2706 oldpass, newpass, nt_errstr(r.out.result));
2708 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2709 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2710 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2711 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2712 return false;
2714 /* Perhaps the server has a 'min password age' set? */
2716 } else {
2717 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2718 *password = talloc_strdup(tctx, newpass);
2721 return ret;
2725 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2726 struct torture_context *tctx,
2727 struct policy_handle *alias_handle)
2729 struct samr_GetMembersInAlias r;
2730 struct lsa_SidArray sids;
2732 torture_comment(tctx, "Testing GetMembersInAlias\n");
2734 r.in.alias_handle = alias_handle;
2735 r.out.sids = &sids;
2737 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2738 "GetMembersInAlias failed");
2739 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2741 return true;
2744 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2745 struct torture_context *tctx,
2746 struct policy_handle *alias_handle,
2747 const struct dom_sid *domain_sid)
2749 struct samr_AddAliasMember r;
2750 struct samr_DeleteAliasMember d;
2751 struct dom_sid *sid;
2753 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2755 torture_comment(tctx, "Testing AddAliasMember\n");
2756 r.in.alias_handle = alias_handle;
2757 r.in.sid = sid;
2759 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2760 "AddAliasMember failed");
2761 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2763 d.in.alias_handle = alias_handle;
2764 d.in.sid = sid;
2766 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2767 "DeleteAliasMember failed");
2768 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2770 return true;
2773 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2774 struct torture_context *tctx,
2775 struct policy_handle *alias_handle)
2777 struct samr_AddMultipleMembersToAlias a;
2778 struct samr_RemoveMultipleMembersFromAlias r;
2779 struct lsa_SidArray sids;
2781 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2782 a.in.alias_handle = alias_handle;
2783 a.in.sids = &sids;
2785 sids.num_sids = 3;
2786 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2788 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2789 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2790 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2792 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2793 "AddMultipleMembersToAlias failed");
2794 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2797 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2798 r.in.alias_handle = alias_handle;
2799 r.in.sids = &sids;
2801 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2802 "RemoveMultipleMembersFromAlias failed");
2803 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2805 /* strange! removing twice doesn't give any error */
2806 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2807 "RemoveMultipleMembersFromAlias failed");
2808 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2810 /* but removing an alias that isn't there does */
2811 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2813 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2814 "RemoveMultipleMembersFromAlias failed");
2815 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2817 return true;
2820 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2821 struct torture_context *tctx,
2822 struct policy_handle *domain_handle)
2824 struct samr_GetAliasMembership r;
2825 struct lsa_SidArray sids;
2826 struct samr_Ids rids;
2828 torture_comment(tctx, "Testing GetAliasMembership\n");
2830 r.in.domain_handle = domain_handle;
2831 r.in.sids = &sids;
2832 r.out.rids = &rids;
2834 sids.num_sids = 0;
2835 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2837 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2838 "GetAliasMembership failed");
2839 torture_assert_ntstatus_ok(tctx, r.out.result,
2840 "samr_GetAliasMembership failed");
2842 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2843 "protocol misbehaviour");
2845 sids.num_sids = 1;
2846 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2847 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2849 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2850 "samr_GetAliasMembership failed");
2851 torture_assert_ntstatus_ok(tctx, r.out.result,
2852 "samr_GetAliasMembership failed");
2854 #if 0
2855 /* only true for w2k8 it seems
2856 * win7, xp, w2k3 will return a 0 length array pointer */
2858 if (rids.ids && (rids.count == 0)) {
2859 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2861 #endif
2862 if (!rids.ids && rids.count) {
2863 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2866 return true;
2869 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2870 struct torture_context *tctx,
2871 struct policy_handle *user_handle)
2873 struct samr_TestPrivateFunctionsUser r;
2875 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2877 r.in.user_handle = user_handle;
2879 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2880 "TestPrivateFunctionsUser failed");
2881 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2883 return true;
2886 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2887 struct torture_context *tctx,
2888 struct policy_handle *handle,
2889 bool use_info2,
2890 NTTIME *pwdlastset)
2892 NTSTATUS status;
2893 uint16_t levels[] = { /* 3, */ 5, 21 };
2894 int i;
2895 NTTIME pwdlastset3 = 0;
2896 NTTIME pwdlastset5 = 0;
2897 NTTIME pwdlastset21 = 0;
2899 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2900 use_info2 ? "2":"");
2902 for (i=0; i<ARRAY_SIZE(levels); i++) {
2904 struct samr_QueryUserInfo r;
2905 struct samr_QueryUserInfo2 r2;
2906 union samr_UserInfo *info;
2908 if (use_info2) {
2909 r2.in.user_handle = handle;
2910 r2.in.level = levels[i];
2911 r2.out.info = &info;
2912 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2913 "QueryUserInfo2 failed");
2914 status = r2.out.result;
2916 } else {
2917 r.in.user_handle = handle;
2918 r.in.level = levels[i];
2919 r.out.info = &info;
2920 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2921 "QueryUserInfo failed");
2922 status = r.out.result;
2925 if (!NT_STATUS_IS_OK(status) &&
2926 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2927 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo%s level %u failed - %s\n",
2928 use_info2 ? "2":"", levels[i], nt_errstr(status));
2929 return false;
2932 switch (levels[i]) {
2933 case 3:
2934 pwdlastset3 = info->info3.last_password_change;
2935 break;
2936 case 5:
2937 pwdlastset5 = info->info5.last_password_change;
2938 break;
2939 case 21:
2940 pwdlastset21 = info->info21.last_password_change;
2941 break;
2942 default:
2943 return false;
2946 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2947 "pwdlastset mixup"); */
2948 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2949 "pwdlastset mixup");
2951 *pwdlastset = pwdlastset21;
2953 torture_comment(tctx, "(pwdlastset: %llu)\n",
2954 (unsigned long long) *pwdlastset);
2956 return true;
2959 static bool test_SamLogon(struct torture_context *tctx,
2960 struct dcerpc_pipe *p,
2961 struct cli_credentials *machine_credentials,
2962 struct cli_credentials *test_credentials,
2963 NTSTATUS expected_result,
2964 bool interactive)
2966 NTSTATUS status;
2967 struct netr_LogonSamLogonEx r;
2968 union netr_LogonLevel logon;
2969 union netr_Validation validation;
2970 uint8_t authoritative;
2971 struct netr_IdentityInfo identity;
2972 struct netr_NetworkInfo ninfo;
2973 struct netr_PasswordInfo pinfo;
2974 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2975 int flags = CLI_CRED_NTLM_AUTH;
2976 uint32_t samlogon_flags = 0;
2977 struct netlogon_creds_CredentialState *creds;
2978 struct netr_Authenticator a;
2979 struct dcerpc_binding_handle *b = p->binding_handle;
2981 torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), "");
2983 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
2984 flags |= CLI_CRED_LANMAN_AUTH;
2987 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
2988 flags |= CLI_CRED_NTLMv2_AUTH;
2991 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2992 &identity.account_name.string,
2993 &identity.domain_name.string);
2995 identity.parameter_control =
2996 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2997 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2998 identity.logon_id_low = 0;
2999 identity.logon_id_high = 0;
3000 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
3002 if (interactive) {
3003 netlogon_creds_client_authenticator(creds, &a);
3005 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
3006 ZERO_STRUCT(pinfo.lmpassword.hash);
3008 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
3010 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3011 netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
3012 netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
3013 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
3014 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
3015 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
3016 } else {
3017 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
3018 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
3021 pinfo.identity_info = identity;
3022 logon.password = &pinfo;
3024 r.in.logon_level = NetlogonInteractiveInformation;
3025 } else {
3026 generate_random_buffer(ninfo.challenge,
3027 sizeof(ninfo.challenge));
3028 chal = data_blob_const(ninfo.challenge,
3029 sizeof(ninfo.challenge));
3031 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3032 cli_credentials_get_domain(test_credentials));
3034 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3035 &flags,
3036 chal,
3037 names_blob,
3038 &lm_resp, &nt_resp,
3039 NULL, NULL);
3040 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3042 ninfo.lm.data = lm_resp.data;
3043 ninfo.lm.length = lm_resp.length;
3045 ninfo.nt.data = nt_resp.data;
3046 ninfo.nt.length = nt_resp.length;
3048 ninfo.identity_info = identity;
3049 logon.network = &ninfo;
3051 r.in.logon_level = NetlogonNetworkInformation;
3054 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3055 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3056 r.in.logon = &logon;
3057 r.in.flags = &samlogon_flags;
3058 r.out.flags = &samlogon_flags;
3059 r.out.validation = &validation;
3060 r.out.authoritative = &authoritative;
3062 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3064 r.in.validation_level = 6;
3066 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3067 "netr_LogonSamLogonEx failed");
3068 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3069 r.in.validation_level = 3;
3070 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3071 "netr_LogonSamLogonEx failed");
3073 if (!NT_STATUS_IS_OK(r.out.result)) {
3074 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3075 return true;
3076 } else {
3077 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3080 return true;
3083 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3084 struct dcerpc_pipe *p,
3085 struct cli_credentials *machine_creds,
3086 const char *acct_name,
3087 const char *password,
3088 NTSTATUS expected_samlogon_result,
3089 bool interactive)
3091 bool ret = true;
3092 struct cli_credentials *test_credentials;
3094 test_credentials = cli_credentials_init(tctx);
3096 cli_credentials_set_workstation(test_credentials,
3097 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3098 cli_credentials_set_domain(test_credentials,
3099 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3100 cli_credentials_set_username(test_credentials,
3101 acct_name, CRED_SPECIFIED);
3102 cli_credentials_set_password(test_credentials,
3103 password, CRED_SPECIFIED);
3105 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3106 interactive ? "interactive" : "network", acct_name, password);
3108 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
3109 expected_samlogon_result, interactive)) {
3110 torture_result(tctx, TORTURE_FAIL, "new password did not work\n");
3111 ret = false;
3114 return ret;
3117 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3118 struct dcerpc_pipe *np,
3119 struct torture_context *tctx,
3120 struct policy_handle *handle,
3121 uint16_t level,
3122 uint32_t fields_present,
3123 uint8_t password_expired,
3124 bool *matched_expected_error,
3125 bool use_setinfo2,
3126 const char *acct_name,
3127 char **password,
3128 struct cli_credentials *machine_creds,
3129 bool use_queryinfo2,
3130 NTTIME *pwdlastset,
3131 NTSTATUS expected_samlogon_result)
3133 const char *fields = NULL;
3134 bool ret = true;
3135 struct dcerpc_binding_handle *b = p->binding_handle;
3137 switch (level) {
3138 case 21:
3139 case 23:
3140 case 25:
3141 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3142 fields_present);
3143 break;
3144 default:
3145 break;
3148 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3149 "(password_expired: %d) %s\n",
3150 use_setinfo2 ? "2":"", level, password_expired,
3151 fields ? fields : "");
3153 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3154 fields_present,
3155 password,
3156 password_expired,
3157 use_setinfo2,
3158 matched_expected_error)) {
3159 ret = false;
3162 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3163 use_queryinfo2,
3164 pwdlastset)) {
3165 ret = false;
3168 if (*matched_expected_error == true) {
3169 return ret;
3172 if (!test_SamLogon_with_creds(tctx, np,
3173 machine_creds,
3174 acct_name,
3175 *password,
3176 expected_samlogon_result,
3177 false)) {
3178 ret = false;
3181 return ret;
3184 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3185 struct cli_credentials *credentials,
3186 struct dcerpc_pipe **p)
3188 struct dcerpc_binding *b;
3189 NTSTATUS status;
3191 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3192 "failed to get rpc binding");
3194 /* We have to use schannel, otherwise the SamLogonEx fails
3195 * with INTERNAL_ERROR */
3197 status = dcerpc_binding_set_flags(b,
3198 DCERPC_SCHANNEL | DCERPC_SIGN |
3199 DCERPC_SCHANNEL_AUTO,
3200 DCERPC_AUTH_OPTIONS);
3201 torture_assert_ntstatus_ok(tctx, status, "set flags");
3203 torture_assert_ntstatus_ok(tctx,
3204 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3205 credentials, tctx->ev, tctx->lp_ctx),
3206 "failed to bind to netlogon");
3208 return true;
3211 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3212 struct torture_context *tctx,
3213 uint32_t acct_flags,
3214 const char *acct_name,
3215 struct policy_handle *handle,
3216 char **password,
3217 struct cli_credentials *machine_credentials)
3219 int s = 0, q = 0, f = 0, l = 0, z = 0;
3220 bool ret = true;
3221 int delay = 50000;
3222 bool set_levels[] = { false, true };
3223 bool query_levels[] = { false, true };
3224 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3225 uint32_t nonzeros[] = { 1, 24 };
3226 uint32_t fields_present[] = {
3228 SAMR_FIELD_EXPIRED_FLAG,
3229 SAMR_FIELD_LAST_PWD_CHANGE,
3230 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3231 SAMR_FIELD_COMMENT,
3232 SAMR_FIELD_NT_PASSWORD_PRESENT,
3233 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3234 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3235 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3236 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3237 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3238 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3240 struct dcerpc_pipe *np = NULL;
3242 if (torture_setting_bool(tctx, "samba3", false) ||
3243 torture_setting_bool(tctx, "samba4", false)) {
3244 delay = 999999;
3245 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3246 delay);
3249 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3251 /* set to 1 to enable testing for all possible opcode
3252 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3253 combinations */
3254 #if 0
3255 #define TEST_ALL_LEVELS 1
3256 #define TEST_SET_LEVELS 1
3257 #define TEST_QUERY_LEVELS 1
3258 #endif
3259 #ifdef TEST_ALL_LEVELS
3260 for (l=0; l<ARRAY_SIZE(levels); l++) {
3261 #else
3262 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3263 #endif
3264 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3265 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3266 #ifdef TEST_SET_LEVELS
3267 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3268 #endif
3269 #ifdef TEST_QUERY_LEVELS
3270 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3271 #endif
3272 NTTIME pwdlastset_old = 0;
3273 NTTIME pwdlastset_new = 0;
3274 bool matched_expected_error = false;
3275 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3277 torture_comment(tctx, "------------------------------\n"
3278 "Testing pwdLastSet attribute for flags: 0x%08x "
3279 "(s: %d (l: %d), q: %d)\n",
3280 acct_flags, s, levels[l], q);
3282 switch (levels[l]) {
3283 case 21:
3284 case 23:
3285 case 25:
3286 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3287 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3288 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3290 break;
3294 /* set #1 */
3296 /* set a password and force password change (pwdlastset 0) by
3297 * setting the password expired flag to a non-0 value */
3299 if (!test_SetPassword_level(p, np, tctx, handle,
3300 levels[l],
3301 fields_present[f],
3302 nonzeros[z],
3303 &matched_expected_error,
3304 set_levels[s],
3305 acct_name,
3306 password,
3307 machine_credentials,
3308 query_levels[q],
3309 &pwdlastset_new,
3310 expected_samlogon_result)) {
3311 ret = false;
3314 if (matched_expected_error == true) {
3315 /* skipping on expected failure */
3316 continue;
3319 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3320 * set without the SAMR_FIELD_EXPIRED_FLAG */
3322 switch (levels[l]) {
3323 case 21:
3324 case 23:
3325 case 25:
3326 if ((pwdlastset_new != 0) &&
3327 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3328 torture_comment(tctx, "not considering a non-0 "
3329 "pwdLastSet as a an error as the "
3330 "SAMR_FIELD_EXPIRED_FLAG has not "
3331 "been set\n");
3332 break;
3334 break;
3335 default:
3336 if (pwdlastset_new != 0) {
3337 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3338 "expected pwdLastSet 0 but got %llu\n",
3339 (unsigned long long) pwdlastset_old);
3340 ret = false;
3342 break;
3345 switch (levels[l]) {
3346 case 21:
3347 case 23:
3348 case 25:
3349 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3350 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3351 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3352 (pwdlastset_old >= pwdlastset_new)) {
3353 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3354 ret = false;
3356 break;
3359 pwdlastset_old = pwdlastset_new;
3361 usleep(delay);
3363 /* set #2 */
3365 /* set a password, pwdlastset needs to get updated (increased
3366 * value), password_expired value used here is 0 */
3368 if (!test_SetPassword_level(p, np, tctx, handle,
3369 levels[l],
3370 fields_present[f],
3372 &matched_expected_error,
3373 set_levels[s],
3374 acct_name,
3375 password,
3376 machine_credentials,
3377 query_levels[q],
3378 &pwdlastset_new,
3379 expected_samlogon_result)) {
3380 ret = false;
3383 /* when a password has been changed, pwdlastset must not be 0 afterwards
3384 * and must be larger then the old value */
3386 switch (levels[l]) {
3387 case 21:
3388 case 23:
3389 case 25:
3390 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3391 * password has been changed, old and new pwdlastset
3392 * need to be the same value */
3394 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3395 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3396 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3398 torture_assert_int_equal(tctx, pwdlastset_old,
3399 pwdlastset_new, "pwdlastset must be equal");
3400 break;
3402 break;
3403 default:
3404 if (pwdlastset_old >= pwdlastset_new) {
3405 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3406 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3407 (unsigned long long) pwdlastset_old,
3408 (unsigned long long) pwdlastset_new);
3409 ret = false;
3411 if (pwdlastset_new == 0) {
3412 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3413 "expected non-0 pwdlastset, got: %llu\n",
3414 (unsigned long long) pwdlastset_new);
3415 ret = false;
3417 break;
3420 switch (levels[l]) {
3421 case 21:
3422 case 23:
3423 case 25:
3424 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3425 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3426 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3427 (pwdlastset_old >= pwdlastset_new)) {
3428 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3429 ret = false;
3431 break;
3434 pwdlastset_old = pwdlastset_new;
3436 usleep(delay);
3438 /* set #2b */
3440 /* set a password, pwdlastset needs to get updated (increased
3441 * value), password_expired value used here is 0 */
3443 if (!test_SetPassword_level(p, np, tctx, handle,
3444 levels[l],
3445 fields_present[f],
3447 &matched_expected_error,
3448 set_levels[s],
3449 acct_name,
3450 password,
3451 machine_credentials,
3452 query_levels[q],
3453 &pwdlastset_new,
3454 expected_samlogon_result)) {
3455 ret = false;
3458 /* when a password has been changed, pwdlastset must not be 0 afterwards
3459 * and must be larger then the old value */
3461 switch (levels[l]) {
3462 case 21:
3463 case 23:
3464 case 25:
3466 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3467 * password has been changed, old and new pwdlastset
3468 * need to be the same value */
3470 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3471 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3472 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3474 torture_assert_int_equal(tctx, pwdlastset_old,
3475 pwdlastset_new, "pwdlastset must be equal");
3476 break;
3478 break;
3479 default:
3480 if (pwdlastset_old >= pwdlastset_new) {
3481 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3482 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3483 (unsigned long long) pwdlastset_old,
3484 (unsigned long long) pwdlastset_new);
3485 ret = false;
3487 if (pwdlastset_new == 0) {
3488 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3489 "expected non-0 pwdlastset, got: %llu\n",
3490 (unsigned long long) pwdlastset_new);
3491 ret = false;
3493 break;
3496 switch (levels[l]) {
3497 case 21:
3498 case 23:
3499 case 25:
3500 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3501 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3502 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3503 (pwdlastset_old >= pwdlastset_new)) {
3504 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3505 ret = false;
3507 break;
3510 pwdlastset_old = pwdlastset_new;
3512 usleep(delay);
3514 /* set #3 */
3516 /* set a password and force password change (pwdlastset 0) by
3517 * setting the password expired flag to a non-0 value */
3519 if (!test_SetPassword_level(p, np, tctx, handle,
3520 levels[l],
3521 fields_present[f],
3522 nonzeros[z],
3523 &matched_expected_error,
3524 set_levels[s],
3525 acct_name,
3526 password,
3527 machine_credentials,
3528 query_levels[q],
3529 &pwdlastset_new,
3530 expected_samlogon_result)) {
3531 ret = false;
3534 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3535 * set without the SAMR_FIELD_EXPIRED_FLAG */
3537 switch (levels[l]) {
3538 case 21:
3539 case 23:
3540 case 25:
3541 if ((pwdlastset_new != 0) &&
3542 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3543 torture_comment(tctx, "not considering a non-0 "
3544 "pwdLastSet as a an error as the "
3545 "SAMR_FIELD_EXPIRED_FLAG has not "
3546 "been set\n");
3547 break;
3550 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3551 * password has been changed, old and new pwdlastset
3552 * need to be the same value */
3554 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3555 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3556 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3558 torture_assert_int_equal(tctx, pwdlastset_old,
3559 pwdlastset_new, "pwdlastset must be equal");
3560 break;
3562 break;
3563 default:
3564 if (pwdlastset_new != 0) {
3565 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3566 "expected pwdLastSet 0, got %llu\n",
3567 (unsigned long long) pwdlastset_old);
3568 ret = false;
3570 break;
3573 switch (levels[l]) {
3574 case 21:
3575 case 23:
3576 case 25:
3577 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3578 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3579 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3580 (pwdlastset_old >= pwdlastset_new)) {
3581 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3582 ret = false;
3584 break;
3587 /* if the level we are testing does not have a fields_present
3588 * field, skip all fields present tests by setting f to to
3589 * arraysize */
3590 switch (levels[l]) {
3591 case 18:
3592 case 24:
3593 case 26:
3594 f = ARRAY_SIZE(fields_present);
3595 break;
3598 #ifdef TEST_QUERY_LEVELS
3600 #endif
3601 #ifdef TEST_SET_LEVELS
3603 #endif
3604 } /* fields present */
3605 } /* nonzeros */
3606 } /* levels */
3608 #undef TEST_SET_LEVELS
3609 #undef TEST_QUERY_LEVELS
3611 talloc_free(np);
3613 return ret;
3616 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3617 struct torture_context *tctx,
3618 struct policy_handle *handle,
3619 uint32_t *badpwdcount)
3621 union samr_UserInfo *info;
3622 struct samr_QueryUserInfo r;
3624 r.in.user_handle = handle;
3625 r.in.level = 3;
3626 r.out.info = &info;
3628 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3630 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3631 "failed to query userinfo");
3632 torture_assert_ntstatus_ok(tctx, r.out.result,
3633 "failed to query userinfo");
3635 *badpwdcount = info->info3.bad_password_count;
3637 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3639 return true;
3642 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3643 struct torture_context *tctx,
3644 struct policy_handle *user_handle,
3645 uint32_t acct_flags)
3647 struct samr_SetUserInfo r;
3648 union samr_UserInfo user_info;
3650 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3652 user_info.info16.acct_flags = acct_flags;
3654 r.in.user_handle = user_handle;
3655 r.in.level = 16;
3656 r.in.info = &user_info;
3658 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3659 "failed to set account flags");
3660 torture_assert_ntstatus_ok(tctx, r.out.result,
3661 "failed to set account flags");
3663 return true;
3666 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3667 struct torture_context *tctx,
3668 struct policy_handle *user_handle,
3669 uint32_t acct_flags,
3670 char **password)
3672 struct dcerpc_binding_handle *b = p->binding_handle;
3674 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3675 "failed to set password");
3677 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3679 torture_assert(tctx,
3680 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3681 acct_flags & ~ACB_DISABLED),
3682 "failed to enable user");
3684 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3685 "failed to set password");
3687 return true;
3690 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3691 struct torture_context *tctx,
3692 struct policy_handle *domain_handle,
3693 enum samr_DomainInfoClass level,
3694 union samr_DomainInfo *info)
3696 struct samr_SetDomainInfo r;
3698 r.in.domain_handle = domain_handle;
3699 r.in.level = level;
3700 r.in.info = info;
3702 torture_assert_ntstatus_ok(tctx,
3703 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3704 "failed to set domain info");
3705 torture_assert_ntstatus_ok(tctx, r.out.result,
3706 "failed to set domain info");
3708 return true;
3711 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3712 struct torture_context *tctx,
3713 struct policy_handle *domain_handle,
3714 enum samr_DomainInfoClass level,
3715 union samr_DomainInfo *info,
3716 NTSTATUS expected)
3718 struct samr_SetDomainInfo r;
3720 r.in.domain_handle = domain_handle;
3721 r.in.level = level;
3722 r.in.info = info;
3724 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3725 "SetDomainInfo failed");
3726 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3728 return true;
3731 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3732 struct torture_context *tctx,
3733 struct policy_handle *domain_handle,
3734 enum samr_DomainInfoClass level,
3735 union samr_DomainInfo **q_info)
3737 struct samr_QueryDomainInfo2 r;
3739 r.in.domain_handle = domain_handle;
3740 r.in.level = level;
3741 r.out.info = q_info;
3743 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3744 "failed to query domain info");
3745 torture_assert_ntstatus_ok(tctx, r.out.result,
3746 "failed to query domain info");
3748 return true;
3751 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3752 struct dcerpc_pipe *np,
3753 struct torture_context *tctx,
3754 uint32_t acct_flags,
3755 const char *acct_name,
3756 struct policy_handle *domain_handle,
3757 struct policy_handle *user_handle,
3758 char **password,
3759 struct cli_credentials *machine_credentials,
3760 const char *comment,
3761 bool disable,
3762 bool interactive,
3763 NTSTATUS expected_success_status,
3764 struct samr_DomInfo1 *info1,
3765 struct samr_DomInfo12 *info12)
3767 union samr_DomainInfo info;
3768 char **passwords;
3769 int i;
3770 uint32_t badpwdcount, tmp;
3771 uint32_t password_history_length = 12;
3772 uint32_t lockout_threshold = 15;
3773 uint32_t lockout_seconds = 5;
3774 uint64_t delta_time_factor = 10 * 1000 * 1000;
3775 struct dcerpc_binding_handle *b = p->binding_handle;
3777 if (torture_setting_bool(tctx, "samba3", false)) {
3778 lockout_seconds = 60;
3781 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3783 torture_assert(tctx, password_history_length < lockout_threshold,
3784 "password history length needs to be smaller than account lockout threshold for this test");
3787 /* set policies */
3789 info.info1 = *info1;
3790 info.info1.password_history_length = password_history_length;
3791 info.info1.min_password_age = 0;
3793 torture_assert(tctx,
3794 test_SetDomainInfo(b, tctx, domain_handle,
3795 DomainPasswordInformation, &info),
3796 "failed to set password history length and min passwd age");
3798 info.info12 = *info12;
3799 info.info12.lockout_threshold = lockout_threshold;
3801 /* set lockout duration of 5 seconds */
3802 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3803 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
3805 torture_assert(tctx,
3806 test_SetDomainInfo(b, tctx, domain_handle,
3807 DomainLockoutInformation, &info),
3808 "failed to set lockout threshold");
3810 /* reset bad pwd count */
3812 torture_assert(tctx,
3813 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3816 /* enable or disable account */
3817 if (disable) {
3818 torture_assert(tctx,
3819 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3820 acct_flags | ACB_DISABLED),
3821 "failed to disable user");
3822 } else {
3823 torture_assert(tctx,
3824 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3825 acct_flags & ~ACB_DISABLED),
3826 "failed to enable user");
3830 /* setup password history */
3832 passwords = talloc_array(tctx, char *, password_history_length);
3834 for (i=0; i < password_history_length; i++) {
3836 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3837 "failed to set password");
3838 passwords[i] = talloc_strdup(tctx, *password);
3840 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3841 acct_name, passwords[i],
3842 expected_success_status, interactive)) {
3843 torture_fail(tctx, "failed to auth with latest password");
3846 torture_assert(tctx,
3847 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3849 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3853 /* test with wrong password */
3855 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3856 acct_name, "random_crap",
3857 NT_STATUS_WRONG_PASSWORD, interactive)) {
3858 torture_fail(tctx, "succeeded to authenticate with wrong password");
3861 torture_assert(tctx,
3862 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3864 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3867 /* test with latest good password */
3869 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3870 passwords[password_history_length-1],
3871 expected_success_status, interactive)) {
3872 torture_fail(tctx, "succeeded to authenticate with wrong password");
3875 torture_assert(tctx,
3876 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3878 if (disable) {
3879 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3880 } else {
3881 /* only enabled accounts get the bad pwd count reset upon
3882 * successful logon */
3883 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3886 tmp = badpwdcount;
3889 /* test password history */
3891 for (i=0; i < password_history_length; i++) {
3893 torture_comment(tctx, "Testing bad password count behavior with "
3894 "password #%d of #%d\n", i, password_history_length);
3896 /* - network samlogon will succeed auth and not
3897 * increase badpwdcount for 2 last entries
3898 * - interactive samlogon only for the last one */
3900 if (i == password_history_length - 1 ||
3901 (i == password_history_length - 2 && !interactive)) {
3903 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3904 acct_name, passwords[i],
3905 expected_success_status, interactive)) {
3906 torture_fail(tctx, talloc_asprintf(tctx, "did not successfully to obtain %s for %s login with old password (#%d of #%d in history)",
3907 nt_errstr(expected_success_status),
3908 interactive ? "interactive" : "network", i, password_history_length));
3911 torture_assert(tctx,
3912 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3914 if (disable) {
3915 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3916 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3917 } else {
3918 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3919 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3922 tmp = badpwdcount;
3924 continue;
3927 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3928 acct_name, passwords[i],
3929 NT_STATUS_WRONG_PASSWORD, interactive)) {
3930 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3933 torture_assert(tctx,
3934 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3936 /* - network samlogon will fail auth but not increase
3937 * badpwdcount for 3rd last entry
3938 * - interactive samlogon for 3rd and 2nd last entry */
3940 if (i == password_history_length - 3 ||
3941 (i == password_history_length - 2 && interactive)) {
3942 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3943 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3944 } else {
3945 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3946 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3949 tmp = badpwdcount;
3952 return true;
3955 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3956 struct torture_context *tctx,
3957 uint32_t acct_flags,
3958 const char *acct_name,
3959 struct policy_handle *domain_handle,
3960 struct policy_handle *user_handle,
3961 char **password,
3962 struct cli_credentials *machine_credentials)
3964 union samr_DomainInfo *q_info, s_info;
3965 struct samr_DomInfo1 info1, _info1;
3966 struct samr_DomInfo12 info12, _info12;
3967 bool ret = true;
3968 struct dcerpc_binding_handle *b = p->binding_handle;
3969 struct dcerpc_pipe *np;
3970 int i;
3972 struct {
3973 const char *comment;
3974 bool disabled;
3975 bool interactive;
3976 NTSTATUS expected_success_status;
3977 } creds[] = {
3979 .comment = "network logon (disabled account)",
3980 .disabled = true,
3981 .interactive = false,
3982 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3985 .comment = "network logon (enabled account)",
3986 .disabled = false,
3987 .interactive = false,
3988 .expected_success_status= NT_STATUS_OK
3991 .comment = "interactive logon (disabled account)",
3992 .disabled = true,
3993 .interactive = true,
3994 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3997 .comment = "interactive logon (enabled account)",
3998 .disabled = false,
3999 .interactive = true,
4000 .expected_success_status= NT_STATUS_OK
4004 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4006 /* backup old policies */
4008 torture_assert(tctx,
4009 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4010 DomainPasswordInformation, &q_info),
4011 "failed to query domain info level 1");
4013 info1 = q_info->info1;
4014 _info1 = info1;
4016 torture_assert(tctx,
4017 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4018 DomainLockoutInformation, &q_info),
4019 "failed to query domain info level 12");
4021 info12 = q_info->info12;
4022 _info12 = info12;
4024 /* run tests */
4026 for (i=0; i < ARRAY_SIZE(creds); i++) {
4028 /* skip trust tests for now */
4029 if (acct_flags & ACB_WSTRUST ||
4030 acct_flags & ACB_SVRTRUST ||
4031 acct_flags & ACB_DOMTRUST) {
4032 continue;
4035 if (!test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4036 domain_handle, user_handle, password,
4037 machine_credentials,
4038 creds[i].comment,
4039 creds[i].disabled,
4040 creds[i].interactive,
4041 creds[i].expected_success_status,
4042 &_info1, &_info12)) {
4043 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4044 ret = false;
4045 } else {
4046 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4050 /* restore policies */
4052 s_info.info1 = info1;
4054 torture_assert(tctx,
4055 test_SetDomainInfo(b, tctx, domain_handle,
4056 DomainPasswordInformation, &s_info),
4057 "failed to set password information");
4059 s_info.info12 = info12;
4061 torture_assert(tctx,
4062 test_SetDomainInfo(b, tctx, domain_handle,
4063 DomainLockoutInformation, &s_info),
4064 "failed to set lockout information");
4066 return ret;
4069 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
4070 struct torture_context *tctx,
4071 struct policy_handle *domain_handle,
4072 const char *acct_name,
4073 uint32_t *acct_flags)
4075 struct policy_handle user_handle;
4076 union samr_UserInfo *info;
4077 struct samr_QueryUserInfo r;
4079 NTSTATUS status = test_OpenUser_byname(b, tctx, domain_handle, acct_name, &user_handle);
4080 if (!NT_STATUS_IS_OK(status)) {
4081 return false;
4084 r.in.user_handle = &user_handle;
4085 r.in.level = 16;
4086 r.out.info = &info;
4088 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4090 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4091 "failed to query userinfo");
4092 torture_assert_ntstatus_ok(tctx, r.out.result,
4093 "failed to query userinfo");
4095 *acct_flags = info->info16.acct_flags;
4097 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
4099 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
4100 return false;
4103 return true;
4106 static bool test_Password_lockout(struct dcerpc_pipe *p,
4107 struct dcerpc_pipe *np,
4108 struct torture_context *tctx,
4109 uint32_t acct_flags,
4110 const char *acct_name,
4111 struct policy_handle *domain_handle,
4112 struct policy_handle *user_handle,
4113 char **password,
4114 struct cli_credentials *machine_credentials,
4115 const char *comment,
4116 bool disable,
4117 bool interactive,
4118 NTSTATUS expected_success_status,
4119 struct samr_DomInfo1 *info1,
4120 struct samr_DomInfo12 *info12)
4122 union samr_DomainInfo info;
4123 uint32_t badpwdcount;
4124 uint32_t password_history_length = 1;
4125 uint64_t lockout_threshold = 1;
4126 uint32_t lockout_seconds = 5;
4127 uint64_t delta_time_factor = 10 * 1000 * 1000;
4128 struct dcerpc_binding_handle *b = p->binding_handle;
4130 if (torture_setting_bool(tctx, "samba3", false)) {
4131 lockout_seconds = 60;
4134 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4136 /* set policies */
4138 info.info1 = *info1;
4140 torture_comment(tctx, "setting password history length.\n");
4141 info.info1.password_history_length = password_history_length;
4143 torture_comment(tctx, "setting min password again.\n");
4144 info.info1.min_password_age = 0;
4146 torture_assert(tctx,
4147 test_SetDomainInfo(b, tctx, domain_handle,
4148 DomainPasswordInformation, &info),
4149 "failed to set password history length");
4151 info.info12 = *info12;
4152 info.info12.lockout_threshold = lockout_threshold;
4154 /* set lockout duration < lockout window: should fail */
4155 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4156 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4158 torture_assert(tctx,
4159 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4160 DomainLockoutInformation, &info,
4161 NT_STATUS_INVALID_PARAMETER),
4162 "setting lockout duration < lockout window gave unexpected result");
4164 info.info12.lockout_duration = 0;
4165 info.info12.lockout_window = 0;
4167 torture_assert(tctx,
4168 test_SetDomainInfo(b, tctx, domain_handle,
4169 DomainLockoutInformation, &info),
4170 "failed to set lockout window and duration to 0");
4173 /* set lockout duration of 5 seconds */
4174 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4175 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4177 torture_assert(tctx,
4178 test_SetDomainInfo(b, tctx, domain_handle,
4179 DomainLockoutInformation, &info),
4180 "failed to set lockout window and duration to 5 seconds");
4182 /* reset bad pwd count */
4184 torture_assert(tctx,
4185 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4188 /* enable or disable account */
4190 if (disable) {
4191 torture_assert(tctx,
4192 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4193 acct_flags | ACB_DISABLED),
4194 "failed to disable user");
4195 } else {
4196 torture_assert(tctx,
4197 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4198 acct_flags & ~ACB_DISABLED),
4199 "failed to enable user");
4203 /* test logon with right password */
4205 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4206 acct_name, *password,
4207 expected_success_status, interactive)) {
4208 torture_fail(tctx, "failed to auth with latest password");
4211 torture_assert(tctx,
4212 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4213 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4216 /* test with wrong password ==> lockout */
4218 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4219 acct_name, "random_crap",
4220 NT_STATUS_WRONG_PASSWORD, interactive)) {
4221 torture_fail(tctx, "succeeded to authenticate with wrong password");
4224 torture_assert(tctx,
4225 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4226 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4228 /* curiously, windows does _not_ set the autlock flag unless you re-open the user */
4229 torture_assert(tctx,
4230 test_QueryUserInfo_acct_flags(b, tctx, domain_handle, acct_name, &acct_flags), "");
4231 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, ACB_AUTOLOCK,
4232 "expected account to be locked");
4235 /* test with good password */
4237 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4238 *password,
4239 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4241 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4244 /* bad pwd count should not get updated */
4245 torture_assert(tctx,
4246 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4247 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4249 /* curiously, windows does _not_ set the autlock flag unless you re-open the user */
4250 torture_assert(tctx,
4251 test_QueryUserInfo_acct_flags(b, tctx, domain_handle, acct_name, &acct_flags), "");
4252 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, ACB_AUTOLOCK,
4253 "expected account to be locked");
4256 /* with bad password */
4258 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4259 acct_name, "random_crap2",
4260 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4262 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4265 /* bad pwd count should not get updated */
4266 torture_assert(tctx,
4267 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4268 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4270 /* curiously, windows does _not_ set the autlock flag untill you re-open the user */
4271 torture_assert(tctx,
4272 test_QueryUserInfo_acct_flags(b, tctx, domain_handle, acct_name, &acct_flags), "");
4273 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, ACB_AUTOLOCK,
4274 "expected account to show ACB_AUTOLOCK");
4277 /* let lockout duration expire ==> unlock */
4279 torture_comment(tctx, "let lockout duration expire...\n");
4280 sleep(lockout_seconds + 1);
4282 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4283 *password,
4284 expected_success_status, interactive))
4286 torture_fail(tctx, "failed to authenticate after lockout expired");
4289 torture_assert(tctx,
4290 test_QueryUserInfo_acct_flags(b, tctx, domain_handle, acct_name, &acct_flags), "");
4291 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4292 "expected account not to be locked");
4294 return true;
4297 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4298 struct torture_context *tctx,
4299 uint32_t acct_flags,
4300 const char *acct_name,
4301 struct policy_handle *domain_handle,
4302 struct policy_handle *user_handle,
4303 char **password,
4304 struct cli_credentials *machine_credentials)
4306 union samr_DomainInfo *q_info, s_info;
4307 struct samr_DomInfo1 info1, _info1;
4308 struct samr_DomInfo12 info12, _info12;
4309 bool ret = true;
4310 struct dcerpc_binding_handle *b = p->binding_handle;
4311 struct dcerpc_pipe *np;
4312 int i;
4314 struct {
4315 const char *comment;
4316 bool disabled;
4317 bool interactive;
4318 NTSTATUS expected_success_status;
4319 } creds[] = {
4321 .comment = "network logon (disabled account)",
4322 .disabled = true,
4323 .interactive = false,
4324 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4327 .comment = "network logon (enabled account)",
4328 .disabled = false,
4329 .interactive = false,
4330 .expected_success_status= NT_STATUS_OK
4333 .comment = "interactive logon (disabled account)",
4334 .disabled = true,
4335 .interactive = true,
4336 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4339 .comment = "interactive logon (enabled account)",
4340 .disabled = false,
4341 .interactive = true,
4342 .expected_success_status= NT_STATUS_OK
4346 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4348 /* backup old policies */
4350 torture_assert(tctx,
4351 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4352 DomainPasswordInformation, &q_info),
4353 "failed to query domain info level 1");
4355 info1 = q_info->info1;
4356 _info1 = info1;
4358 torture_assert(tctx,
4359 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4360 DomainLockoutInformation, &q_info),
4361 "failed to query domain info level 12");
4363 info12 = q_info->info12;
4364 _info12 = info12;
4366 /* run tests */
4368 for (i=0; i < ARRAY_SIZE(creds); i++) {
4369 bool test_passed;
4370 /* skip trust tests for now */
4371 if (acct_flags & ACB_WSTRUST ||
4372 acct_flags & ACB_SVRTRUST ||
4373 acct_flags & ACB_DOMTRUST) {
4374 continue;
4377 test_passed = test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4378 domain_handle, user_handle, password,
4379 machine_credentials,
4380 creds[i].comment,
4381 creds[i].disabled,
4382 creds[i].interactive,
4383 creds[i].expected_success_status,
4384 &_info1, &_info12);
4385 ret &= test_passed;
4386 if (!test_passed) {
4387 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4388 break;
4389 } else {
4390 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4394 /* restore policies */
4396 s_info.info1 = info1;
4398 torture_assert(tctx,
4399 test_SetDomainInfo(b, tctx, domain_handle,
4400 DomainPasswordInformation, &s_info),
4401 "failed to set password information");
4403 s_info.info12 = info12;
4405 torture_assert(tctx,
4406 test_SetDomainInfo(b, tctx, domain_handle,
4407 DomainLockoutInformation, &s_info),
4408 "failed to set lockout information");
4410 return ret;
4413 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4414 struct dcerpc_pipe *lp,
4415 struct torture_context *tctx,
4416 struct policy_handle *domain_handle,
4417 struct policy_handle *lsa_handle,
4418 struct policy_handle *user_handle,
4419 const struct dom_sid *domain_sid,
4420 uint32_t rid,
4421 struct cli_credentials *machine_credentials)
4423 bool ret = true;
4424 struct dcerpc_binding_handle *b = p->binding_handle;
4425 struct dcerpc_binding_handle *lb = lp->binding_handle;
4427 struct policy_handle lsa_acct_handle;
4428 struct dom_sid *user_sid;
4430 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4433 struct lsa_EnumAccountRights r;
4434 struct lsa_RightSet rights;
4436 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4438 r.in.handle = lsa_handle;
4439 r.in.sid = user_sid;
4440 r.out.rights = &rights;
4442 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4443 "lsa_EnumAccountRights failed");
4444 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4445 "Expected enum rights for account to fail");
4449 struct lsa_RightSet rights;
4450 struct lsa_StringLarge names[2];
4451 struct lsa_AddAccountRights r;
4453 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4455 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4456 init_lsa_StringLarge(&names[1], NULL);
4458 rights.count = 1;
4459 rights.names = names;
4461 r.in.handle = lsa_handle;
4462 r.in.sid = user_sid;
4463 r.in.rights = &rights;
4465 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4466 "lsa_AddAccountRights failed");
4467 torture_assert_ntstatus_ok(tctx, r.out.result,
4468 "Failed to add privileges");
4472 struct lsa_EnumAccounts r;
4473 uint32_t resume_handle = 0;
4474 struct lsa_SidArray lsa_sid_array;
4475 int i;
4476 bool found_sid = false;
4478 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4480 r.in.handle = lsa_handle;
4481 r.in.num_entries = 0x1000;
4482 r.in.resume_handle = &resume_handle;
4483 r.out.sids = &lsa_sid_array;
4484 r.out.resume_handle = &resume_handle;
4486 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4487 "lsa_EnumAccounts failed");
4488 torture_assert_ntstatus_ok(tctx, r.out.result,
4489 "Failed to enum accounts");
4491 for (i=0; i < lsa_sid_array.num_sids; i++) {
4492 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4493 found_sid = true;
4497 torture_assert(tctx, found_sid,
4498 "failed to list privileged account");
4502 struct lsa_EnumAccountRights r;
4503 struct lsa_RightSet user_rights;
4505 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4507 r.in.handle = lsa_handle;
4508 r.in.sid = user_sid;
4509 r.out.rights = &user_rights;
4511 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4512 "lsa_EnumAccountRights failed");
4513 torture_assert_ntstatus_ok(tctx, r.out.result,
4514 "Failed to enum rights for account");
4516 if (user_rights.count < 1) {
4517 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4518 return false;
4523 struct lsa_OpenAccount r;
4525 torture_comment(tctx, "Testing LSA OpenAccount\n");
4527 r.in.handle = lsa_handle;
4528 r.in.sid = user_sid;
4529 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4530 r.out.acct_handle = &lsa_acct_handle;
4532 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4533 "lsa_OpenAccount failed");
4534 torture_assert_ntstatus_ok(tctx, r.out.result,
4535 "Failed to open lsa account");
4539 struct lsa_GetSystemAccessAccount r;
4540 uint32_t access_mask;
4542 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4544 r.in.handle = &lsa_acct_handle;
4545 r.out.access_mask = &access_mask;
4547 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4548 "lsa_GetSystemAccessAccount failed");
4549 torture_assert_ntstatus_ok(tctx, r.out.result,
4550 "Failed to get lsa system access account");
4554 struct lsa_Close r;
4556 torture_comment(tctx, "Testing LSA Close\n");
4558 r.in.handle = &lsa_acct_handle;
4559 r.out.handle = &lsa_acct_handle;
4561 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4562 "lsa_Close failed");
4563 torture_assert_ntstatus_ok(tctx, r.out.result,
4564 "Failed to close lsa");
4568 struct samr_DeleteUser r;
4570 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4572 r.in.user_handle = user_handle;
4573 r.out.user_handle = user_handle;
4575 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4576 "DeleteUser failed");
4577 torture_assert_ntstatus_ok(tctx, r.out.result,
4578 "DeleteUser failed");
4582 struct lsa_EnumAccounts r;
4583 uint32_t resume_handle = 0;
4584 struct lsa_SidArray lsa_sid_array;
4585 int i;
4586 bool found_sid = false;
4588 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4590 r.in.handle = lsa_handle;
4591 r.in.num_entries = 0x1000;
4592 r.in.resume_handle = &resume_handle;
4593 r.out.sids = &lsa_sid_array;
4594 r.out.resume_handle = &resume_handle;
4596 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4597 "lsa_EnumAccounts failed");
4598 torture_assert_ntstatus_ok(tctx, r.out.result,
4599 "Failed to enum accounts");
4601 for (i=0; i < lsa_sid_array.num_sids; i++) {
4602 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4603 found_sid = true;
4607 torture_assert(tctx, found_sid,
4608 "failed to list privileged account");
4612 struct lsa_EnumAccountRights r;
4613 struct lsa_RightSet user_rights;
4615 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4617 r.in.handle = lsa_handle;
4618 r.in.sid = user_sid;
4619 r.out.rights = &user_rights;
4621 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4622 "lsa_EnumAccountRights failed");
4623 torture_assert_ntstatus_ok(tctx, r.out.result,
4624 "Failed to enum rights for account");
4626 if (user_rights.count < 1) {
4627 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4628 return false;
4633 struct lsa_OpenAccount r;
4635 torture_comment(tctx, "Testing LSA OpenAccount\n");
4637 r.in.handle = lsa_handle;
4638 r.in.sid = user_sid;
4639 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4640 r.out.acct_handle = &lsa_acct_handle;
4642 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4643 "lsa_OpenAccount failed");
4644 torture_assert_ntstatus_ok(tctx, r.out.result,
4645 "Failed to open lsa account");
4649 struct lsa_GetSystemAccessAccount r;
4650 uint32_t access_mask;
4652 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4654 r.in.handle = &lsa_acct_handle;
4655 r.out.access_mask = &access_mask;
4657 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4658 "lsa_GetSystemAccessAccount failed");
4659 torture_assert_ntstatus_ok(tctx, r.out.result,
4660 "Failed to get lsa system access account");
4664 struct lsa_DeleteObject r;
4666 torture_comment(tctx, "Testing LSA DeleteObject\n");
4668 r.in.handle = &lsa_acct_handle;
4669 r.out.handle = &lsa_acct_handle;
4671 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4672 "lsa_DeleteObject failed");
4673 torture_assert_ntstatus_ok(tctx, r.out.result,
4674 "Failed to delete object");
4678 struct lsa_EnumAccounts r;
4679 uint32_t resume_handle = 0;
4680 struct lsa_SidArray lsa_sid_array;
4681 int i;
4682 bool found_sid = false;
4684 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4686 r.in.handle = lsa_handle;
4687 r.in.num_entries = 0x1000;
4688 r.in.resume_handle = &resume_handle;
4689 r.out.sids = &lsa_sid_array;
4690 r.out.resume_handle = &resume_handle;
4692 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4693 "lsa_EnumAccounts failed");
4694 torture_assert_ntstatus_ok(tctx, r.out.result,
4695 "Failed to enum accounts");
4697 for (i=0; i < lsa_sid_array.num_sids; i++) {
4698 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4699 found_sid = true;
4703 torture_assert(tctx, !found_sid,
4704 "should not have listed privileged account");
4708 struct lsa_EnumAccountRights r;
4709 struct lsa_RightSet user_rights;
4711 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4713 r.in.handle = lsa_handle;
4714 r.in.sid = user_sid;
4715 r.out.rights = &user_rights;
4717 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4718 "lsa_EnumAccountRights failed");
4719 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4720 "Failed to enum rights for account");
4723 return ret;
4726 static bool test_user_ops(struct dcerpc_pipe *p,
4727 struct torture_context *tctx,
4728 struct policy_handle *user_handle,
4729 struct policy_handle *domain_handle,
4730 const struct dom_sid *domain_sid,
4731 uint32_t base_acct_flags,
4732 const char *base_acct_name, enum torture_samr_choice which_ops,
4733 struct cli_credentials *machine_credentials)
4735 char *password = NULL;
4736 struct samr_QueryUserInfo q;
4737 union samr_UserInfo *info;
4738 NTSTATUS status;
4739 struct dcerpc_binding_handle *b = p->binding_handle;
4741 bool ret = true;
4742 int i;
4743 uint32_t rid;
4744 const uint32_t password_fields[] = {
4745 SAMR_FIELD_NT_PASSWORD_PRESENT,
4746 SAMR_FIELD_LM_PASSWORD_PRESENT,
4747 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4751 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4752 if (!NT_STATUS_IS_OK(status)) {
4753 ret = false;
4756 switch (which_ops) {
4757 case TORTURE_SAMR_USER_ATTRIBUTES:
4758 if (!test_QuerySecurity(b, tctx, user_handle)) {
4759 ret = false;
4762 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4763 ret = false;
4766 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4767 ret = false;
4770 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4771 base_acct_name)) {
4772 ret = false;
4775 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4776 ret = false;
4779 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4780 ret = false;
4783 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4784 ret = false;
4786 break;
4787 case TORTURE_SAMR_PASSWORDS:
4788 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4789 char simple_pass[9];
4790 char *v = generate_random_str(tctx, 1);
4792 ZERO_STRUCT(simple_pass);
4793 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4795 torture_comment(tctx, "Testing machine account password policy rules\n");
4797 /* Workstation trust accounts don't seem to need to honour password quality policy */
4798 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4799 ret = false;
4802 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4803 ret = false;
4806 /* reset again, to allow another 'user' password change */
4807 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4808 ret = false;
4811 /* Try a 'short' password */
4812 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4813 ret = false;
4816 /* Try a compleatly random password */
4817 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4818 ret = false;
4822 for (i = 0; password_fields[i]; i++) {
4823 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4824 ret = false;
4827 /* check it was set right */
4828 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4829 ret = false;
4833 for (i = 0; password_fields[i]; i++) {
4834 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4835 ret = false;
4838 /* check it was set right */
4839 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4840 ret = false;
4844 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4845 ret = false;
4848 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4849 ret = false;
4852 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4853 ret = false;
4856 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4857 ret = false;
4860 for (i = 0; password_fields[i]; i++) {
4862 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4863 /* we need to skip as that would break
4864 * the ChangePasswordUser3 verify */
4865 continue;
4868 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4869 ret = false;
4872 /* check it was set right */
4873 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4874 ret = false;
4878 q.in.user_handle = user_handle;
4879 q.in.level = 5;
4880 q.out.info = &info;
4882 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4883 "QueryUserInfo failed");
4884 if (!NT_STATUS_IS_OK(q.out.result)) {
4885 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
4886 q.in.level, nt_errstr(q.out.result));
4887 ret = false;
4888 } else {
4889 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4890 if ((info->info5.acct_flags) != expected_flags) {
4891 /* FIXME: GD */
4892 if (!torture_setting_bool(tctx, "samba3", false)) {
4893 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4894 info->info5.acct_flags,
4895 expected_flags);
4896 ret = false;
4899 if (info->info5.rid != rid) {
4900 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4901 info->info5.rid, rid);
4906 break;
4908 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4910 /* test last password change timestamp behaviour */
4911 torture_assert(tctx, test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4912 base_acct_name,
4913 user_handle, &password,
4914 machine_credentials),
4915 "pwdLastSet test failed\n");
4916 break;
4918 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4920 /* test bad pwd count change behaviour */
4921 torture_assert(tctx, test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4922 base_acct_name,
4923 domain_handle,
4924 user_handle, &password,
4925 machine_credentials),
4926 "badPwdCount test failed\n");
4927 break;
4929 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4931 torture_assert(tctx, test_Password_lockout_wrap(p, tctx, base_acct_flags,
4932 base_acct_name,
4933 domain_handle,
4934 user_handle, &password,
4935 machine_credentials),
4936 "Lockout test failed");
4937 break;
4940 case TORTURE_SAMR_USER_PRIVILEGES: {
4942 struct dcerpc_pipe *lp;
4943 struct policy_handle *lsa_handle;
4944 struct dcerpc_binding_handle *lb;
4946 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4947 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4948 lb = lp->binding_handle;
4950 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4951 ret = false;
4954 if (!test_DeleteUser_with_privs(p, lp, tctx,
4955 domain_handle, lsa_handle, user_handle,
4956 domain_sid, rid,
4957 machine_credentials)) {
4958 ret = false;
4961 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4962 ret = false;
4965 if (!ret) {
4966 torture_result(tctx, TORTURE_FAIL, "privileged user delete test failed\n");
4969 break;
4971 case TORTURE_SAMR_OTHER:
4972 case TORTURE_SAMR_MANY_ACCOUNTS:
4973 case TORTURE_SAMR_MANY_GROUPS:
4974 case TORTURE_SAMR_MANY_ALIASES:
4975 /* We just need the account to exist */
4976 break;
4978 return ret;
4981 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4982 struct torture_context *tctx,
4983 struct policy_handle *alias_handle,
4984 const struct dom_sid *domain_sid)
4986 bool ret = true;
4988 if (!torture_setting_bool(tctx, "samba3", false)) {
4989 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4990 ret = false;
4994 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4995 ret = false;
4998 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4999 ret = false;
5002 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
5003 ret = false;
5006 if (torture_setting_bool(tctx, "samba3", false) ||
5007 torture_setting_bool(tctx, "samba4", false)) {
5008 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
5009 return ret;
5012 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
5013 ret = false;
5016 return ret;
5020 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
5021 struct torture_context *tctx,
5022 struct policy_handle *user_handle)
5024 struct samr_DeleteUser d;
5025 torture_comment(tctx, "Testing DeleteUser\n");
5027 d.in.user_handle = user_handle;
5028 d.out.user_handle = user_handle;
5030 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5031 "DeleteUser failed");
5032 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5034 return true;
5037 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5038 struct torture_context *tctx,
5039 struct policy_handle *handle, const char *name)
5041 NTSTATUS status;
5042 struct samr_DeleteUser d;
5043 struct policy_handle user_handle;
5044 uint32_t rid;
5046 status = test_LookupName(b, tctx, handle, name, &rid);
5047 if (!NT_STATUS_IS_OK(status)) {
5048 goto failed;
5051 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5052 if (!NT_STATUS_IS_OK(status)) {
5053 goto failed;
5056 d.in.user_handle = &user_handle;
5057 d.out.user_handle = &user_handle;
5058 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5059 "DeleteUser failed");
5060 if (!NT_STATUS_IS_OK(d.out.result)) {
5061 status = d.out.result;
5062 goto failed;
5065 return true;
5067 failed:
5068 torture_result(tctx, TORTURE_FAIL, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
5069 return false;
5073 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
5074 struct torture_context *tctx,
5075 struct policy_handle *handle, const char *name)
5077 NTSTATUS status;
5078 struct samr_OpenGroup r;
5079 struct samr_DeleteDomainGroup d;
5080 struct policy_handle group_handle;
5081 uint32_t rid;
5083 status = test_LookupName(b, tctx, handle, name, &rid);
5084 if (!NT_STATUS_IS_OK(status)) {
5085 goto failed;
5088 r.in.domain_handle = handle;
5089 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5090 r.in.rid = rid;
5091 r.out.group_handle = &group_handle;
5092 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5093 "OpenGroup failed");
5094 if (!NT_STATUS_IS_OK(r.out.result)) {
5095 status = r.out.result;
5096 goto failed;
5099 d.in.group_handle = &group_handle;
5100 d.out.group_handle = &group_handle;
5101 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
5102 "DeleteDomainGroup failed");
5103 if (!NT_STATUS_IS_OK(d.out.result)) {
5104 status = d.out.result;
5105 goto failed;
5108 return true;
5110 failed:
5111 torture_result(tctx, TORTURE_FAIL, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
5112 return false;
5116 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
5117 struct torture_context *tctx,
5118 struct policy_handle *domain_handle,
5119 const char *name)
5121 NTSTATUS status;
5122 struct samr_OpenAlias r;
5123 struct samr_DeleteDomAlias d;
5124 struct policy_handle alias_handle;
5125 uint32_t rid;
5127 torture_comment(tctx, "Testing DeleteAlias_byname\n");
5129 status = test_LookupName(b, tctx, domain_handle, name, &rid);
5130 if (!NT_STATUS_IS_OK(status)) {
5131 goto failed;
5134 r.in.domain_handle = domain_handle;
5135 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5136 r.in.rid = rid;
5137 r.out.alias_handle = &alias_handle;
5138 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5139 "OpenAlias failed");
5140 if (!NT_STATUS_IS_OK(r.out.result)) {
5141 status = r.out.result;
5142 goto failed;
5145 d.in.alias_handle = &alias_handle;
5146 d.out.alias_handle = &alias_handle;
5147 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5148 "DeleteDomAlias failed");
5149 if (!NT_STATUS_IS_OK(d.out.result)) {
5150 status = d.out.result;
5151 goto failed;
5154 return true;
5156 failed:
5157 torture_result(tctx, TORTURE_FAIL, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5158 return false;
5161 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5162 struct torture_context *tctx,
5163 struct policy_handle *alias_handle)
5165 struct samr_DeleteDomAlias d;
5166 bool ret = true;
5168 torture_comment(tctx, "Testing DeleteAlias\n");
5170 d.in.alias_handle = alias_handle;
5171 d.out.alias_handle = alias_handle;
5173 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5174 "DeleteDomAlias failed");
5175 if (!NT_STATUS_IS_OK(d.out.result)) {
5176 torture_result(tctx, TORTURE_FAIL, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5177 ret = false;
5180 return ret;
5183 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5184 struct torture_context *tctx,
5185 struct policy_handle *domain_handle,
5186 const char *alias_name,
5187 struct policy_handle *alias_handle,
5188 const struct dom_sid *domain_sid,
5189 bool test_alias)
5191 struct samr_CreateDomAlias r;
5192 struct lsa_String name;
5193 uint32_t rid;
5194 bool ret = true;
5196 init_lsa_String(&name, alias_name);
5197 r.in.domain_handle = domain_handle;
5198 r.in.alias_name = &name;
5199 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5200 r.out.alias_handle = alias_handle;
5201 r.out.rid = &rid;
5203 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5205 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5206 "CreateDomAlias failed");
5208 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5209 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5210 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5211 return true;
5212 } else {
5213 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5214 nt_errstr(r.out.result));
5215 return false;
5219 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5220 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5221 return false;
5223 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5224 "CreateDomAlias failed");
5227 if (!NT_STATUS_IS_OK(r.out.result)) {
5228 torture_result(tctx, TORTURE_FAIL, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5229 return false;
5232 if (!test_alias) {
5233 return ret;
5236 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5237 ret = false;
5240 return ret;
5243 static bool test_ChangePassword(struct dcerpc_pipe *p,
5244 struct torture_context *tctx,
5245 const char *acct_name,
5246 struct policy_handle *domain_handle, char **password)
5248 bool ret = true;
5249 struct dcerpc_binding_handle *b = p->binding_handle;
5251 if (!*password) {
5252 return false;
5255 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5256 ret = false;
5259 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5260 ret = false;
5263 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5264 ret = false;
5267 /* test what happens when setting the old password again */
5268 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5269 ret = false;
5273 char simple_pass[9];
5274 char *v = generate_random_str(tctx, 1);
5276 ZERO_STRUCT(simple_pass);
5277 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5279 /* test what happens when picking a simple password */
5280 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5281 ret = false;
5285 /* set samr_SetDomainInfo level 1 with min_length 5 */
5287 struct samr_QueryDomainInfo r;
5288 union samr_DomainInfo *info = NULL;
5289 struct samr_SetDomainInfo s;
5290 uint16_t len_old, len;
5291 uint32_t pwd_prop_old;
5292 int64_t min_pwd_age_old;
5294 len = 5;
5296 r.in.domain_handle = domain_handle;
5297 r.in.level = 1;
5298 r.out.info = &info;
5300 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5301 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5302 "QueryDomainInfo failed");
5303 if (!NT_STATUS_IS_OK(r.out.result)) {
5304 return false;
5307 s.in.domain_handle = domain_handle;
5308 s.in.level = 1;
5309 s.in.info = info;
5311 /* remember the old min length, so we can reset it */
5312 len_old = s.in.info->info1.min_password_length;
5313 s.in.info->info1.min_password_length = len;
5314 pwd_prop_old = s.in.info->info1.password_properties;
5315 /* turn off password complexity checks for this test */
5316 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5318 min_pwd_age_old = s.in.info->info1.min_password_age;
5319 s.in.info->info1.min_password_age = 0;
5321 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5322 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5323 "SetDomainInfo failed");
5324 if (!NT_STATUS_IS_OK(s.out.result)) {
5325 return false;
5328 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5330 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5331 ret = false;
5334 s.in.info->info1.min_password_length = len_old;
5335 s.in.info->info1.password_properties = pwd_prop_old;
5336 s.in.info->info1.min_password_age = min_pwd_age_old;
5338 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5339 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5340 "SetDomainInfo failed");
5341 if (!NT_STATUS_IS_OK(s.out.result)) {
5342 return false;
5348 struct samr_OpenUser r;
5349 struct samr_QueryUserInfo q;
5350 union samr_UserInfo *info;
5351 struct samr_LookupNames n;
5352 struct policy_handle user_handle;
5353 struct samr_Ids rids, types;
5355 n.in.domain_handle = domain_handle;
5356 n.in.num_names = 1;
5357 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5358 n.in.names[0].string = acct_name;
5359 n.out.rids = &rids;
5360 n.out.types = &types;
5362 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5363 "LookupNames failed");
5364 if (!NT_STATUS_IS_OK(n.out.result)) {
5365 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5366 return false;
5369 r.in.domain_handle = domain_handle;
5370 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5371 r.in.rid = n.out.rids->ids[0];
5372 r.out.user_handle = &user_handle;
5374 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5375 "OpenUser failed");
5376 if (!NT_STATUS_IS_OK(r.out.result)) {
5377 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5378 return false;
5381 q.in.user_handle = &user_handle;
5382 q.in.level = 5;
5383 q.out.info = &info;
5385 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5386 "QueryUserInfo failed");
5387 if (!NT_STATUS_IS_OK(q.out.result)) {
5388 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5389 return false;
5392 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5394 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5395 info->info5.last_password_change, true)) {
5396 ret = false;
5400 /* we change passwords twice - this has the effect of verifying
5401 they were changed correctly for the final call */
5402 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5403 ret = false;
5406 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5407 ret = false;
5410 return ret;
5413 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5414 struct policy_handle *domain_handle,
5415 const char *user_name,
5416 struct policy_handle *user_handle_out,
5417 struct dom_sid *domain_sid,
5418 enum torture_samr_choice which_ops,
5419 struct cli_credentials *machine_credentials,
5420 bool test_user)
5423 TALLOC_CTX *user_ctx;
5425 struct samr_CreateUser r;
5426 struct samr_QueryUserInfo q;
5427 union samr_UserInfo *info;
5428 struct samr_DeleteUser d;
5429 uint32_t rid;
5431 /* This call creates a 'normal' account - check that it really does */
5432 const uint32_t acct_flags = ACB_NORMAL;
5433 struct lsa_String name;
5434 bool ret = true;
5435 struct dcerpc_binding_handle *b = p->binding_handle;
5437 struct policy_handle user_handle;
5438 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5439 init_lsa_String(&name, user_name);
5441 r.in.domain_handle = domain_handle;
5442 r.in.account_name = &name;
5443 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5444 r.out.user_handle = &user_handle;
5445 r.out.rid = &rid;
5447 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5449 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5450 "CreateUser failed");
5452 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5453 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5454 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5455 return true;
5456 } else {
5457 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5458 nt_errstr(r.out.result));
5459 return false;
5463 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5464 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5465 talloc_free(user_ctx);
5466 return false;
5468 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5469 "CreateUser failed");
5472 if (!NT_STATUS_IS_OK(r.out.result)) {
5473 talloc_free(user_ctx);
5474 torture_result(tctx, TORTURE_FAIL, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5475 return false;
5478 if (!test_user) {
5479 if (user_handle_out) {
5480 *user_handle_out = user_handle;
5482 return ret;
5486 q.in.user_handle = &user_handle;
5487 q.in.level = 16;
5488 q.out.info = &info;
5490 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5491 "QueryUserInfo failed");
5492 if (!NT_STATUS_IS_OK(q.out.result)) {
5493 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5494 q.in.level, nt_errstr(q.out.result));
5495 ret = false;
5496 } else {
5497 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5498 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5499 info->info16.acct_flags,
5500 acct_flags);
5501 ret = false;
5505 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5506 domain_sid, acct_flags, name.string, which_ops,
5507 machine_credentials)) {
5508 ret = false;
5511 if (user_handle_out) {
5512 *user_handle_out = user_handle;
5513 } else {
5514 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5516 d.in.user_handle = &user_handle;
5517 d.out.user_handle = &user_handle;
5519 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5520 "DeleteUser failed");
5521 if (!NT_STATUS_IS_OK(d.out.result)) {
5522 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5523 ret = false;
5529 talloc_free(user_ctx);
5531 return ret;
5535 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5536 struct policy_handle *domain_handle,
5537 struct dom_sid *domain_sid,
5538 enum torture_samr_choice which_ops,
5539 struct cli_credentials *machine_credentials)
5541 struct samr_CreateUser2 r;
5542 struct samr_QueryUserInfo q;
5543 union samr_UserInfo *info;
5544 struct samr_DeleteUser d;
5545 struct policy_handle user_handle;
5546 uint32_t rid;
5547 struct lsa_String name;
5548 bool ret = true;
5549 int i;
5550 struct dcerpc_binding_handle *b = p->binding_handle;
5552 struct {
5553 uint32_t acct_flags;
5554 const char *account_name;
5555 NTSTATUS nt_status;
5556 } account_types[] = {
5557 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5558 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5559 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5560 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5561 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5562 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5563 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5564 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5565 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5566 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5567 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5568 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5569 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5570 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5571 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5574 for (i = 0; account_types[i].account_name; i++) {
5575 TALLOC_CTX *user_ctx;
5576 uint32_t acct_flags = account_types[i].acct_flags;
5577 uint32_t access_granted;
5578 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5579 init_lsa_String(&name, account_types[i].account_name);
5581 r.in.domain_handle = domain_handle;
5582 r.in.account_name = &name;
5583 r.in.acct_flags = acct_flags;
5584 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5585 r.out.user_handle = &user_handle;
5586 r.out.access_granted = &access_granted;
5587 r.out.rid = &rid;
5589 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5591 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5592 "CreateUser2 failed");
5594 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5595 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5596 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5597 continue;
5598 } else {
5599 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5600 nt_errstr(r.out.result));
5601 ret = false;
5602 continue;
5606 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5607 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5608 talloc_free(user_ctx);
5609 ret = false;
5610 continue;
5612 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5613 "CreateUser2 failed");
5616 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5617 torture_result(tctx, TORTURE_FAIL, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5618 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5619 ret = false;
5622 if (NT_STATUS_IS_OK(r.out.result)) {
5623 q.in.user_handle = &user_handle;
5624 q.in.level = 5;
5625 q.out.info = &info;
5627 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5628 "QueryUserInfo failed");
5629 if (!NT_STATUS_IS_OK(q.out.result)) {
5630 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5631 q.in.level, nt_errstr(q.out.result));
5632 ret = false;
5633 } else {
5634 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5635 if (acct_flags == ACB_NORMAL) {
5636 expected_flags |= ACB_PW_EXPIRED;
5638 if ((info->info5.acct_flags) != expected_flags) {
5639 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5640 info->info5.acct_flags,
5641 expected_flags);
5642 ret = false;
5644 switch (acct_flags) {
5645 case ACB_SVRTRUST:
5646 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5647 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5648 DOMAIN_RID_DCS, info->info5.primary_gid);
5649 ret = false;
5651 break;
5652 case ACB_WSTRUST:
5653 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5654 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5655 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5656 ret = false;
5658 break;
5659 case ACB_NORMAL:
5660 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5661 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5662 DOMAIN_RID_USERS, info->info5.primary_gid);
5663 ret = false;
5665 break;
5669 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5670 domain_sid, acct_flags, name.string, which_ops,
5671 machine_credentials)) {
5672 ret = false;
5675 if (!ndr_policy_handle_empty(&user_handle)) {
5676 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5678 d.in.user_handle = &user_handle;
5679 d.out.user_handle = &user_handle;
5681 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5682 "DeleteUser failed");
5683 if (!NT_STATUS_IS_OK(d.out.result)) {
5684 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5685 ret = false;
5689 talloc_free(user_ctx);
5692 return ret;
5695 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5696 struct torture_context *tctx,
5697 struct policy_handle *handle)
5699 struct samr_QueryAliasInfo r;
5700 union samr_AliasInfo *info;
5701 uint16_t levels[] = {1, 2, 3};
5702 int i;
5703 bool ret = true;
5705 for (i=0;i<ARRAY_SIZE(levels);i++) {
5706 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5708 r.in.alias_handle = handle;
5709 r.in.level = levels[i];
5710 r.out.info = &info;
5712 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5713 "QueryAliasInfo failed");
5714 if (!NT_STATUS_IS_OK(r.out.result)) {
5715 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
5716 levels[i], nt_errstr(r.out.result));
5717 ret = false;
5721 return ret;
5724 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5725 struct torture_context *tctx,
5726 struct policy_handle *handle)
5728 struct samr_QueryGroupInfo r;
5729 union samr_GroupInfo *info;
5730 uint16_t levels[] = {1, 2, 3, 4, 5};
5731 int i;
5732 bool ret = true;
5734 for (i=0;i<ARRAY_SIZE(levels);i++) {
5735 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5737 r.in.group_handle = handle;
5738 r.in.level = levels[i];
5739 r.out.info = &info;
5741 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5742 "QueryGroupInfo failed");
5743 if (!NT_STATUS_IS_OK(r.out.result)) {
5744 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
5745 levels[i], nt_errstr(r.out.result));
5746 ret = false;
5750 return ret;
5753 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5754 struct torture_context *tctx,
5755 struct policy_handle *handle)
5757 struct samr_QueryGroupMember r;
5758 struct samr_RidAttrArray *rids = NULL;
5759 bool ret = true;
5761 torture_comment(tctx, "Testing QueryGroupMember\n");
5763 r.in.group_handle = handle;
5764 r.out.rids = &rids;
5766 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5767 "QueryGroupMember failed");
5768 if (!NT_STATUS_IS_OK(r.out.result)) {
5769 torture_result(tctx, TORTURE_FAIL, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
5770 ret = false;
5773 return ret;
5777 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5778 struct torture_context *tctx,
5779 struct policy_handle *handle)
5781 struct samr_QueryGroupInfo r;
5782 union samr_GroupInfo *info;
5783 struct samr_SetGroupInfo s;
5784 uint16_t levels[] = {1, 2, 3, 4};
5785 uint16_t set_ok[] = {0, 1, 1, 1};
5786 int i;
5787 bool ret = true;
5789 for (i=0;i<ARRAY_SIZE(levels);i++) {
5790 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5792 r.in.group_handle = handle;
5793 r.in.level = levels[i];
5794 r.out.info = &info;
5796 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5797 "QueryGroupInfo failed");
5798 if (!NT_STATUS_IS_OK(r.out.result)) {
5799 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
5800 levels[i], nt_errstr(r.out.result));
5801 ret = false;
5804 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5806 s.in.group_handle = handle;
5807 s.in.level = levels[i];
5808 s.in.info = *r.out.info;
5810 #if 0
5811 /* disabled this, as it changes the name only from the point of view of samr,
5812 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5813 the name is still reserved, so creating the old name fails, but deleting by the old name
5814 also fails */
5815 if (s.in.level == 2) {
5816 init_lsa_String(&s.in.info->string, "NewName");
5818 #endif
5820 if (s.in.level == 4) {
5821 init_lsa_String(&s.in.info->description, "test description");
5824 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5825 "SetGroupInfo failed");
5826 if (set_ok[i]) {
5827 if (!NT_STATUS_IS_OK(s.out.result)) {
5828 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u failed - %s\n",
5829 r.in.level, nt_errstr(s.out.result));
5830 ret = false;
5831 continue;
5833 } else {
5834 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5835 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5836 r.in.level, nt_errstr(s.out.result));
5837 ret = false;
5838 continue;
5843 return ret;
5846 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5847 struct torture_context *tctx,
5848 struct policy_handle *handle)
5850 struct samr_QueryUserInfo r;
5851 union samr_UserInfo *info;
5852 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5853 11, 12, 13, 14, 16, 17, 20, 21};
5854 int i;
5855 bool ret = true;
5857 for (i=0;i<ARRAY_SIZE(levels);i++) {
5858 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5860 r.in.user_handle = handle;
5861 r.in.level = levels[i];
5862 r.out.info = &info;
5864 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5865 "QueryUserInfo failed");
5866 if (!NT_STATUS_IS_OK(r.out.result)) {
5867 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5868 levels[i], nt_errstr(r.out.result));
5869 ret = false;
5873 return ret;
5876 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5877 struct torture_context *tctx,
5878 struct policy_handle *handle)
5880 struct samr_QueryUserInfo2 r;
5881 union samr_UserInfo *info;
5882 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5883 11, 12, 13, 14, 16, 17, 20, 21};
5884 int i;
5885 bool ret = true;
5887 for (i=0;i<ARRAY_SIZE(levels);i++) {
5888 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5890 r.in.user_handle = handle;
5891 r.in.level = levels[i];
5892 r.out.info = &info;
5894 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5895 "QueryUserInfo2 failed");
5896 if (!NT_STATUS_IS_OK(r.out.result)) {
5897 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo2 level %u failed - %s\n",
5898 levels[i], nt_errstr(r.out.result));
5899 ret = false;
5903 return ret;
5906 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5907 struct torture_context *tctx,
5908 struct policy_handle *handle, uint32_t rid)
5910 struct samr_OpenUser r;
5911 struct policy_handle user_handle;
5912 bool ret = true;
5914 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5916 r.in.domain_handle = handle;
5917 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5918 r.in.rid = rid;
5919 r.out.user_handle = &user_handle;
5921 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5922 "OpenUser failed");
5923 if (!NT_STATUS_IS_OK(r.out.result)) {
5924 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5925 return false;
5928 if (!test_QuerySecurity(b, tctx, &user_handle)) {
5929 ret = false;
5932 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5933 ret = false;
5936 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5937 ret = false;
5940 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5941 ret = false;
5944 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5945 ret = false;
5948 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5949 ret = false;
5952 return ret;
5955 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5956 struct torture_context *tctx,
5957 struct policy_handle *handle, uint32_t rid)
5959 struct samr_OpenGroup r;
5960 struct policy_handle group_handle;
5961 bool ret = true;
5963 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5965 r.in.domain_handle = handle;
5966 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5967 r.in.rid = rid;
5968 r.out.group_handle = &group_handle;
5970 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5971 "OpenGroup failed");
5972 if (!NT_STATUS_IS_OK(r.out.result)) {
5973 torture_result(tctx, TORTURE_FAIL, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5974 return false;
5977 if (!torture_setting_bool(tctx, "samba3", false)) {
5978 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5979 ret = false;
5983 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5984 ret = false;
5987 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5988 ret = false;
5991 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5992 ret = false;
5995 return ret;
5998 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5999 struct torture_context *tctx,
6000 struct policy_handle *handle, uint32_t rid)
6002 struct samr_OpenAlias r;
6003 struct policy_handle alias_handle;
6004 bool ret = true;
6006 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
6008 r.in.domain_handle = handle;
6009 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6010 r.in.rid = rid;
6011 r.out.alias_handle = &alias_handle;
6013 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
6014 "OpenAlias failed");
6015 if (!NT_STATUS_IS_OK(r.out.result)) {
6016 torture_result(tctx, TORTURE_FAIL, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6017 return false;
6020 if (!torture_setting_bool(tctx, "samba3", false)) {
6021 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
6022 ret = false;
6026 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6027 ret = false;
6030 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6031 ret = false;
6034 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6035 ret = false;
6038 return ret;
6041 static bool check_mask(struct dcerpc_binding_handle *b,
6042 struct torture_context *tctx,
6043 struct policy_handle *handle, uint32_t rid,
6044 uint32_t acct_flag_mask)
6046 struct samr_OpenUser r;
6047 struct samr_QueryUserInfo q;
6048 union samr_UserInfo *info;
6049 struct policy_handle user_handle;
6050 bool ret = true;
6052 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6054 r.in.domain_handle = handle;
6055 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6056 r.in.rid = rid;
6057 r.out.user_handle = &user_handle;
6059 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6060 "OpenUser failed");
6061 if (!NT_STATUS_IS_OK(r.out.result)) {
6062 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6063 return false;
6066 q.in.user_handle = &user_handle;
6067 q.in.level = 16;
6068 q.out.info = &info;
6070 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6071 "QueryUserInfo failed");
6072 if (!NT_STATUS_IS_OK(q.out.result)) {
6073 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed - %s\n",
6074 nt_errstr(q.out.result));
6075 ret = false;
6076 } else {
6077 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
6078 torture_result(tctx, TORTURE_FAIL, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
6079 acct_flag_mask, info->info16.acct_flags, rid);
6080 ret = false;
6084 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6085 ret = false;
6088 return ret;
6091 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
6092 struct torture_context *tctx,
6093 struct policy_handle *handle)
6095 struct samr_EnumDomainUsers r;
6096 uint32_t mask, resume_handle=0;
6097 int i, mask_idx;
6098 bool ret = true;
6099 struct samr_LookupNames n;
6100 struct samr_LookupRids lr ;
6101 struct lsa_Strings names;
6102 struct samr_Ids rids, types;
6103 struct samr_SamArray *sam = NULL;
6104 uint32_t num_entries = 0;
6106 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
6107 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
6108 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
6109 ACB_PWNOEXP, 0};
6111 torture_comment(tctx, "Testing EnumDomainUsers\n");
6113 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
6114 r.in.domain_handle = handle;
6115 r.in.resume_handle = &resume_handle;
6116 r.in.acct_flags = mask = masks[mask_idx];
6117 r.in.max_size = (uint32_t)-1;
6118 r.out.resume_handle = &resume_handle;
6119 r.out.num_entries = &num_entries;
6120 r.out.sam = &sam;
6122 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
6123 "EnumDomainUsers failed");
6124 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6125 !NT_STATUS_IS_OK(r.out.result)) {
6126 torture_result(tctx, TORTURE_FAIL, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
6127 return false;
6130 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6132 if (sam->count == 0) {
6133 continue;
6136 for (i=0;i<sam->count;i++) {
6137 if (mask) {
6138 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6139 ret = false;
6141 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6142 ret = false;
6147 torture_comment(tctx, "Testing LookupNames\n");
6148 n.in.domain_handle = handle;
6149 n.in.num_names = sam->count;
6150 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6151 n.out.rids = &rids;
6152 n.out.types = &types;
6153 for (i=0;i<sam->count;i++) {
6154 n.in.names[i].string = sam->entries[i].name.string;
6156 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6157 "LookupNames failed");
6158 if (!NT_STATUS_IS_OK(n.out.result)) {
6159 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6160 ret = false;
6164 torture_comment(tctx, "Testing LookupRids\n");
6165 lr.in.domain_handle = handle;
6166 lr.in.num_rids = sam->count;
6167 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6168 lr.out.names = &names;
6169 lr.out.types = &types;
6170 for (i=0;i<sam->count;i++) {
6171 lr.in.rids[i] = sam->entries[i].idx;
6173 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6174 "LookupRids failed");
6175 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6177 return ret;
6181 try blasting the server with a bunch of sync requests
6183 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6184 struct policy_handle *handle)
6186 struct samr_EnumDomainUsers r;
6187 uint32_t resume_handle=0;
6188 int i;
6189 #define ASYNC_COUNT 100
6190 struct tevent_req *req[ASYNC_COUNT];
6192 if (!torture_setting_bool(tctx, "dangerous", false)) {
6193 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6196 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6198 r.in.domain_handle = handle;
6199 r.in.resume_handle = &resume_handle;
6200 r.in.acct_flags = 0;
6201 r.in.max_size = (uint32_t)-1;
6202 r.out.resume_handle = &resume_handle;
6204 for (i=0;i<ASYNC_COUNT;i++) {
6205 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6208 for (i=0;i<ASYNC_COUNT;i++) {
6209 tevent_req_poll(req[i], tctx->ev);
6210 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6211 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6212 i, nt_errstr(r.out.result)));
6215 torture_comment(tctx, "%d async requests OK\n", i);
6217 return true;
6220 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6221 struct torture_context *tctx,
6222 struct policy_handle *handle)
6224 struct samr_EnumDomainGroups r;
6225 uint32_t resume_handle=0;
6226 struct samr_SamArray *sam = NULL;
6227 uint32_t num_entries = 0;
6228 int i;
6229 bool ret = true;
6230 bool universal_group_found = false;
6232 torture_comment(tctx, "Testing EnumDomainGroups\n");
6234 r.in.domain_handle = handle;
6235 r.in.resume_handle = &resume_handle;
6236 r.in.max_size = (uint32_t)-1;
6237 r.out.resume_handle = &resume_handle;
6238 r.out.num_entries = &num_entries;
6239 r.out.sam = &sam;
6241 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6242 "EnumDomainGroups failed");
6243 if (!NT_STATUS_IS_OK(r.out.result)) {
6244 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6245 return false;
6248 if (!sam) {
6249 return false;
6252 for (i=0;i<sam->count;i++) {
6253 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6254 ret = false;
6256 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6257 "Enterprise Admins") == 0)) {
6258 universal_group_found = true;
6262 /* when we are running this on s4 we should get back at least the
6263 * "Enterprise Admins" universal group. If we don't get a group entry
6264 * at all we probably are performing the test on the builtin domain.
6265 * So ignore this case. */
6266 if (torture_setting_bool(tctx, "samba4", false)) {
6267 if ((sam->count > 0) && (!universal_group_found)) {
6268 ret = false;
6272 return ret;
6275 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6276 struct torture_context *tctx,
6277 struct policy_handle *handle)
6279 struct samr_EnumDomainAliases r;
6280 uint32_t resume_handle=0;
6281 struct samr_SamArray *sam = NULL;
6282 uint32_t num_entries = 0;
6283 int i;
6284 bool ret = true;
6286 torture_comment(tctx, "Testing EnumDomainAliases\n");
6288 r.in.domain_handle = handle;
6289 r.in.resume_handle = &resume_handle;
6290 r.in.max_size = (uint32_t)-1;
6291 r.out.sam = &sam;
6292 r.out.num_entries = &num_entries;
6293 r.out.resume_handle = &resume_handle;
6295 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6296 "EnumDomainAliases failed");
6297 if (!NT_STATUS_IS_OK(r.out.result)) {
6298 torture_result(tctx, TORTURE_FAIL, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6299 return false;
6302 if (!sam) {
6303 return false;
6306 for (i=0;i<sam->count;i++) {
6307 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6308 ret = false;
6312 return ret;
6315 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6316 struct torture_context *tctx,
6317 struct policy_handle *handle)
6319 struct samr_GetDisplayEnumerationIndex r;
6320 bool ret = true;
6321 uint16_t levels[] = {1, 2, 3, 4, 5};
6322 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6323 struct lsa_String name;
6324 uint32_t idx = 0;
6325 int i;
6327 for (i=0;i<ARRAY_SIZE(levels);i++) {
6328 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6330 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6332 r.in.domain_handle = handle;
6333 r.in.level = levels[i];
6334 r.in.name = &name;
6335 r.out.idx = &idx;
6337 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6338 "GetDisplayEnumerationIndex failed");
6340 if (ok_lvl[i] &&
6341 !NT_STATUS_IS_OK(r.out.result) &&
6342 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6343 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6344 levels[i], nt_errstr(r.out.result));
6345 ret = false;
6348 init_lsa_String(&name, "zzzzzzzz");
6350 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6351 "GetDisplayEnumerationIndex failed");
6353 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6354 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6355 levels[i], nt_errstr(r.out.result));
6356 ret = false;
6360 return ret;
6363 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6364 struct torture_context *tctx,
6365 struct policy_handle *handle)
6367 struct samr_GetDisplayEnumerationIndex2 r;
6368 bool ret = true;
6369 uint16_t levels[] = {1, 2, 3, 4, 5};
6370 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6371 struct lsa_String name;
6372 uint32_t idx = 0;
6373 int i;
6375 for (i=0;i<ARRAY_SIZE(levels);i++) {
6376 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6378 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6380 r.in.domain_handle = handle;
6381 r.in.level = levels[i];
6382 r.in.name = &name;
6383 r.out.idx = &idx;
6385 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6386 "GetDisplayEnumerationIndex2 failed");
6387 if (ok_lvl[i] &&
6388 !NT_STATUS_IS_OK(r.out.result) &&
6389 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6390 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6391 levels[i], nt_errstr(r.out.result));
6392 ret = false;
6395 init_lsa_String(&name, "zzzzzzzz");
6397 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6398 "GetDisplayEnumerationIndex2 failed");
6399 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6400 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6401 levels[i], nt_errstr(r.out.result));
6402 ret = false;
6406 return ret;
6409 #define STRING_EQUAL_QUERY(s1, s2, user) \
6410 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6411 /* odd, but valid */ \
6412 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6413 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: %s != %s (%s)\n", \
6414 #s1, user.string, s1.string, s2.string, __location__); \
6415 ret = false; \
6417 #define INT_EQUAL_QUERY(s1, s2, user) \
6418 if (s1 != s2) { \
6419 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6420 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6421 ret = false; \
6424 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6425 struct torture_context *tctx,
6426 struct samr_QueryDisplayInfo *querydisplayinfo,
6427 bool *seen_testuser)
6429 struct samr_OpenUser r;
6430 struct samr_QueryUserInfo q;
6431 union samr_UserInfo *info;
6432 struct policy_handle user_handle;
6433 int i, ret = true;
6434 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6435 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6436 for (i = 0; ; i++) {
6437 switch (querydisplayinfo->in.level) {
6438 case 1:
6439 if (i >= querydisplayinfo->out.info->info1.count) {
6440 return ret;
6442 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6443 break;
6444 case 2:
6445 if (i >= querydisplayinfo->out.info->info2.count) {
6446 return ret;
6448 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6449 break;
6450 case 3:
6451 /* Groups */
6452 case 4:
6453 case 5:
6454 /* Not interested in validating just the account name */
6455 return true;
6458 r.out.user_handle = &user_handle;
6460 switch (querydisplayinfo->in.level) {
6461 case 1:
6462 case 2:
6463 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6464 "OpenUser failed");
6465 if (!NT_STATUS_IS_OK(r.out.result)) {
6466 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6467 return false;
6471 q.in.user_handle = &user_handle;
6472 q.in.level = 21;
6473 q.out.info = &info;
6474 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6475 "QueryUserInfo failed");
6476 if (!NT_STATUS_IS_OK(r.out.result)) {
6477 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6478 return false;
6481 switch (querydisplayinfo->in.level) {
6482 case 1:
6483 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6484 *seen_testuser = true;
6486 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6487 info->info21.full_name, info->info21.account_name);
6488 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6489 info->info21.account_name, info->info21.account_name);
6490 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6491 info->info21.description, info->info21.account_name);
6492 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6493 info->info21.rid, info->info21.account_name);
6494 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6495 info->info21.acct_flags, info->info21.account_name);
6497 break;
6498 case 2:
6499 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6500 info->info21.account_name, info->info21.account_name);
6501 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6502 info->info21.description, info->info21.account_name);
6503 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6504 info->info21.rid, info->info21.account_name);
6505 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6506 info->info21.acct_flags, info->info21.account_name);
6508 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6509 torture_result(tctx, TORTURE_FAIL, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6510 info->info21.account_name.string);
6513 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6514 torture_result(tctx, TORTURE_FAIL, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6515 info->info21.account_name.string,
6516 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6517 info->info21.acct_flags);
6518 return false;
6521 break;
6524 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6525 return false;
6528 return ret;
6531 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6532 struct torture_context *tctx,
6533 struct policy_handle *handle)
6535 struct samr_QueryDisplayInfo r;
6536 struct samr_QueryDomainInfo dom_info;
6537 union samr_DomainInfo *info = NULL;
6538 bool ret = true;
6539 uint16_t levels[] = {1, 2, 3, 4, 5};
6540 int i;
6541 bool seen_testuser = false;
6542 uint32_t total_size;
6543 uint32_t returned_size;
6544 union samr_DispInfo disp_info;
6547 for (i=0;i<ARRAY_SIZE(levels);i++) {
6548 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6550 r.in.start_idx = 0;
6551 r.out.result = STATUS_MORE_ENTRIES;
6552 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6553 r.in.domain_handle = handle;
6554 r.in.level = levels[i];
6555 r.in.max_entries = 2;
6556 r.in.buf_size = (uint32_t)-1;
6557 r.out.total_size = &total_size;
6558 r.out.returned_size = &returned_size;
6559 r.out.info = &disp_info;
6561 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6562 "QueryDisplayInfo failed");
6563 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6564 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
6565 levels[i], nt_errstr(r.out.result));
6566 ret = false;
6568 switch (r.in.level) {
6569 case 1:
6570 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6571 ret = false;
6573 r.in.start_idx += r.out.info->info1.count;
6574 break;
6575 case 2:
6576 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6577 ret = false;
6579 r.in.start_idx += r.out.info->info2.count;
6580 break;
6581 case 3:
6582 r.in.start_idx += r.out.info->info3.count;
6583 break;
6584 case 4:
6585 r.in.start_idx += r.out.info->info4.count;
6586 break;
6587 case 5:
6588 r.in.start_idx += r.out.info->info5.count;
6589 break;
6592 dom_info.in.domain_handle = handle;
6593 dom_info.in.level = 2;
6594 dom_info.out.info = &info;
6596 /* Check number of users returned is correct */
6597 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6598 "QueryDomainInfo failed");
6599 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6600 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6601 r.in.level, nt_errstr(dom_info.out.result));
6602 ret = false;
6603 break;
6605 switch (r.in.level) {
6606 case 1:
6607 case 4:
6608 if (info->general.num_users < r.in.start_idx) {
6609 /* On AD deployments this numbers don't match
6610 * since QueryDisplayInfo returns universal and
6611 * global groups, QueryDomainInfo only global
6612 * ones. */
6613 if (torture_setting_bool(tctx, "samba3", false)) {
6614 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6615 r.in.start_idx, info->general.num_groups,
6616 info->general.domain_name.string);
6617 ret = false;
6620 if (!seen_testuser) {
6621 struct policy_handle user_handle;
6622 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6623 torture_result(tctx, TORTURE_FAIL, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6624 info->general.domain_name.string);
6625 ret = false;
6626 test_samr_handle_Close(b, tctx, &user_handle);
6629 break;
6630 case 3:
6631 case 5:
6632 if (info->general.num_groups != r.in.start_idx) {
6633 /* On AD deployments this numbers don't match
6634 * since QueryDisplayInfo returns universal and
6635 * global groups, QueryDomainInfo only global
6636 * ones. */
6637 if (torture_setting_bool(tctx, "samba3", false)) {
6638 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6639 r.in.start_idx, info->general.num_groups,
6640 info->general.domain_name.string);
6641 ret = false;
6645 break;
6650 return ret;
6653 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6654 struct torture_context *tctx,
6655 struct policy_handle *handle)
6657 struct samr_QueryDisplayInfo2 r;
6658 bool ret = true;
6659 uint16_t levels[] = {1, 2, 3, 4, 5};
6660 int i;
6661 uint32_t total_size;
6662 uint32_t returned_size;
6663 union samr_DispInfo info;
6665 for (i=0;i<ARRAY_SIZE(levels);i++) {
6666 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6668 r.in.domain_handle = handle;
6669 r.in.level = levels[i];
6670 r.in.start_idx = 0;
6671 r.in.max_entries = 1000;
6672 r.in.buf_size = (uint32_t)-1;
6673 r.out.total_size = &total_size;
6674 r.out.returned_size = &returned_size;
6675 r.out.info = &info;
6677 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6678 "QueryDisplayInfo2 failed");
6679 if (!NT_STATUS_IS_OK(r.out.result)) {
6680 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo2 level %u failed - %s\n",
6681 levels[i], nt_errstr(r.out.result));
6682 ret = false;
6686 return ret;
6689 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6690 struct torture_context *tctx,
6691 struct policy_handle *handle)
6693 struct samr_QueryDisplayInfo3 r;
6694 bool ret = true;
6695 uint16_t levels[] = {1, 2, 3, 4, 5};
6696 int i;
6697 uint32_t total_size;
6698 uint32_t returned_size;
6699 union samr_DispInfo info;
6701 for (i=0;i<ARRAY_SIZE(levels);i++) {
6702 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6704 r.in.domain_handle = handle;
6705 r.in.level = levels[i];
6706 r.in.start_idx = 0;
6707 r.in.max_entries = 1000;
6708 r.in.buf_size = (uint32_t)-1;
6709 r.out.total_size = &total_size;
6710 r.out.returned_size = &returned_size;
6711 r.out.info = &info;
6713 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6714 "QueryDisplayInfo3 failed");
6715 if (!NT_STATUS_IS_OK(r.out.result)) {
6716 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo3 level %u failed - %s\n",
6717 levels[i], nt_errstr(r.out.result));
6718 ret = false;
6722 return ret;
6726 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6727 struct torture_context *tctx,
6728 struct policy_handle *handle)
6730 struct samr_QueryDisplayInfo r;
6731 bool ret = true;
6732 uint32_t total_size;
6733 uint32_t returned_size;
6734 union samr_DispInfo info;
6736 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6738 r.in.domain_handle = handle;
6739 r.in.level = 1;
6740 r.in.start_idx = 0;
6741 r.in.max_entries = 1;
6742 r.in.buf_size = (uint32_t)-1;
6743 r.out.total_size = &total_size;
6744 r.out.returned_size = &returned_size;
6745 r.out.info = &info;
6747 do {
6748 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6749 "QueryDisplayInfo failed");
6750 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6751 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6752 torture_result(tctx, TORTURE_FAIL, "expected idx %d but got %d\n",
6753 r.in.start_idx + 1,
6754 r.out.info->info1.entries[0].idx);
6755 break;
6758 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6759 !NT_STATUS_IS_OK(r.out.result)) {
6760 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
6761 r.in.level, nt_errstr(r.out.result));
6762 ret = false;
6763 break;
6765 r.in.start_idx++;
6766 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6767 NT_STATUS_IS_OK(r.out.result)) &&
6768 *r.out.returned_size != 0);
6770 return ret;
6773 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6774 struct torture_context *tctx,
6775 struct policy_handle *handle)
6777 struct samr_QueryDomainInfo r;
6778 union samr_DomainInfo *info = NULL;
6779 struct samr_SetDomainInfo s;
6780 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6781 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6782 int i;
6783 bool ret = true;
6784 struct dcerpc_binding_handle *b = p->binding_handle;
6785 const char *domain_comment = talloc_asprintf(tctx,
6786 "Tortured by Samba4 RPC-SAMR: %s",
6787 timestring(tctx, time(NULL)));
6789 s.in.domain_handle = handle;
6790 s.in.level = 4;
6791 s.in.info = talloc(tctx, union samr_DomainInfo);
6793 s.in.info->oem.oem_information.string = domain_comment;
6794 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6795 "SetDomainInfo failed");
6796 if (!NT_STATUS_IS_OK(s.out.result)) {
6797 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u (set comment) failed - %s\n",
6798 s.in.level, nt_errstr(s.out.result));
6799 return false;
6802 for (i=0;i<ARRAY_SIZE(levels);i++) {
6803 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6805 r.in.domain_handle = handle;
6806 r.in.level = levels[i];
6807 r.out.info = &info;
6809 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6810 "QueryDomainInfo failed");
6811 if (!NT_STATUS_IS_OK(r.out.result)) {
6812 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6813 r.in.level, nt_errstr(r.out.result));
6814 ret = false;
6815 continue;
6818 switch (levels[i]) {
6819 case 2:
6820 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6821 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6822 levels[i], info->general.oem_information.string, domain_comment);
6823 if (!torture_setting_bool(tctx, "samba3", false)) {
6824 ret = false;
6827 if (!info->general.primary.string) {
6828 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
6829 levels[i]);
6830 ret = false;
6831 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6832 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6833 if (torture_setting_bool(tctx, "samba3", false)) {
6834 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6835 levels[i], info->general.primary.string, dcerpc_server_name(p));
6839 break;
6840 case 4:
6841 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6842 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6843 levels[i], info->oem.oem_information.string, domain_comment);
6844 if (!torture_setting_bool(tctx, "samba3", false)) {
6845 ret = false;
6848 break;
6849 case 6:
6850 if (!info->info6.primary.string) {
6851 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
6852 levels[i]);
6853 ret = false;
6855 break;
6856 case 11:
6857 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6858 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6859 levels[i], info->general2.general.oem_information.string, domain_comment);
6860 if (!torture_setting_bool(tctx, "samba3", false)) {
6861 ret = false;
6864 break;
6867 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6869 s.in.domain_handle = handle;
6870 s.in.level = levels[i];
6871 s.in.info = info;
6873 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6874 "SetDomainInfo failed");
6875 if (set_ok[i]) {
6876 if (!NT_STATUS_IS_OK(s.out.result)) {
6877 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u failed - %s\n",
6878 r.in.level, nt_errstr(s.out.result));
6879 ret = false;
6880 continue;
6882 } else {
6883 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6884 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6885 r.in.level, nt_errstr(s.out.result));
6886 ret = false;
6887 continue;
6891 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6892 "QueryDomainInfo failed");
6893 if (!NT_STATUS_IS_OK(r.out.result)) {
6894 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6895 r.in.level, nt_errstr(r.out.result));
6896 ret = false;
6897 continue;
6901 return ret;
6905 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6906 struct torture_context *tctx,
6907 struct policy_handle *handle)
6909 struct samr_QueryDomainInfo2 r;
6910 union samr_DomainInfo *info = NULL;
6911 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6912 int i;
6913 bool ret = true;
6915 for (i=0;i<ARRAY_SIZE(levels);i++) {
6916 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6918 r.in.domain_handle = handle;
6919 r.in.level = levels[i];
6920 r.out.info = &info;
6922 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6923 "QueryDomainInfo2 failed");
6924 if (!NT_STATUS_IS_OK(r.out.result)) {
6925 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo2 level %u failed - %s\n",
6926 r.in.level, nt_errstr(r.out.result));
6927 ret = false;
6928 continue;
6932 return true;
6935 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6936 set of group names. */
6937 static bool test_GroupList(struct dcerpc_binding_handle *b,
6938 struct torture_context *tctx,
6939 struct dom_sid *domain_sid,
6940 struct policy_handle *handle)
6942 struct samr_EnumDomainGroups q1;
6943 struct samr_QueryDisplayInfo q2;
6944 NTSTATUS status;
6945 uint32_t resume_handle=0;
6946 struct samr_SamArray *sam = NULL;
6947 uint32_t num_entries = 0;
6948 int i;
6949 bool ret = true;
6950 uint32_t total_size;
6951 uint32_t returned_size;
6952 union samr_DispInfo info;
6954 int num_names = 0;
6955 const char **names = NULL;
6957 bool builtin_domain = dom_sid_compare(domain_sid,
6958 &global_sid_Builtin) == 0;
6960 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6962 q1.in.domain_handle = handle;
6963 q1.in.resume_handle = &resume_handle;
6964 q1.in.max_size = 5;
6965 q1.out.resume_handle = &resume_handle;
6966 q1.out.num_entries = &num_entries;
6967 q1.out.sam = &sam;
6969 status = STATUS_MORE_ENTRIES;
6970 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6971 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6972 "EnumDomainGroups failed");
6973 status = q1.out.result;
6975 if (!NT_STATUS_IS_OK(status) &&
6976 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6977 break;
6979 for (i=0; i<*q1.out.num_entries; i++) {
6980 add_string_to_array(tctx,
6981 sam->entries[i].name.string,
6982 &names, &num_names);
6986 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6988 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6990 if (builtin_domain) {
6991 torture_assert(tctx, num_names == 0,
6992 "EnumDomainGroups shouldn't return any group in the builtin domain!");
6995 q2.in.domain_handle = handle;
6996 q2.in.level = 5;
6997 q2.in.start_idx = 0;
6998 q2.in.max_entries = 5;
6999 q2.in.buf_size = (uint32_t)-1;
7000 q2.out.total_size = &total_size;
7001 q2.out.returned_size = &returned_size;
7002 q2.out.info = &info;
7004 status = STATUS_MORE_ENTRIES;
7005 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7006 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
7007 "QueryDisplayInfo failed");
7008 status = q2.out.result;
7009 if (!NT_STATUS_IS_OK(status) &&
7010 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7011 break;
7013 for (i=0; i<q2.out.info->info5.count; i++) {
7014 int j;
7015 const char *name = q2.out.info->info5.entries[i].account_name.string;
7016 bool found = false;
7017 for (j=0; j<num_names; j++) {
7018 if (names[j] == NULL)
7019 continue;
7020 if (strequal(names[j], name)) {
7021 names[j] = NULL;
7022 found = true;
7023 break;
7027 if ((!found) && (!builtin_domain)) {
7028 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7029 name);
7030 ret = false;
7033 q2.in.start_idx += q2.out.info->info5.count;
7036 if (!NT_STATUS_IS_OK(status)) {
7037 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level 5 failed - %s\n",
7038 nt_errstr(status));
7039 ret = false;
7042 if (builtin_domain) {
7043 torture_assert(tctx, q2.in.start_idx != 0,
7044 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
7047 for (i=0; i<num_names; i++) {
7048 if (names[i] != NULL) {
7049 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
7050 names[i]);
7051 ret = false;
7055 return ret;
7058 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
7059 struct torture_context *tctx,
7060 struct policy_handle *group_handle)
7062 struct samr_DeleteDomainGroup d;
7064 torture_comment(tctx, "Testing DeleteDomainGroup\n");
7066 d.in.group_handle = group_handle;
7067 d.out.group_handle = group_handle;
7069 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
7070 "DeleteDomainGroup failed");
7071 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
7073 return true;
7076 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
7077 struct torture_context *tctx,
7078 struct policy_handle *domain_handle)
7080 struct samr_TestPrivateFunctionsDomain r;
7081 bool ret = true;
7083 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
7085 r.in.domain_handle = domain_handle;
7087 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
7088 "TestPrivateFunctionsDomain failed");
7089 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
7091 return ret;
7094 static bool test_RidToSid(struct dcerpc_binding_handle *b,
7095 struct torture_context *tctx,
7096 struct dom_sid *domain_sid,
7097 struct policy_handle *domain_handle)
7099 struct samr_RidToSid r;
7100 bool ret = true;
7101 struct dom_sid *calc_sid, *out_sid;
7102 int rids[] = { 0, 42, 512, 10200 };
7103 int i;
7105 for (i=0;i<ARRAY_SIZE(rids);i++) {
7106 torture_comment(tctx, "Testing RidToSid\n");
7108 calc_sid = dom_sid_dup(tctx, domain_sid);
7109 r.in.domain_handle = domain_handle;
7110 r.in.rid = rids[i];
7111 r.out.sid = &out_sid;
7113 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
7114 "RidToSid failed");
7115 if (!NT_STATUS_IS_OK(r.out.result)) {
7116 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
7117 ret = false;
7118 } else {
7119 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
7121 if (!dom_sid_equal(calc_sid, out_sid)) {
7122 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
7123 dom_sid_string(tctx, out_sid),
7124 dom_sid_string(tctx, calc_sid));
7125 ret = false;
7130 return ret;
7133 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7134 struct torture_context *tctx,
7135 struct policy_handle *domain_handle)
7137 struct samr_GetBootKeyInformation r;
7138 bool ret = true;
7139 uint32_t unknown = 0;
7140 NTSTATUS status;
7142 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7144 r.in.domain_handle = domain_handle;
7145 r.out.unknown = &unknown;
7147 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7148 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7149 status = r.out.result;
7151 if (!NT_STATUS_IS_OK(status)) {
7152 /* w2k3 seems to fail this sometimes and pass it sometimes */
7153 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7156 return ret;
7159 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7160 struct torture_context *tctx,
7161 struct policy_handle *domain_handle,
7162 struct policy_handle *group_handle)
7164 NTSTATUS status;
7165 struct samr_AddGroupMember r;
7166 struct samr_DeleteGroupMember d;
7167 struct samr_QueryGroupMember q;
7168 struct samr_RidAttrArray *rids = NULL;
7169 struct samr_SetMemberAttributesOfGroup s;
7170 uint32_t rid;
7171 bool found_member = false;
7172 int i;
7174 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7175 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7177 r.in.group_handle = group_handle;
7178 r.in.rid = rid;
7179 r.in.flags = 0; /* ??? */
7181 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7183 d.in.group_handle = group_handle;
7184 d.in.rid = rid;
7186 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7187 "DeleteGroupMember failed");
7188 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7190 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7191 "AddGroupMember failed");
7192 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7194 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7195 "AddGroupMember failed");
7196 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7198 if (torture_setting_bool(tctx, "samba4", false) ||
7199 torture_setting_bool(tctx, "samba3", false)) {
7200 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7201 } else {
7202 /* this one is quite strange. I am using random inputs in the
7203 hope of triggering an error that might give us a clue */
7205 s.in.group_handle = group_handle;
7206 s.in.unknown1 = random();
7207 s.in.unknown2 = random();
7209 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7210 "SetMemberAttributesOfGroup failed");
7211 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7214 q.in.group_handle = group_handle;
7215 q.out.rids = &rids;
7217 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7218 "QueryGroupMember failed");
7219 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7220 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7222 for (i=0; i < rids->count; i++) {
7223 if (rids->rids[i] == rid) {
7224 found_member = true;
7228 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7230 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7231 "DeleteGroupMember failed");
7232 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7234 rids = NULL;
7235 found_member = false;
7237 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7238 "QueryGroupMember failed");
7239 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7240 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7242 for (i=0; i < rids->count; i++) {
7243 if (rids->rids[i] == rid) {
7244 found_member = true;
7248 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7250 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7251 "AddGroupMember failed");
7252 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7254 return true;
7258 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7259 struct torture_context *tctx,
7260 struct policy_handle *domain_handle,
7261 const char *group_name,
7262 struct policy_handle *group_handle,
7263 struct dom_sid *domain_sid,
7264 bool test_group)
7266 struct samr_CreateDomainGroup r;
7267 uint32_t rid;
7268 struct lsa_String name;
7269 bool ret = true;
7271 init_lsa_String(&name, group_name);
7273 r.in.domain_handle = domain_handle;
7274 r.in.name = &name;
7275 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7276 r.out.group_handle = group_handle;
7277 r.out.rid = &rid;
7279 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7281 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7282 "CreateDomainGroup failed");
7284 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7285 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7286 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7287 return true;
7288 } else {
7289 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7290 nt_errstr(r.out.result));
7291 return false;
7295 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7296 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7297 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7298 nt_errstr(r.out.result));
7299 return false;
7301 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7302 "CreateDomainGroup failed");
7304 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7305 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7307 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7308 nt_errstr(r.out.result));
7309 return false;
7311 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7312 "CreateDomainGroup failed");
7314 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7316 if (!test_group) {
7317 return ret;
7320 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7321 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7322 ret = false;
7325 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7326 ret = false;
7329 return ret;
7334 its not totally clear what this does. It seems to accept any sid you like.
7336 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7337 struct torture_context *tctx,
7338 struct policy_handle *domain_handle)
7340 struct samr_RemoveMemberFromForeignDomain r;
7342 r.in.domain_handle = domain_handle;
7343 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7345 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7346 "RemoveMemberFromForeignDomain failed");
7347 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7349 return true;
7352 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7353 struct torture_context *tctx,
7354 struct policy_handle *domain_handle,
7355 uint32_t *total_num_entries_p)
7357 NTSTATUS status;
7358 struct samr_EnumDomainUsers r;
7359 uint32_t resume_handle = 0;
7360 uint32_t num_entries = 0;
7361 uint32_t total_num_entries = 0;
7362 struct samr_SamArray *sam;
7364 r.in.domain_handle = domain_handle;
7365 r.in.acct_flags = 0;
7366 r.in.max_size = (uint32_t)-1;
7367 r.in.resume_handle = &resume_handle;
7369 r.out.sam = &sam;
7370 r.out.num_entries = &num_entries;
7371 r.out.resume_handle = &resume_handle;
7373 torture_comment(tctx, "Testing EnumDomainUsers\n");
7375 do {
7376 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7377 "EnumDomainUsers failed");
7378 if (NT_STATUS_IS_ERR(r.out.result)) {
7379 torture_assert_ntstatus_ok(tctx, r.out.result,
7380 "failed to enumerate users");
7382 status = r.out.result;
7384 total_num_entries += num_entries;
7385 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7387 if (total_num_entries_p) {
7388 *total_num_entries_p = total_num_entries;
7391 return true;
7394 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7395 struct torture_context *tctx,
7396 struct policy_handle *domain_handle,
7397 uint32_t *total_num_entries_p)
7399 NTSTATUS status;
7400 struct samr_EnumDomainGroups r;
7401 uint32_t resume_handle = 0;
7402 uint32_t num_entries = 0;
7403 uint32_t total_num_entries = 0;
7404 struct samr_SamArray *sam;
7406 r.in.domain_handle = domain_handle;
7407 r.in.max_size = (uint32_t)-1;
7408 r.in.resume_handle = &resume_handle;
7410 r.out.sam = &sam;
7411 r.out.num_entries = &num_entries;
7412 r.out.resume_handle = &resume_handle;
7414 torture_comment(tctx, "Testing EnumDomainGroups\n");
7416 do {
7417 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7418 "EnumDomainGroups failed");
7419 if (NT_STATUS_IS_ERR(r.out.result)) {
7420 torture_assert_ntstatus_ok(tctx, r.out.result,
7421 "failed to enumerate groups");
7423 status = r.out.result;
7425 total_num_entries += num_entries;
7426 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7428 if (total_num_entries_p) {
7429 *total_num_entries_p = total_num_entries;
7432 return true;
7435 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7436 struct torture_context *tctx,
7437 struct policy_handle *domain_handle,
7438 uint32_t *total_num_entries_p)
7440 NTSTATUS status;
7441 struct samr_EnumDomainAliases r;
7442 uint32_t resume_handle = 0;
7443 uint32_t num_entries = 0;
7444 uint32_t total_num_entries = 0;
7445 struct samr_SamArray *sam;
7447 r.in.domain_handle = domain_handle;
7448 r.in.max_size = (uint32_t)-1;
7449 r.in.resume_handle = &resume_handle;
7451 r.out.sam = &sam;
7452 r.out.num_entries = &num_entries;
7453 r.out.resume_handle = &resume_handle;
7455 torture_comment(tctx, "Testing EnumDomainAliases\n");
7457 do {
7458 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7459 "EnumDomainAliases failed");
7460 if (NT_STATUS_IS_ERR(r.out.result)) {
7461 torture_assert_ntstatus_ok(tctx, r.out.result,
7462 "failed to enumerate aliases");
7464 status = r.out.result;
7466 total_num_entries += num_entries;
7467 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7469 if (total_num_entries_p) {
7470 *total_num_entries_p = total_num_entries;
7473 return true;
7476 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7477 struct torture_context *tctx,
7478 struct policy_handle *handle,
7479 uint16_t level,
7480 uint32_t *total_num_entries_p)
7482 NTSTATUS status;
7483 struct samr_QueryDisplayInfo r;
7484 uint32_t total_num_entries = 0;
7486 r.in.domain_handle = handle;
7487 r.in.level = level;
7488 r.in.start_idx = 0;
7489 r.in.max_entries = (uint32_t)-1;
7490 r.in.buf_size = (uint32_t)-1;
7492 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7494 do {
7495 uint32_t total_size;
7496 uint32_t returned_size;
7497 union samr_DispInfo info;
7499 r.out.total_size = &total_size;
7500 r.out.returned_size = &returned_size;
7501 r.out.info = &info;
7503 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7504 "failed to query displayinfo");
7505 if (NT_STATUS_IS_ERR(r.out.result)) {
7506 torture_assert_ntstatus_ok(tctx, r.out.result,
7507 "failed to query displayinfo");
7509 status = r.out.result;
7511 if (*r.out.returned_size == 0) {
7512 break;
7515 switch (r.in.level) {
7516 case 1:
7517 total_num_entries += info.info1.count;
7518 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7519 break;
7520 case 2:
7521 total_num_entries += info.info2.count;
7522 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7523 break;
7524 case 3:
7525 total_num_entries += info.info3.count;
7526 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7527 break;
7528 case 4:
7529 total_num_entries += info.info4.count;
7530 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7531 break;
7532 case 5:
7533 total_num_entries += info.info5.count;
7534 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7535 break;
7536 default:
7537 return false;
7540 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7542 if (total_num_entries_p) {
7543 *total_num_entries_p = total_num_entries;
7546 return true;
7549 static bool test_ManyObjects(struct dcerpc_pipe *p,
7550 struct torture_context *tctx,
7551 struct policy_handle *domain_handle,
7552 struct dom_sid *domain_sid,
7553 struct torture_samr_context *ctx)
7555 uint32_t num_total = ctx->num_objects_large_dc;
7556 uint32_t num_enum = 0;
7557 uint32_t num_disp = 0;
7558 uint32_t num_created = 0;
7559 uint32_t num_anounced = 0;
7560 uint32_t i;
7561 struct dcerpc_binding_handle *b = p->binding_handle;
7563 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7565 /* query */
7568 struct samr_QueryDomainInfo2 r;
7569 union samr_DomainInfo *info;
7570 r.in.domain_handle = domain_handle;
7571 r.in.level = 2;
7572 r.out.info = &info;
7574 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7575 "QueryDomainInfo2 failed");
7576 torture_assert_ntstatus_ok(tctx, r.out.result,
7577 "failed to query domain info");
7579 switch (ctx->choice) {
7580 case TORTURE_SAMR_MANY_ACCOUNTS:
7581 num_anounced = info->general.num_users;
7582 break;
7583 case TORTURE_SAMR_MANY_GROUPS:
7584 num_anounced = info->general.num_groups;
7585 break;
7586 case TORTURE_SAMR_MANY_ALIASES:
7587 num_anounced = info->general.num_aliases;
7588 break;
7589 default:
7590 return false;
7594 /* create */
7596 for (i=0; i < num_total; i++) {
7598 const char *name = NULL;
7600 switch (ctx->choice) {
7601 case TORTURE_SAMR_MANY_ACCOUNTS:
7602 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7603 torture_assert(tctx,
7604 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7605 "failed to create user");
7606 break;
7607 case TORTURE_SAMR_MANY_GROUPS:
7608 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7609 torture_assert(tctx,
7610 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7611 "failed to create group");
7612 break;
7613 case TORTURE_SAMR_MANY_ALIASES:
7614 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7615 torture_assert(tctx,
7616 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7617 "failed to create alias");
7618 break;
7619 default:
7620 return false;
7622 if (!ndr_policy_handle_empty(&handles[i])) {
7623 num_created++;
7627 /* enum */
7629 switch (ctx->choice) {
7630 case TORTURE_SAMR_MANY_ACCOUNTS:
7631 torture_assert(tctx,
7632 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7633 "failed to enum users");
7634 break;
7635 case TORTURE_SAMR_MANY_GROUPS:
7636 torture_assert(tctx,
7637 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7638 "failed to enum groups");
7639 break;
7640 case TORTURE_SAMR_MANY_ALIASES:
7641 torture_assert(tctx,
7642 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7643 "failed to enum aliases");
7644 break;
7645 default:
7646 return false;
7649 /* dispinfo */
7651 switch (ctx->choice) {
7652 case TORTURE_SAMR_MANY_ACCOUNTS:
7653 torture_assert(tctx,
7654 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
7655 "failed to query display info");
7656 break;
7657 case TORTURE_SAMR_MANY_GROUPS:
7658 torture_assert(tctx,
7659 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
7660 "failed to query display info");
7661 break;
7662 case TORTURE_SAMR_MANY_ALIASES:
7663 /* no aliases in dispinfo */
7664 break;
7665 default:
7666 return false;
7669 /* close or delete */
7671 for (i=0; i < num_total; i++) {
7673 if (ndr_policy_handle_empty(&handles[i])) {
7674 continue;
7677 if (torture_setting_bool(tctx, "samba3", false)) {
7678 torture_assert(tctx,
7679 test_samr_handle_Close(b, tctx, &handles[i]),
7680 "failed to close handle");
7681 } else {
7682 switch (ctx->choice) {
7683 case TORTURE_SAMR_MANY_ACCOUNTS:
7684 torture_assert(tctx,
7685 test_DeleteUser(b, tctx, &handles[i]),
7686 "failed to delete user");
7687 break;
7688 case TORTURE_SAMR_MANY_GROUPS:
7689 torture_assert(tctx,
7690 test_DeleteDomainGroup(b, tctx, &handles[i]),
7691 "failed to delete group");
7692 break;
7693 case TORTURE_SAMR_MANY_ALIASES:
7694 torture_assert(tctx,
7695 test_DeleteAlias(b, tctx, &handles[i]),
7696 "failed to delete alias");
7697 break;
7698 default:
7699 return false;
7704 talloc_free(handles);
7706 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7707 torture_comment(tctx,
7708 "unexpected number of results (%u) returned in enum call, expected %u\n",
7709 num_enum, num_anounced + num_created);
7711 torture_comment(tctx,
7712 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7713 num_disp, num_anounced + num_created);
7716 return true;
7719 static bool test_Connect(struct dcerpc_binding_handle *b,
7720 struct torture_context *tctx,
7721 struct policy_handle *handle);
7723 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7724 struct torture_samr_context *ctx, struct dom_sid *sid)
7726 struct samr_OpenDomain r;
7727 struct policy_handle domain_handle;
7728 struct policy_handle alias_handle;
7729 struct policy_handle user_handle;
7730 struct policy_handle group_handle;
7731 bool ret = true;
7732 struct dcerpc_binding_handle *b = p->binding_handle;
7734 ZERO_STRUCT(alias_handle);
7735 ZERO_STRUCT(user_handle);
7736 ZERO_STRUCT(group_handle);
7737 ZERO_STRUCT(domain_handle);
7739 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7741 r.in.connect_handle = &ctx->handle;
7742 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7743 r.in.sid = sid;
7744 r.out.domain_handle = &domain_handle;
7746 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7747 "OpenDomain failed");
7748 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7750 /* run the domain tests with the main handle closed - this tests
7751 the servers reference counting */
7752 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7754 switch (ctx->choice) {
7755 case TORTURE_SAMR_PASSWORDS:
7756 case TORTURE_SAMR_USER_PRIVILEGES:
7757 if (!torture_setting_bool(tctx, "samba3", false)) {
7758 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7760 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7761 if (!ret) {
7762 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7764 break;
7765 case TORTURE_SAMR_USER_ATTRIBUTES:
7766 if (!torture_setting_bool(tctx, "samba3", false)) {
7767 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7769 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7770 /* This test needs 'complex' users to validate */
7771 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7772 if (!ret) {
7773 torture_result(tctx, TORTURE_FAIL, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7775 break;
7776 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7777 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7778 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7779 if (!torture_setting_bool(tctx, "samba3", false)) {
7780 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7782 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7783 if (!ret) {
7784 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7786 break;
7787 case TORTURE_SAMR_MANY_ACCOUNTS:
7788 case TORTURE_SAMR_MANY_GROUPS:
7789 case TORTURE_SAMR_MANY_ALIASES:
7790 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7791 if (!ret) {
7792 torture_result(tctx, TORTURE_FAIL, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7794 break;
7795 case TORTURE_SAMR_OTHER:
7796 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7797 if (!ret) {
7798 torture_result(tctx, TORTURE_FAIL, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7800 if (!torture_setting_bool(tctx, "samba3", false)) {
7801 ret &= test_QuerySecurity(b, tctx, &domain_handle);
7803 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7804 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7805 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7806 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7807 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7808 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7809 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7810 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7811 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7812 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7813 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7814 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7815 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7817 if (torture_setting_bool(tctx, "samba4", false)) {
7818 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7819 } else {
7820 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7821 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7823 ret &= test_GroupList(b, tctx, sid, &domain_handle);
7824 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7825 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7826 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7827 if (!ret) {
7828 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7830 break;
7833 if (!ndr_policy_handle_empty(&user_handle) &&
7834 !test_DeleteUser(b, tctx, &user_handle)) {
7835 ret = false;
7838 if (!ndr_policy_handle_empty(&alias_handle) &&
7839 !test_DeleteAlias(b, tctx, &alias_handle)) {
7840 ret = false;
7843 if (!ndr_policy_handle_empty(&group_handle) &&
7844 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7845 ret = false;
7848 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7850 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7851 /* reconnect the main handle */
7853 if (!ret) {
7854 torture_result(tctx, TORTURE_FAIL, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7857 return ret;
7860 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7861 struct torture_samr_context *ctx, const char *domain)
7863 struct samr_LookupDomain r;
7864 struct dom_sid2 *sid = NULL;
7865 struct lsa_String n1;
7866 struct lsa_String n2;
7867 bool ret = true;
7868 struct dcerpc_binding_handle *b = p->binding_handle;
7870 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7872 /* check for correct error codes */
7873 r.in.connect_handle = &ctx->handle;
7874 r.in.domain_name = &n2;
7875 r.out.sid = &sid;
7876 n2.string = NULL;
7878 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7879 "LookupDomain failed");
7880 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7882 init_lsa_String(&n2, "xxNODOMAINxx");
7884 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7885 "LookupDomain failed");
7886 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7888 r.in.connect_handle = &ctx->handle;
7890 init_lsa_String(&n1, domain);
7891 r.in.domain_name = &n1;
7893 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7894 "LookupDomain failed");
7895 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7897 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7898 ret = false;
7901 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7902 ret = false;
7905 return ret;
7909 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7910 struct torture_samr_context *ctx)
7912 struct samr_EnumDomains r;
7913 uint32_t resume_handle = 0;
7914 uint32_t num_entries = 0;
7915 struct samr_SamArray *sam = NULL;
7916 int i;
7917 bool ret = true;
7918 struct dcerpc_binding_handle *b = p->binding_handle;
7920 r.in.connect_handle = &ctx->handle;
7921 r.in.resume_handle = &resume_handle;
7922 r.in.buf_size = (uint32_t)-1;
7923 r.out.resume_handle = &resume_handle;
7924 r.out.num_entries = &num_entries;
7925 r.out.sam = &sam;
7927 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7928 "EnumDomains failed");
7929 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7931 if (!*r.out.sam) {
7932 return false;
7935 for (i=0;i<sam->count;i++) {
7936 if (!test_LookupDomain(p, tctx, ctx,
7937 sam->entries[i].name.string)) {
7938 ret = false;
7942 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7943 "EnumDomains failed");
7944 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7946 return ret;
7950 static bool test_Connect(struct dcerpc_binding_handle *b,
7951 struct torture_context *tctx,
7952 struct policy_handle *handle)
7954 struct samr_Connect r;
7955 struct samr_Connect2 r2;
7956 struct samr_Connect3 r3;
7957 struct samr_Connect4 r4;
7958 struct samr_Connect5 r5;
7959 union samr_ConnectInfo info;
7960 struct policy_handle h;
7961 uint32_t level_out = 0;
7962 bool ret = true, got_handle = false;
7964 torture_comment(tctx, "Testing samr_Connect\n");
7966 r.in.system_name = NULL;
7967 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7968 r.out.connect_handle = &h;
7970 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7971 "Connect failed");
7972 if (!NT_STATUS_IS_OK(r.out.result)) {
7973 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7974 ret = false;
7975 } else {
7976 got_handle = true;
7977 *handle = h;
7980 torture_comment(tctx, "Testing samr_Connect2\n");
7982 r2.in.system_name = NULL;
7983 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7984 r2.out.connect_handle = &h;
7986 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7987 "Connect2 failed");
7988 if (!NT_STATUS_IS_OK(r2.out.result)) {
7989 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7990 ret = false;
7991 } else {
7992 if (got_handle) {
7993 test_samr_handle_Close(b, tctx, handle);
7995 got_handle = true;
7996 *handle = h;
7999 torture_comment(tctx, "Testing samr_Connect3\n");
8001 r3.in.system_name = NULL;
8002 r3.in.unknown = 0;
8003 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8004 r3.out.connect_handle = &h;
8006 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
8007 "Connect3 failed");
8008 if (!NT_STATUS_IS_OK(r3.out.result)) {
8009 torture_result(tctx, TORTURE_FAIL, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
8010 ret = false;
8011 } else {
8012 if (got_handle) {
8013 test_samr_handle_Close(b, tctx, handle);
8015 got_handle = true;
8016 *handle = h;
8019 torture_comment(tctx, "Testing samr_Connect4\n");
8021 r4.in.system_name = "";
8022 r4.in.client_version = 0;
8023 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8024 r4.out.connect_handle = &h;
8026 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8027 "Connect4 failed");
8028 if (!NT_STATUS_IS_OK(r4.out.result)) {
8029 torture_result(tctx, TORTURE_FAIL, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8030 ret = false;
8031 } else {
8032 if (got_handle) {
8033 test_samr_handle_Close(b, tctx, handle);
8035 got_handle = true;
8036 *handle = h;
8039 torture_comment(tctx, "Testing samr_Connect5\n");
8041 info.info1.client_version = 0;
8042 info.info1.unknown2 = 0;
8044 r5.in.system_name = "";
8045 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8046 r5.in.level_in = 1;
8047 r5.out.level_out = &level_out;
8048 r5.in.info_in = &info;
8049 r5.out.info_out = &info;
8050 r5.out.connect_handle = &h;
8052 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
8053 "Connect5 failed");
8054 if (!NT_STATUS_IS_OK(r5.out.result)) {
8055 torture_result(tctx, TORTURE_FAIL, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
8056 ret = false;
8057 } else {
8058 if (got_handle) {
8059 test_samr_handle_Close(b, tctx, handle);
8061 got_handle = true;
8062 *handle = h;
8065 return ret;
8069 static bool test_samr_ValidatePassword(struct torture_context *tctx,
8070 struct dcerpc_pipe *p)
8072 struct samr_ValidatePassword r;
8073 union samr_ValidatePasswordReq req;
8074 union samr_ValidatePasswordRep *repp = NULL;
8075 NTSTATUS status;
8076 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
8077 int i;
8078 struct dcerpc_binding_handle *b = p->binding_handle;
8080 torture_comment(tctx, "Testing samr_ValidatePassword\n");
8082 if (p->conn->transport.transport != NCACN_IP_TCP) {
8083 torture_comment(tctx, "samr_ValidatePassword only should succeed over NCACN_IP_TCP!\n");
8086 ZERO_STRUCT(r);
8087 r.in.level = NetValidatePasswordReset;
8088 r.in.req = &req;
8089 r.out.rep = &repp;
8091 ZERO_STRUCT(req);
8092 req.req3.account.string = "non-existent-account-aklsdji";
8094 for (i=0; passwords[i]; i++) {
8095 req.req3.password.string = passwords[i];
8097 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
8098 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
8099 torture_skip(tctx, "ValidatePassword not supported by server\n");
8101 torture_assert_ntstatus_ok(tctx, status,
8102 "samr_ValidatePassword failed");
8103 torture_assert_ntstatus_ok(tctx, r.out.result,
8104 "samr_ValidatePassword failed");
8105 torture_comment(tctx, "Server %s password '%s' with code %i\n",
8106 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
8107 req.req3.password.string, repp->ctr3.status);
8110 return true;
8113 bool torture_rpc_samr(struct torture_context *torture)
8115 NTSTATUS status;
8116 struct dcerpc_pipe *p;
8117 bool ret = true;
8118 struct torture_samr_context *ctx;
8119 struct dcerpc_binding_handle *b;
8121 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8122 if (!NT_STATUS_IS_OK(status)) {
8123 return false;
8125 b = p->binding_handle;
8127 ctx = talloc_zero(torture, struct torture_samr_context);
8129 ctx->choice = TORTURE_SAMR_OTHER;
8131 ret &= test_Connect(b, torture, &ctx->handle);
8133 if (!torture_setting_bool(torture, "samba3", false)) {
8134 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8137 ret &= test_EnumDomains(p, torture, ctx);
8139 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8141 ret &= test_Shutdown(b, torture, &ctx->handle);
8143 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8145 return ret;
8149 bool torture_rpc_samr_users(struct torture_context *torture)
8151 NTSTATUS status;
8152 struct dcerpc_pipe *p;
8153 bool ret = true;
8154 struct torture_samr_context *ctx;
8155 struct dcerpc_binding_handle *b;
8157 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8158 if (!NT_STATUS_IS_OK(status)) {
8159 return false;
8161 b = p->binding_handle;
8163 ctx = talloc_zero(torture, struct torture_samr_context);
8165 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8167 ret &= test_Connect(b, torture, &ctx->handle);
8169 if (!torture_setting_bool(torture, "samba3", false)) {
8170 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8173 ret &= test_EnumDomains(p, torture, ctx);
8175 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8177 ret &= test_Shutdown(b, torture, &ctx->handle);
8179 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8181 return ret;
8185 bool torture_rpc_samr_passwords(struct torture_context *torture)
8187 NTSTATUS status;
8188 struct dcerpc_pipe *p;
8189 bool ret = true;
8190 struct torture_samr_context *ctx;
8191 struct dcerpc_binding_handle *b;
8193 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8194 if (!NT_STATUS_IS_OK(status)) {
8195 return false;
8197 b = p->binding_handle;
8199 ctx = talloc_zero(torture, struct torture_samr_context);
8201 ctx->choice = TORTURE_SAMR_PASSWORDS;
8203 ret &= test_Connect(b, torture, &ctx->handle);
8205 ret &= test_EnumDomains(p, torture, ctx);
8207 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8209 return ret;
8212 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8213 struct dcerpc_pipe *p2,
8214 struct cli_credentials *machine_credentials)
8216 NTSTATUS status;
8217 struct dcerpc_pipe *p;
8218 bool ret = true;
8219 struct torture_samr_context *ctx;
8220 struct dcerpc_binding_handle *b;
8222 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8223 if (!NT_STATUS_IS_OK(status)) {
8224 return false;
8226 b = p->binding_handle;
8228 ctx = talloc_zero(torture, struct torture_samr_context);
8230 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8231 ctx->machine_credentials = machine_credentials;
8233 ret &= test_Connect(b, torture, &ctx->handle);
8235 ret &= test_EnumDomains(p, torture, ctx);
8237 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8239 return ret;
8242 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8244 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8245 struct torture_rpc_tcase *tcase;
8247 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8248 &ndr_table_samr,
8249 TEST_ACCOUNT_NAME_PWD);
8251 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8252 torture_rpc_samr_pwdlastset);
8254 return suite;
8257 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8258 struct dcerpc_pipe *p2,
8259 struct cli_credentials *machine_credentials)
8261 NTSTATUS status;
8262 struct dcerpc_pipe *p;
8263 bool ret = true;
8264 struct torture_samr_context *ctx;
8265 struct dcerpc_binding_handle *b;
8267 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8268 if (!NT_STATUS_IS_OK(status)) {
8269 return false;
8271 b = p->binding_handle;
8273 ctx = talloc_zero(torture, struct torture_samr_context);
8275 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8276 ctx->machine_credentials = machine_credentials;
8278 ret &= test_Connect(b, torture, &ctx->handle);
8280 ret &= test_EnumDomains(p, torture, ctx);
8282 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8284 return ret;
8287 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8289 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8290 struct torture_rpc_tcase *tcase;
8292 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8293 &ndr_table_samr,
8294 TEST_ACCOUNT_NAME_PWD);
8296 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8297 torture_rpc_samr_users_privileges_delete_user);
8299 return suite;
8302 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8303 struct dcerpc_pipe *p2,
8304 void *data)
8306 NTSTATUS status;
8307 struct dcerpc_pipe *p;
8308 bool ret = true;
8309 struct torture_samr_context *ctx =
8310 talloc_get_type_abort(data, struct torture_samr_context);
8311 struct dcerpc_binding_handle *b;
8313 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8314 if (!NT_STATUS_IS_OK(status)) {
8315 return false;
8317 b = p->binding_handle;
8319 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8320 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8321 ctx->num_objects_large_dc);
8323 ret &= test_Connect(b, torture, &ctx->handle);
8325 ret &= test_EnumDomains(p, torture, ctx);
8327 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8329 return ret;
8332 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8333 struct dcerpc_pipe *p2,
8334 void *data)
8336 NTSTATUS status;
8337 struct dcerpc_pipe *p;
8338 bool ret = true;
8339 struct torture_samr_context *ctx =
8340 talloc_get_type_abort(data, struct torture_samr_context);
8341 struct dcerpc_binding_handle *b;
8343 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8344 if (!NT_STATUS_IS_OK(status)) {
8345 return false;
8347 b = p->binding_handle;
8349 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8350 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8351 ctx->num_objects_large_dc);
8353 ret &= test_Connect(b, torture, &ctx->handle);
8355 ret &= test_EnumDomains(p, torture, ctx);
8357 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8359 return ret;
8362 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8363 struct dcerpc_pipe *p2,
8364 void *data)
8366 NTSTATUS status;
8367 struct dcerpc_pipe *p;
8368 bool ret = true;
8369 struct torture_samr_context *ctx =
8370 talloc_get_type_abort(data, struct torture_samr_context);
8371 struct dcerpc_binding_handle *b;
8373 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8374 if (!NT_STATUS_IS_OK(status)) {
8375 return false;
8377 b = p->binding_handle;
8379 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8380 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8381 ctx->num_objects_large_dc);
8383 ret &= test_Connect(b, torture, &ctx->handle);
8385 ret &= test_EnumDomains(p, torture, ctx);
8387 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8389 return ret;
8392 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8394 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8395 struct torture_rpc_tcase *tcase;
8396 struct torture_samr_context *ctx;
8398 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8400 ctx = talloc_zero(suite, struct torture_samr_context);
8401 ctx->num_objects_large_dc = 150;
8403 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8404 torture_rpc_samr_many_aliases, ctx);
8405 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8406 torture_rpc_samr_many_groups, ctx);
8407 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8408 torture_rpc_samr_many_accounts, ctx);
8410 return suite;
8413 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8414 struct dcerpc_pipe *p2,
8415 struct cli_credentials *machine_credentials)
8417 NTSTATUS status;
8418 struct dcerpc_pipe *p;
8419 bool ret = true;
8420 struct torture_samr_context *ctx;
8421 struct dcerpc_binding_handle *b;
8423 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8424 if (!NT_STATUS_IS_OK(status)) {
8425 return false;
8427 b = p->binding_handle;
8429 ctx = talloc_zero(torture, struct torture_samr_context);
8431 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8432 ctx->machine_credentials = machine_credentials;
8434 ret &= test_Connect(b, torture, &ctx->handle);
8436 ret &= test_EnumDomains(p, torture, ctx);
8438 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8440 return ret;
8443 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8445 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8446 struct torture_rpc_tcase *tcase;
8448 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8449 &ndr_table_samr,
8450 TEST_ACCOUNT_NAME_PWD);
8452 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8453 torture_rpc_samr_badpwdcount);
8455 return suite;
8458 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8459 struct dcerpc_pipe *p2,
8460 struct cli_credentials *machine_credentials)
8462 NTSTATUS status;
8463 struct dcerpc_pipe *p;
8464 bool ret = true;
8465 struct torture_samr_context *ctx;
8466 struct dcerpc_binding_handle *b;
8468 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8469 if (!NT_STATUS_IS_OK(status)) {
8470 return false;
8472 b = p->binding_handle;
8474 ctx = talloc_zero(torture, struct torture_samr_context);
8476 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8477 ctx->machine_credentials = machine_credentials;
8479 ret &= test_Connect(b, torture, &ctx->handle);
8481 ret &= test_EnumDomains(p, torture, ctx);
8483 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8485 return ret;
8488 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8490 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8491 struct torture_rpc_tcase *tcase;
8493 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8494 &ndr_table_samr,
8495 TEST_ACCOUNT_NAME_PWD);
8497 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8498 torture_rpc_samr_lockout);
8500 return suite;
8503 struct torture_suite *torture_rpc_samr_passwords_validate(TALLOC_CTX *mem_ctx)
8505 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.validate");
8506 struct torture_rpc_tcase *tcase;
8508 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
8509 &ndr_table_samr);
8510 torture_rpc_tcase_add_test(tcase, "validate",
8511 test_samr_ValidatePassword);
8513 return suite;