torture-samr: Do not issue a TORTURE_FAIL unless *this* test failed
[Samba.git] / source4 / torture / rpc / samr.c
blob45a74cbb58f80f962d597f992ace7c60564c4041
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, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3909 torture_assert(tctx,
3910 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3912 if (disable) {
3913 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3914 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3915 } else {
3916 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3917 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3920 tmp = badpwdcount;
3922 continue;
3925 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3926 acct_name, passwords[i],
3927 NT_STATUS_WRONG_PASSWORD, interactive)) {
3928 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3931 torture_assert(tctx,
3932 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3934 /* - network samlogon will fail auth but not increase
3935 * badpwdcount for 3rd last entry
3936 * - interactive samlogon for 3rd and 2nd last entry */
3938 if (i == password_history_length - 3 ||
3939 (i == password_history_length - 2 && interactive)) {
3940 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3941 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3942 } else {
3943 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3944 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3947 tmp = badpwdcount;
3950 return true;
3953 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3954 struct torture_context *tctx,
3955 uint32_t acct_flags,
3956 const char *acct_name,
3957 struct policy_handle *domain_handle,
3958 struct policy_handle *user_handle,
3959 char **password,
3960 struct cli_credentials *machine_credentials)
3962 union samr_DomainInfo *q_info, s_info;
3963 struct samr_DomInfo1 info1, _info1;
3964 struct samr_DomInfo12 info12, _info12;
3965 bool ret = true;
3966 struct dcerpc_binding_handle *b = p->binding_handle;
3967 struct dcerpc_pipe *np;
3968 int i;
3970 struct {
3971 const char *comment;
3972 bool disabled;
3973 bool interactive;
3974 NTSTATUS expected_success_status;
3975 } creds[] = {
3977 .comment = "network logon (disabled account)",
3978 .disabled = true,
3979 .interactive = false,
3980 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3983 .comment = "network logon (enabled account)",
3984 .disabled = false,
3985 .interactive = false,
3986 .expected_success_status= NT_STATUS_OK
3989 .comment = "interactive logon (disabled account)",
3990 .disabled = true,
3991 .interactive = true,
3992 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3995 .comment = "interactive logon (enabled account)",
3996 .disabled = false,
3997 .interactive = true,
3998 .expected_success_status= NT_STATUS_OK
4002 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4004 /* backup old policies */
4006 torture_assert(tctx,
4007 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4008 DomainPasswordInformation, &q_info),
4009 "failed to query domain info level 1");
4011 info1 = q_info->info1;
4012 _info1 = info1;
4014 torture_assert(tctx,
4015 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4016 DomainLockoutInformation, &q_info),
4017 "failed to query domain info level 12");
4019 info12 = q_info->info12;
4020 _info12 = info12;
4022 /* run tests */
4024 for (i=0; i < ARRAY_SIZE(creds); i++) {
4026 /* skip trust tests for now */
4027 if (acct_flags & ACB_WSTRUST ||
4028 acct_flags & ACB_SVRTRUST ||
4029 acct_flags & ACB_DOMTRUST) {
4030 continue;
4033 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4034 domain_handle, user_handle, password,
4035 machine_credentials,
4036 creds[i].comment,
4037 creds[i].disabled,
4038 creds[i].interactive,
4039 creds[i].expected_success_status,
4040 &_info1, &_info12);
4041 if (!ret) {
4042 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4043 } else {
4044 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4048 /* restore policies */
4050 s_info.info1 = info1;
4052 torture_assert(tctx,
4053 test_SetDomainInfo(b, tctx, domain_handle,
4054 DomainPasswordInformation, &s_info),
4055 "failed to set password information");
4057 s_info.info12 = info12;
4059 torture_assert(tctx,
4060 test_SetDomainInfo(b, tctx, domain_handle,
4061 DomainLockoutInformation, &s_info),
4062 "failed to set lockout information");
4064 return ret;
4067 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
4068 struct torture_context *tctx,
4069 struct policy_handle *domain_handle,
4070 const char *acct_name,
4071 uint32_t *acct_flags)
4073 struct policy_handle user_handle;
4074 union samr_UserInfo *info;
4075 struct samr_QueryUserInfo r;
4077 NTSTATUS status = test_OpenUser_byname(b, tctx, domain_handle, acct_name, &user_handle);
4078 if (!NT_STATUS_IS_OK(status)) {
4079 return false;
4082 r.in.user_handle = &user_handle;
4083 r.in.level = 16;
4084 r.out.info = &info;
4086 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4088 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4089 "failed to query userinfo");
4090 torture_assert_ntstatus_ok(tctx, r.out.result,
4091 "failed to query userinfo");
4093 *acct_flags = info->info16.acct_flags;
4095 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
4097 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
4098 return false;
4101 return true;
4104 static bool test_Password_lockout(struct dcerpc_pipe *p,
4105 struct dcerpc_pipe *np,
4106 struct torture_context *tctx,
4107 uint32_t acct_flags,
4108 const char *acct_name,
4109 struct policy_handle *domain_handle,
4110 struct policy_handle *user_handle,
4111 char **password,
4112 struct cli_credentials *machine_credentials,
4113 const char *comment,
4114 bool disable,
4115 bool interactive,
4116 NTSTATUS expected_success_status,
4117 struct samr_DomInfo1 *info1,
4118 struct samr_DomInfo12 *info12)
4120 union samr_DomainInfo info;
4121 uint32_t badpwdcount;
4122 uint32_t password_history_length = 1;
4123 uint64_t lockout_threshold = 1;
4124 uint32_t lockout_seconds = 5;
4125 uint64_t delta_time_factor = 10 * 1000 * 1000;
4126 struct dcerpc_binding_handle *b = p->binding_handle;
4128 if (torture_setting_bool(tctx, "samba3", false)) {
4129 lockout_seconds = 60;
4132 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4134 /* set policies */
4136 info.info1 = *info1;
4138 torture_comment(tctx, "setting password history length.\n");
4139 info.info1.password_history_length = password_history_length;
4141 torture_comment(tctx, "setting min password again.\n");
4142 info.info1.min_password_age = 0;
4144 torture_assert(tctx,
4145 test_SetDomainInfo(b, tctx, domain_handle,
4146 DomainPasswordInformation, &info),
4147 "failed to set password history length");
4149 info.info12 = *info12;
4150 info.info12.lockout_threshold = lockout_threshold;
4152 /* set lockout duration < lockout window: should fail */
4153 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4154 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4156 torture_assert(tctx,
4157 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4158 DomainLockoutInformation, &info,
4159 NT_STATUS_INVALID_PARAMETER),
4160 "setting lockout duration < lockout window gave unexpected result");
4162 info.info12.lockout_duration = 0;
4163 info.info12.lockout_window = 0;
4165 torture_assert(tctx,
4166 test_SetDomainInfo(b, tctx, domain_handle,
4167 DomainLockoutInformation, &info),
4168 "failed to set lockout window and duration to 0");
4171 /* set lockout duration of 5 seconds */
4172 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4173 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4175 torture_assert(tctx,
4176 test_SetDomainInfo(b, tctx, domain_handle,
4177 DomainLockoutInformation, &info),
4178 "failed to set lockout window and duration to 5 seconds");
4180 /* reset bad pwd count */
4182 torture_assert(tctx,
4183 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4186 /* enable or disable account */
4188 if (disable) {
4189 torture_assert(tctx,
4190 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4191 acct_flags | ACB_DISABLED),
4192 "failed to disable user");
4193 } else {
4194 torture_assert(tctx,
4195 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4196 acct_flags & ~ACB_DISABLED),
4197 "failed to enable user");
4201 /* test logon with right password */
4203 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4204 acct_name, *password,
4205 expected_success_status, interactive)) {
4206 torture_fail(tctx, "failed to auth with latest password");
4209 torture_assert(tctx,
4210 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4211 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4214 /* test with wrong password ==> lockout */
4216 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4217 acct_name, "random_crap",
4218 NT_STATUS_WRONG_PASSWORD, interactive)) {
4219 torture_fail(tctx, "succeeded to authenticate with wrong password");
4222 torture_assert(tctx,
4223 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4224 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4226 /* curiously, windows does _not_ set the autlock flag unless you re-open the user */
4227 torture_assert(tctx,
4228 test_QueryUserInfo_acct_flags(b, tctx, domain_handle, acct_name, &acct_flags), "");
4229 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, ACB_AUTOLOCK,
4230 "expected account to be locked");
4233 /* test with good password */
4235 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4236 *password,
4237 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4239 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4242 /* bad pwd count should not get updated */
4243 torture_assert(tctx,
4244 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4245 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4247 /* curiously, windows does _not_ set the autlock flag unless you re-open the user */
4248 torture_assert(tctx,
4249 test_QueryUserInfo_acct_flags(b, tctx, domain_handle, acct_name, &acct_flags), "");
4250 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, ACB_AUTOLOCK,
4251 "expected account to be locked");
4254 /* with bad password */
4256 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4257 acct_name, "random_crap2",
4258 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4260 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4263 /* bad pwd count should not get updated */
4264 torture_assert(tctx,
4265 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4266 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4268 /* curiously, windows does _not_ set the autlock flag untill you re-open the user */
4269 torture_assert(tctx,
4270 test_QueryUserInfo_acct_flags(b, tctx, domain_handle, acct_name, &acct_flags), "");
4271 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, ACB_AUTOLOCK,
4272 "expected account to show ACB_AUTOLOCK");
4275 /* let lockout duration expire ==> unlock */
4277 torture_comment(tctx, "let lockout duration expire...\n");
4278 sleep(lockout_seconds + 1);
4280 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4281 *password,
4282 expected_success_status, interactive))
4284 torture_fail(tctx, "failed to authenticate after lockout expired");
4287 torture_assert(tctx,
4288 test_QueryUserInfo_acct_flags(b, tctx, domain_handle, acct_name, &acct_flags), "");
4289 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4290 "expected account not to be locked");
4292 return true;
4295 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4296 struct torture_context *tctx,
4297 uint32_t acct_flags,
4298 const char *acct_name,
4299 struct policy_handle *domain_handle,
4300 struct policy_handle *user_handle,
4301 char **password,
4302 struct cli_credentials *machine_credentials)
4304 union samr_DomainInfo *q_info, s_info;
4305 struct samr_DomInfo1 info1, _info1;
4306 struct samr_DomInfo12 info12, _info12;
4307 bool ret = true;
4308 struct dcerpc_binding_handle *b = p->binding_handle;
4309 struct dcerpc_pipe *np;
4310 int i;
4312 struct {
4313 const char *comment;
4314 bool disabled;
4315 bool interactive;
4316 NTSTATUS expected_success_status;
4317 } creds[] = {
4319 .comment = "network logon (disabled account)",
4320 .disabled = true,
4321 .interactive = false,
4322 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4325 .comment = "network logon (enabled account)",
4326 .disabled = false,
4327 .interactive = false,
4328 .expected_success_status= NT_STATUS_OK
4331 .comment = "interactive logon (disabled account)",
4332 .disabled = true,
4333 .interactive = true,
4334 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4337 .comment = "interactive logon (enabled account)",
4338 .disabled = false,
4339 .interactive = true,
4340 .expected_success_status= NT_STATUS_OK
4344 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4346 /* backup old policies */
4348 torture_assert(tctx,
4349 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4350 DomainPasswordInformation, &q_info),
4351 "failed to query domain info level 1");
4353 info1 = q_info->info1;
4354 _info1 = info1;
4356 torture_assert(tctx,
4357 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4358 DomainLockoutInformation, &q_info),
4359 "failed to query domain info level 12");
4361 info12 = q_info->info12;
4362 _info12 = info12;
4364 /* run tests */
4366 for (i=0; i < ARRAY_SIZE(creds); i++) {
4367 bool test_passed;
4368 /* skip trust tests for now */
4369 if (acct_flags & ACB_WSTRUST ||
4370 acct_flags & ACB_SVRTRUST ||
4371 acct_flags & ACB_DOMTRUST) {
4372 continue;
4375 test_passed = test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4376 domain_handle, user_handle, password,
4377 machine_credentials,
4378 creds[i].comment,
4379 creds[i].disabled,
4380 creds[i].interactive,
4381 creds[i].expected_success_status,
4382 &_info1, &_info12);
4383 ret &= test_passed;
4384 if (!test_passed) {
4385 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4386 break;
4387 } else {
4388 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4392 /* restore policies */
4394 s_info.info1 = info1;
4396 torture_assert(tctx,
4397 test_SetDomainInfo(b, tctx, domain_handle,
4398 DomainPasswordInformation, &s_info),
4399 "failed to set password information");
4401 s_info.info12 = info12;
4403 torture_assert(tctx,
4404 test_SetDomainInfo(b, tctx, domain_handle,
4405 DomainLockoutInformation, &s_info),
4406 "failed to set lockout information");
4408 return ret;
4411 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4412 struct dcerpc_pipe *lp,
4413 struct torture_context *tctx,
4414 struct policy_handle *domain_handle,
4415 struct policy_handle *lsa_handle,
4416 struct policy_handle *user_handle,
4417 const struct dom_sid *domain_sid,
4418 uint32_t rid,
4419 struct cli_credentials *machine_credentials)
4421 bool ret = true;
4422 struct dcerpc_binding_handle *b = p->binding_handle;
4423 struct dcerpc_binding_handle *lb = lp->binding_handle;
4425 struct policy_handle lsa_acct_handle;
4426 struct dom_sid *user_sid;
4428 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4431 struct lsa_EnumAccountRights r;
4432 struct lsa_RightSet rights;
4434 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4436 r.in.handle = lsa_handle;
4437 r.in.sid = user_sid;
4438 r.out.rights = &rights;
4440 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4441 "lsa_EnumAccountRights failed");
4442 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4443 "Expected enum rights for account to fail");
4447 struct lsa_RightSet rights;
4448 struct lsa_StringLarge names[2];
4449 struct lsa_AddAccountRights r;
4451 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4453 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4454 init_lsa_StringLarge(&names[1], NULL);
4456 rights.count = 1;
4457 rights.names = names;
4459 r.in.handle = lsa_handle;
4460 r.in.sid = user_sid;
4461 r.in.rights = &rights;
4463 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4464 "lsa_AddAccountRights failed");
4465 torture_assert_ntstatus_ok(tctx, r.out.result,
4466 "Failed to add privileges");
4470 struct lsa_EnumAccounts r;
4471 uint32_t resume_handle = 0;
4472 struct lsa_SidArray lsa_sid_array;
4473 int i;
4474 bool found_sid = false;
4476 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4478 r.in.handle = lsa_handle;
4479 r.in.num_entries = 0x1000;
4480 r.in.resume_handle = &resume_handle;
4481 r.out.sids = &lsa_sid_array;
4482 r.out.resume_handle = &resume_handle;
4484 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4485 "lsa_EnumAccounts failed");
4486 torture_assert_ntstatus_ok(tctx, r.out.result,
4487 "Failed to enum accounts");
4489 for (i=0; i < lsa_sid_array.num_sids; i++) {
4490 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4491 found_sid = true;
4495 torture_assert(tctx, found_sid,
4496 "failed to list privileged account");
4500 struct lsa_EnumAccountRights r;
4501 struct lsa_RightSet user_rights;
4503 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4505 r.in.handle = lsa_handle;
4506 r.in.sid = user_sid;
4507 r.out.rights = &user_rights;
4509 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4510 "lsa_EnumAccountRights failed");
4511 torture_assert_ntstatus_ok(tctx, r.out.result,
4512 "Failed to enum rights for account");
4514 if (user_rights.count < 1) {
4515 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4516 return false;
4521 struct lsa_OpenAccount r;
4523 torture_comment(tctx, "Testing LSA OpenAccount\n");
4525 r.in.handle = lsa_handle;
4526 r.in.sid = user_sid;
4527 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4528 r.out.acct_handle = &lsa_acct_handle;
4530 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4531 "lsa_OpenAccount failed");
4532 torture_assert_ntstatus_ok(tctx, r.out.result,
4533 "Failed to open lsa account");
4537 struct lsa_GetSystemAccessAccount r;
4538 uint32_t access_mask;
4540 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4542 r.in.handle = &lsa_acct_handle;
4543 r.out.access_mask = &access_mask;
4545 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4546 "lsa_GetSystemAccessAccount failed");
4547 torture_assert_ntstatus_ok(tctx, r.out.result,
4548 "Failed to get lsa system access account");
4552 struct lsa_Close r;
4554 torture_comment(tctx, "Testing LSA Close\n");
4556 r.in.handle = &lsa_acct_handle;
4557 r.out.handle = &lsa_acct_handle;
4559 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4560 "lsa_Close failed");
4561 torture_assert_ntstatus_ok(tctx, r.out.result,
4562 "Failed to close lsa");
4566 struct samr_DeleteUser r;
4568 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4570 r.in.user_handle = user_handle;
4571 r.out.user_handle = user_handle;
4573 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4574 "DeleteUser failed");
4575 torture_assert_ntstatus_ok(tctx, r.out.result,
4576 "DeleteUser failed");
4580 struct lsa_EnumAccounts r;
4581 uint32_t resume_handle = 0;
4582 struct lsa_SidArray lsa_sid_array;
4583 int i;
4584 bool found_sid = false;
4586 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4588 r.in.handle = lsa_handle;
4589 r.in.num_entries = 0x1000;
4590 r.in.resume_handle = &resume_handle;
4591 r.out.sids = &lsa_sid_array;
4592 r.out.resume_handle = &resume_handle;
4594 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4595 "lsa_EnumAccounts failed");
4596 torture_assert_ntstatus_ok(tctx, r.out.result,
4597 "Failed to enum accounts");
4599 for (i=0; i < lsa_sid_array.num_sids; i++) {
4600 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4601 found_sid = true;
4605 torture_assert(tctx, found_sid,
4606 "failed to list privileged account");
4610 struct lsa_EnumAccountRights r;
4611 struct lsa_RightSet user_rights;
4613 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4615 r.in.handle = lsa_handle;
4616 r.in.sid = user_sid;
4617 r.out.rights = &user_rights;
4619 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4620 "lsa_EnumAccountRights failed");
4621 torture_assert_ntstatus_ok(tctx, r.out.result,
4622 "Failed to enum rights for account");
4624 if (user_rights.count < 1) {
4625 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4626 return false;
4631 struct lsa_OpenAccount r;
4633 torture_comment(tctx, "Testing LSA OpenAccount\n");
4635 r.in.handle = lsa_handle;
4636 r.in.sid = user_sid;
4637 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4638 r.out.acct_handle = &lsa_acct_handle;
4640 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4641 "lsa_OpenAccount failed");
4642 torture_assert_ntstatus_ok(tctx, r.out.result,
4643 "Failed to open lsa account");
4647 struct lsa_GetSystemAccessAccount r;
4648 uint32_t access_mask;
4650 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4652 r.in.handle = &lsa_acct_handle;
4653 r.out.access_mask = &access_mask;
4655 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4656 "lsa_GetSystemAccessAccount failed");
4657 torture_assert_ntstatus_ok(tctx, r.out.result,
4658 "Failed to get lsa system access account");
4662 struct lsa_DeleteObject r;
4664 torture_comment(tctx, "Testing LSA DeleteObject\n");
4666 r.in.handle = &lsa_acct_handle;
4667 r.out.handle = &lsa_acct_handle;
4669 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4670 "lsa_DeleteObject failed");
4671 torture_assert_ntstatus_ok(tctx, r.out.result,
4672 "Failed to delete object");
4676 struct lsa_EnumAccounts r;
4677 uint32_t resume_handle = 0;
4678 struct lsa_SidArray lsa_sid_array;
4679 int i;
4680 bool found_sid = false;
4682 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4684 r.in.handle = lsa_handle;
4685 r.in.num_entries = 0x1000;
4686 r.in.resume_handle = &resume_handle;
4687 r.out.sids = &lsa_sid_array;
4688 r.out.resume_handle = &resume_handle;
4690 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4691 "lsa_EnumAccounts failed");
4692 torture_assert_ntstatus_ok(tctx, r.out.result,
4693 "Failed to enum accounts");
4695 for (i=0; i < lsa_sid_array.num_sids; i++) {
4696 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4697 found_sid = true;
4701 torture_assert(tctx, !found_sid,
4702 "should not have listed privileged account");
4706 struct lsa_EnumAccountRights r;
4707 struct lsa_RightSet user_rights;
4709 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4711 r.in.handle = lsa_handle;
4712 r.in.sid = user_sid;
4713 r.out.rights = &user_rights;
4715 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4716 "lsa_EnumAccountRights failed");
4717 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4718 "Failed to enum rights for account");
4721 return ret;
4724 static bool test_user_ops(struct dcerpc_pipe *p,
4725 struct torture_context *tctx,
4726 struct policy_handle *user_handle,
4727 struct policy_handle *domain_handle,
4728 const struct dom_sid *domain_sid,
4729 uint32_t base_acct_flags,
4730 const char *base_acct_name, enum torture_samr_choice which_ops,
4731 struct cli_credentials *machine_credentials)
4733 char *password = NULL;
4734 struct samr_QueryUserInfo q;
4735 union samr_UserInfo *info;
4736 NTSTATUS status;
4737 struct dcerpc_binding_handle *b = p->binding_handle;
4739 bool ret = true;
4740 int i;
4741 uint32_t rid;
4742 const uint32_t password_fields[] = {
4743 SAMR_FIELD_NT_PASSWORD_PRESENT,
4744 SAMR_FIELD_LM_PASSWORD_PRESENT,
4745 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4749 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4750 if (!NT_STATUS_IS_OK(status)) {
4751 ret = false;
4754 switch (which_ops) {
4755 case TORTURE_SAMR_USER_ATTRIBUTES:
4756 if (!test_QuerySecurity(b, tctx, user_handle)) {
4757 ret = false;
4760 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4761 ret = false;
4764 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4765 ret = false;
4768 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4769 base_acct_name)) {
4770 ret = false;
4773 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4774 ret = false;
4777 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4778 ret = false;
4781 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4782 ret = false;
4784 break;
4785 case TORTURE_SAMR_PASSWORDS:
4786 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4787 char simple_pass[9];
4788 char *v = generate_random_str(tctx, 1);
4790 ZERO_STRUCT(simple_pass);
4791 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4793 torture_comment(tctx, "Testing machine account password policy rules\n");
4795 /* Workstation trust accounts don't seem to need to honour password quality policy */
4796 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4797 ret = false;
4800 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4801 ret = false;
4804 /* reset again, to allow another 'user' password change */
4805 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4806 ret = false;
4809 /* Try a 'short' password */
4810 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4811 ret = false;
4814 /* Try a compleatly random password */
4815 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4816 ret = false;
4820 for (i = 0; password_fields[i]; i++) {
4821 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4822 ret = false;
4825 /* check it was set right */
4826 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4827 ret = false;
4831 for (i = 0; password_fields[i]; i++) {
4832 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4833 ret = false;
4836 /* check it was set right */
4837 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4838 ret = false;
4842 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4843 ret = false;
4846 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4847 ret = false;
4850 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4851 ret = false;
4854 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4855 ret = false;
4858 for (i = 0; password_fields[i]; i++) {
4860 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4861 /* we need to skip as that would break
4862 * the ChangePasswordUser3 verify */
4863 continue;
4866 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4867 ret = false;
4870 /* check it was set right */
4871 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4872 ret = false;
4876 q.in.user_handle = user_handle;
4877 q.in.level = 5;
4878 q.out.info = &info;
4880 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4881 "QueryUserInfo failed");
4882 if (!NT_STATUS_IS_OK(q.out.result)) {
4883 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
4884 q.in.level, nt_errstr(q.out.result));
4885 ret = false;
4886 } else {
4887 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4888 if ((info->info5.acct_flags) != expected_flags) {
4889 /* FIXME: GD */
4890 if (!torture_setting_bool(tctx, "samba3", false)) {
4891 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4892 info->info5.acct_flags,
4893 expected_flags);
4894 ret = false;
4897 if (info->info5.rid != rid) {
4898 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4899 info->info5.rid, rid);
4904 break;
4906 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4908 /* test last password change timestamp behaviour */
4909 torture_assert(tctx, test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4910 base_acct_name,
4911 user_handle, &password,
4912 machine_credentials),
4913 "pwdLastSet test failed\n");
4914 break;
4916 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4918 /* test bad pwd count change behaviour */
4919 torture_assert(tctx, test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4920 base_acct_name,
4921 domain_handle,
4922 user_handle, &password,
4923 machine_credentials),
4924 "badPwdCount test failed\n");
4925 break;
4927 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4929 torture_assert(tctx, test_Password_lockout_wrap(p, tctx, base_acct_flags,
4930 base_acct_name,
4931 domain_handle,
4932 user_handle, &password,
4933 machine_credentials),
4934 "Lockout test failed");
4935 break;
4938 case TORTURE_SAMR_USER_PRIVILEGES: {
4940 struct dcerpc_pipe *lp;
4941 struct policy_handle *lsa_handle;
4942 struct dcerpc_binding_handle *lb;
4944 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4945 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4946 lb = lp->binding_handle;
4948 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4949 ret = false;
4952 if (!test_DeleteUser_with_privs(p, lp, tctx,
4953 domain_handle, lsa_handle, user_handle,
4954 domain_sid, rid,
4955 machine_credentials)) {
4956 ret = false;
4959 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4960 ret = false;
4963 if (!ret) {
4964 torture_result(tctx, TORTURE_FAIL, "privileged user delete test failed\n");
4967 break;
4969 case TORTURE_SAMR_OTHER:
4970 case TORTURE_SAMR_MANY_ACCOUNTS:
4971 case TORTURE_SAMR_MANY_GROUPS:
4972 case TORTURE_SAMR_MANY_ALIASES:
4973 /* We just need the account to exist */
4974 break;
4976 return ret;
4979 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4980 struct torture_context *tctx,
4981 struct policy_handle *alias_handle,
4982 const struct dom_sid *domain_sid)
4984 bool ret = true;
4986 if (!torture_setting_bool(tctx, "samba3", false)) {
4987 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4988 ret = false;
4992 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4993 ret = false;
4996 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4997 ret = false;
5000 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
5001 ret = false;
5004 if (torture_setting_bool(tctx, "samba3", false) ||
5005 torture_setting_bool(tctx, "samba4", false)) {
5006 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
5007 return ret;
5010 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
5011 ret = false;
5014 return ret;
5018 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
5019 struct torture_context *tctx,
5020 struct policy_handle *user_handle)
5022 struct samr_DeleteUser d;
5023 torture_comment(tctx, "Testing DeleteUser\n");
5025 d.in.user_handle = user_handle;
5026 d.out.user_handle = user_handle;
5028 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5029 "DeleteUser failed");
5030 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5032 return true;
5035 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5036 struct torture_context *tctx,
5037 struct policy_handle *handle, const char *name)
5039 NTSTATUS status;
5040 struct samr_DeleteUser d;
5041 struct policy_handle user_handle;
5042 uint32_t rid;
5044 status = test_LookupName(b, tctx, handle, name, &rid);
5045 if (!NT_STATUS_IS_OK(status)) {
5046 goto failed;
5049 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5050 if (!NT_STATUS_IS_OK(status)) {
5051 goto failed;
5054 d.in.user_handle = &user_handle;
5055 d.out.user_handle = &user_handle;
5056 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5057 "DeleteUser failed");
5058 if (!NT_STATUS_IS_OK(d.out.result)) {
5059 status = d.out.result;
5060 goto failed;
5063 return true;
5065 failed:
5066 torture_result(tctx, TORTURE_FAIL, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
5067 return false;
5071 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
5072 struct torture_context *tctx,
5073 struct policy_handle *handle, const char *name)
5075 NTSTATUS status;
5076 struct samr_OpenGroup r;
5077 struct samr_DeleteDomainGroup d;
5078 struct policy_handle group_handle;
5079 uint32_t rid;
5081 status = test_LookupName(b, tctx, handle, name, &rid);
5082 if (!NT_STATUS_IS_OK(status)) {
5083 goto failed;
5086 r.in.domain_handle = handle;
5087 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5088 r.in.rid = rid;
5089 r.out.group_handle = &group_handle;
5090 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5091 "OpenGroup failed");
5092 if (!NT_STATUS_IS_OK(r.out.result)) {
5093 status = r.out.result;
5094 goto failed;
5097 d.in.group_handle = &group_handle;
5098 d.out.group_handle = &group_handle;
5099 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
5100 "DeleteDomainGroup failed");
5101 if (!NT_STATUS_IS_OK(d.out.result)) {
5102 status = d.out.result;
5103 goto failed;
5106 return true;
5108 failed:
5109 torture_result(tctx, TORTURE_FAIL, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
5110 return false;
5114 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
5115 struct torture_context *tctx,
5116 struct policy_handle *domain_handle,
5117 const char *name)
5119 NTSTATUS status;
5120 struct samr_OpenAlias r;
5121 struct samr_DeleteDomAlias d;
5122 struct policy_handle alias_handle;
5123 uint32_t rid;
5125 torture_comment(tctx, "Testing DeleteAlias_byname\n");
5127 status = test_LookupName(b, tctx, domain_handle, name, &rid);
5128 if (!NT_STATUS_IS_OK(status)) {
5129 goto failed;
5132 r.in.domain_handle = domain_handle;
5133 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5134 r.in.rid = rid;
5135 r.out.alias_handle = &alias_handle;
5136 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5137 "OpenAlias failed");
5138 if (!NT_STATUS_IS_OK(r.out.result)) {
5139 status = r.out.result;
5140 goto failed;
5143 d.in.alias_handle = &alias_handle;
5144 d.out.alias_handle = &alias_handle;
5145 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5146 "DeleteDomAlias failed");
5147 if (!NT_STATUS_IS_OK(d.out.result)) {
5148 status = d.out.result;
5149 goto failed;
5152 return true;
5154 failed:
5155 torture_result(tctx, TORTURE_FAIL, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5156 return false;
5159 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5160 struct torture_context *tctx,
5161 struct policy_handle *alias_handle)
5163 struct samr_DeleteDomAlias d;
5164 bool ret = true;
5166 torture_comment(tctx, "Testing DeleteAlias\n");
5168 d.in.alias_handle = alias_handle;
5169 d.out.alias_handle = alias_handle;
5171 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5172 "DeleteDomAlias failed");
5173 if (!NT_STATUS_IS_OK(d.out.result)) {
5174 torture_result(tctx, TORTURE_FAIL, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5175 ret = false;
5178 return ret;
5181 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5182 struct torture_context *tctx,
5183 struct policy_handle *domain_handle,
5184 const char *alias_name,
5185 struct policy_handle *alias_handle,
5186 const struct dom_sid *domain_sid,
5187 bool test_alias)
5189 struct samr_CreateDomAlias r;
5190 struct lsa_String name;
5191 uint32_t rid;
5192 bool ret = true;
5194 init_lsa_String(&name, alias_name);
5195 r.in.domain_handle = domain_handle;
5196 r.in.alias_name = &name;
5197 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5198 r.out.alias_handle = alias_handle;
5199 r.out.rid = &rid;
5201 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5203 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5204 "CreateDomAlias failed");
5206 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5207 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5208 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5209 return true;
5210 } else {
5211 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5212 nt_errstr(r.out.result));
5213 return false;
5217 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5218 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5219 return false;
5221 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5222 "CreateDomAlias failed");
5225 if (!NT_STATUS_IS_OK(r.out.result)) {
5226 torture_result(tctx, TORTURE_FAIL, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5227 return false;
5230 if (!test_alias) {
5231 return ret;
5234 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5235 ret = false;
5238 return ret;
5241 static bool test_ChangePassword(struct dcerpc_pipe *p,
5242 struct torture_context *tctx,
5243 const char *acct_name,
5244 struct policy_handle *domain_handle, char **password)
5246 bool ret = true;
5247 struct dcerpc_binding_handle *b = p->binding_handle;
5249 if (!*password) {
5250 return false;
5253 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5254 ret = false;
5257 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5258 ret = false;
5261 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5262 ret = false;
5265 /* test what happens when setting the old password again */
5266 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5267 ret = false;
5271 char simple_pass[9];
5272 char *v = generate_random_str(tctx, 1);
5274 ZERO_STRUCT(simple_pass);
5275 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5277 /* test what happens when picking a simple password */
5278 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5279 ret = false;
5283 /* set samr_SetDomainInfo level 1 with min_length 5 */
5285 struct samr_QueryDomainInfo r;
5286 union samr_DomainInfo *info = NULL;
5287 struct samr_SetDomainInfo s;
5288 uint16_t len_old, len;
5289 uint32_t pwd_prop_old;
5290 int64_t min_pwd_age_old;
5292 len = 5;
5294 r.in.domain_handle = domain_handle;
5295 r.in.level = 1;
5296 r.out.info = &info;
5298 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5299 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5300 "QueryDomainInfo failed");
5301 if (!NT_STATUS_IS_OK(r.out.result)) {
5302 return false;
5305 s.in.domain_handle = domain_handle;
5306 s.in.level = 1;
5307 s.in.info = info;
5309 /* remember the old min length, so we can reset it */
5310 len_old = s.in.info->info1.min_password_length;
5311 s.in.info->info1.min_password_length = len;
5312 pwd_prop_old = s.in.info->info1.password_properties;
5313 /* turn off password complexity checks for this test */
5314 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5316 min_pwd_age_old = s.in.info->info1.min_password_age;
5317 s.in.info->info1.min_password_age = 0;
5319 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5320 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5321 "SetDomainInfo failed");
5322 if (!NT_STATUS_IS_OK(s.out.result)) {
5323 return false;
5326 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5328 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5329 ret = false;
5332 s.in.info->info1.min_password_length = len_old;
5333 s.in.info->info1.password_properties = pwd_prop_old;
5334 s.in.info->info1.min_password_age = min_pwd_age_old;
5336 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5337 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5338 "SetDomainInfo failed");
5339 if (!NT_STATUS_IS_OK(s.out.result)) {
5340 return false;
5346 struct samr_OpenUser r;
5347 struct samr_QueryUserInfo q;
5348 union samr_UserInfo *info;
5349 struct samr_LookupNames n;
5350 struct policy_handle user_handle;
5351 struct samr_Ids rids, types;
5353 n.in.domain_handle = domain_handle;
5354 n.in.num_names = 1;
5355 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5356 n.in.names[0].string = acct_name;
5357 n.out.rids = &rids;
5358 n.out.types = &types;
5360 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5361 "LookupNames failed");
5362 if (!NT_STATUS_IS_OK(n.out.result)) {
5363 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5364 return false;
5367 r.in.domain_handle = domain_handle;
5368 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5369 r.in.rid = n.out.rids->ids[0];
5370 r.out.user_handle = &user_handle;
5372 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5373 "OpenUser failed");
5374 if (!NT_STATUS_IS_OK(r.out.result)) {
5375 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5376 return false;
5379 q.in.user_handle = &user_handle;
5380 q.in.level = 5;
5381 q.out.info = &info;
5383 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5384 "QueryUserInfo failed");
5385 if (!NT_STATUS_IS_OK(q.out.result)) {
5386 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5387 return false;
5390 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5392 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5393 info->info5.last_password_change, true)) {
5394 ret = false;
5398 /* we change passwords twice - this has the effect of verifying
5399 they were changed correctly for the final call */
5400 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5401 ret = false;
5404 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5405 ret = false;
5408 return ret;
5411 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5412 struct policy_handle *domain_handle,
5413 const char *user_name,
5414 struct policy_handle *user_handle_out,
5415 struct dom_sid *domain_sid,
5416 enum torture_samr_choice which_ops,
5417 struct cli_credentials *machine_credentials,
5418 bool test_user)
5421 TALLOC_CTX *user_ctx;
5423 struct samr_CreateUser r;
5424 struct samr_QueryUserInfo q;
5425 union samr_UserInfo *info;
5426 struct samr_DeleteUser d;
5427 uint32_t rid;
5429 /* This call creates a 'normal' account - check that it really does */
5430 const uint32_t acct_flags = ACB_NORMAL;
5431 struct lsa_String name;
5432 bool ret = true;
5433 struct dcerpc_binding_handle *b = p->binding_handle;
5435 struct policy_handle user_handle;
5436 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5437 init_lsa_String(&name, user_name);
5439 r.in.domain_handle = domain_handle;
5440 r.in.account_name = &name;
5441 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5442 r.out.user_handle = &user_handle;
5443 r.out.rid = &rid;
5445 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5447 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5448 "CreateUser failed");
5450 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5451 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5452 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5453 return true;
5454 } else {
5455 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5456 nt_errstr(r.out.result));
5457 return false;
5461 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5462 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5463 talloc_free(user_ctx);
5464 return false;
5466 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5467 "CreateUser failed");
5470 if (!NT_STATUS_IS_OK(r.out.result)) {
5471 talloc_free(user_ctx);
5472 torture_result(tctx, TORTURE_FAIL, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5473 return false;
5476 if (!test_user) {
5477 if (user_handle_out) {
5478 *user_handle_out = user_handle;
5480 return ret;
5484 q.in.user_handle = &user_handle;
5485 q.in.level = 16;
5486 q.out.info = &info;
5488 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5489 "QueryUserInfo failed");
5490 if (!NT_STATUS_IS_OK(q.out.result)) {
5491 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5492 q.in.level, nt_errstr(q.out.result));
5493 ret = false;
5494 } else {
5495 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5496 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5497 info->info16.acct_flags,
5498 acct_flags);
5499 ret = false;
5503 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5504 domain_sid, acct_flags, name.string, which_ops,
5505 machine_credentials)) {
5506 ret = false;
5509 if (user_handle_out) {
5510 *user_handle_out = user_handle;
5511 } else {
5512 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5514 d.in.user_handle = &user_handle;
5515 d.out.user_handle = &user_handle;
5517 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5518 "DeleteUser failed");
5519 if (!NT_STATUS_IS_OK(d.out.result)) {
5520 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5521 ret = false;
5527 talloc_free(user_ctx);
5529 return ret;
5533 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5534 struct policy_handle *domain_handle,
5535 struct dom_sid *domain_sid,
5536 enum torture_samr_choice which_ops,
5537 struct cli_credentials *machine_credentials)
5539 struct samr_CreateUser2 r;
5540 struct samr_QueryUserInfo q;
5541 union samr_UserInfo *info;
5542 struct samr_DeleteUser d;
5543 struct policy_handle user_handle;
5544 uint32_t rid;
5545 struct lsa_String name;
5546 bool ret = true;
5547 int i;
5548 struct dcerpc_binding_handle *b = p->binding_handle;
5550 struct {
5551 uint32_t acct_flags;
5552 const char *account_name;
5553 NTSTATUS nt_status;
5554 } account_types[] = {
5555 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5556 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5557 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5558 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5559 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5560 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5561 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5562 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5563 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5564 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5565 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5566 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5567 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5568 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5569 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5572 for (i = 0; account_types[i].account_name; i++) {
5573 TALLOC_CTX *user_ctx;
5574 uint32_t acct_flags = account_types[i].acct_flags;
5575 uint32_t access_granted;
5576 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5577 init_lsa_String(&name, account_types[i].account_name);
5579 r.in.domain_handle = domain_handle;
5580 r.in.account_name = &name;
5581 r.in.acct_flags = acct_flags;
5582 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5583 r.out.user_handle = &user_handle;
5584 r.out.access_granted = &access_granted;
5585 r.out.rid = &rid;
5587 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5589 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5590 "CreateUser2 failed");
5592 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5593 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5594 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5595 continue;
5596 } else {
5597 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5598 nt_errstr(r.out.result));
5599 ret = false;
5600 continue;
5604 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5605 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5606 talloc_free(user_ctx);
5607 ret = false;
5608 continue;
5610 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5611 "CreateUser2 failed");
5614 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5615 torture_result(tctx, TORTURE_FAIL, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5616 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5617 ret = false;
5620 if (NT_STATUS_IS_OK(r.out.result)) {
5621 q.in.user_handle = &user_handle;
5622 q.in.level = 5;
5623 q.out.info = &info;
5625 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5626 "QueryUserInfo failed");
5627 if (!NT_STATUS_IS_OK(q.out.result)) {
5628 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5629 q.in.level, nt_errstr(q.out.result));
5630 ret = false;
5631 } else {
5632 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5633 if (acct_flags == ACB_NORMAL) {
5634 expected_flags |= ACB_PW_EXPIRED;
5636 if ((info->info5.acct_flags) != expected_flags) {
5637 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5638 info->info5.acct_flags,
5639 expected_flags);
5640 ret = false;
5642 switch (acct_flags) {
5643 case ACB_SVRTRUST:
5644 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5645 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5646 DOMAIN_RID_DCS, info->info5.primary_gid);
5647 ret = false;
5649 break;
5650 case ACB_WSTRUST:
5651 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5652 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5653 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5654 ret = false;
5656 break;
5657 case ACB_NORMAL:
5658 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5659 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5660 DOMAIN_RID_USERS, info->info5.primary_gid);
5661 ret = false;
5663 break;
5667 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5668 domain_sid, acct_flags, name.string, which_ops,
5669 machine_credentials)) {
5670 ret = false;
5673 if (!ndr_policy_handle_empty(&user_handle)) {
5674 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5676 d.in.user_handle = &user_handle;
5677 d.out.user_handle = &user_handle;
5679 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5680 "DeleteUser failed");
5681 if (!NT_STATUS_IS_OK(d.out.result)) {
5682 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5683 ret = false;
5687 talloc_free(user_ctx);
5690 return ret;
5693 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5694 struct torture_context *tctx,
5695 struct policy_handle *handle)
5697 struct samr_QueryAliasInfo r;
5698 union samr_AliasInfo *info;
5699 uint16_t levels[] = {1, 2, 3};
5700 int i;
5701 bool ret = true;
5703 for (i=0;i<ARRAY_SIZE(levels);i++) {
5704 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5706 r.in.alias_handle = handle;
5707 r.in.level = levels[i];
5708 r.out.info = &info;
5710 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5711 "QueryAliasInfo failed");
5712 if (!NT_STATUS_IS_OK(r.out.result)) {
5713 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
5714 levels[i], nt_errstr(r.out.result));
5715 ret = false;
5719 return ret;
5722 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5723 struct torture_context *tctx,
5724 struct policy_handle *handle)
5726 struct samr_QueryGroupInfo r;
5727 union samr_GroupInfo *info;
5728 uint16_t levels[] = {1, 2, 3, 4, 5};
5729 int i;
5730 bool ret = true;
5732 for (i=0;i<ARRAY_SIZE(levels);i++) {
5733 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5735 r.in.group_handle = handle;
5736 r.in.level = levels[i];
5737 r.out.info = &info;
5739 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5740 "QueryGroupInfo failed");
5741 if (!NT_STATUS_IS_OK(r.out.result)) {
5742 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
5743 levels[i], nt_errstr(r.out.result));
5744 ret = false;
5748 return ret;
5751 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5752 struct torture_context *tctx,
5753 struct policy_handle *handle)
5755 struct samr_QueryGroupMember r;
5756 struct samr_RidAttrArray *rids = NULL;
5757 bool ret = true;
5759 torture_comment(tctx, "Testing QueryGroupMember\n");
5761 r.in.group_handle = handle;
5762 r.out.rids = &rids;
5764 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5765 "QueryGroupMember failed");
5766 if (!NT_STATUS_IS_OK(r.out.result)) {
5767 torture_result(tctx, TORTURE_FAIL, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
5768 ret = false;
5771 return ret;
5775 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5776 struct torture_context *tctx,
5777 struct policy_handle *handle)
5779 struct samr_QueryGroupInfo r;
5780 union samr_GroupInfo *info;
5781 struct samr_SetGroupInfo s;
5782 uint16_t levels[] = {1, 2, 3, 4};
5783 uint16_t set_ok[] = {0, 1, 1, 1};
5784 int i;
5785 bool ret = true;
5787 for (i=0;i<ARRAY_SIZE(levels);i++) {
5788 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5790 r.in.group_handle = handle;
5791 r.in.level = levels[i];
5792 r.out.info = &info;
5794 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5795 "QueryGroupInfo failed");
5796 if (!NT_STATUS_IS_OK(r.out.result)) {
5797 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
5798 levels[i], nt_errstr(r.out.result));
5799 ret = false;
5802 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5804 s.in.group_handle = handle;
5805 s.in.level = levels[i];
5806 s.in.info = *r.out.info;
5808 #if 0
5809 /* disabled this, as it changes the name only from the point of view of samr,
5810 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5811 the name is still reserved, so creating the old name fails, but deleting by the old name
5812 also fails */
5813 if (s.in.level == 2) {
5814 init_lsa_String(&s.in.info->string, "NewName");
5816 #endif
5818 if (s.in.level == 4) {
5819 init_lsa_String(&s.in.info->description, "test description");
5822 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5823 "SetGroupInfo failed");
5824 if (set_ok[i]) {
5825 if (!NT_STATUS_IS_OK(s.out.result)) {
5826 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u failed - %s\n",
5827 r.in.level, nt_errstr(s.out.result));
5828 ret = false;
5829 continue;
5831 } else {
5832 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5833 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5834 r.in.level, nt_errstr(s.out.result));
5835 ret = false;
5836 continue;
5841 return ret;
5844 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5845 struct torture_context *tctx,
5846 struct policy_handle *handle)
5848 struct samr_QueryUserInfo r;
5849 union samr_UserInfo *info;
5850 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5851 11, 12, 13, 14, 16, 17, 20, 21};
5852 int i;
5853 bool ret = true;
5855 for (i=0;i<ARRAY_SIZE(levels);i++) {
5856 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5858 r.in.user_handle = handle;
5859 r.in.level = levels[i];
5860 r.out.info = &info;
5862 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5863 "QueryUserInfo failed");
5864 if (!NT_STATUS_IS_OK(r.out.result)) {
5865 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5866 levels[i], nt_errstr(r.out.result));
5867 ret = false;
5871 return ret;
5874 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5875 struct torture_context *tctx,
5876 struct policy_handle *handle)
5878 struct samr_QueryUserInfo2 r;
5879 union samr_UserInfo *info;
5880 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5881 11, 12, 13, 14, 16, 17, 20, 21};
5882 int i;
5883 bool ret = true;
5885 for (i=0;i<ARRAY_SIZE(levels);i++) {
5886 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5888 r.in.user_handle = handle;
5889 r.in.level = levels[i];
5890 r.out.info = &info;
5892 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5893 "QueryUserInfo2 failed");
5894 if (!NT_STATUS_IS_OK(r.out.result)) {
5895 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo2 level %u failed - %s\n",
5896 levels[i], nt_errstr(r.out.result));
5897 ret = false;
5901 return ret;
5904 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5905 struct torture_context *tctx,
5906 struct policy_handle *handle, uint32_t rid)
5908 struct samr_OpenUser r;
5909 struct policy_handle user_handle;
5910 bool ret = true;
5912 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5914 r.in.domain_handle = handle;
5915 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5916 r.in.rid = rid;
5917 r.out.user_handle = &user_handle;
5919 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5920 "OpenUser failed");
5921 if (!NT_STATUS_IS_OK(r.out.result)) {
5922 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5923 return false;
5926 if (!test_QuerySecurity(b, tctx, &user_handle)) {
5927 ret = false;
5930 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5931 ret = false;
5934 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5935 ret = false;
5938 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5939 ret = false;
5942 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5943 ret = false;
5946 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5947 ret = false;
5950 return ret;
5953 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5954 struct torture_context *tctx,
5955 struct policy_handle *handle, uint32_t rid)
5957 struct samr_OpenGroup r;
5958 struct policy_handle group_handle;
5959 bool ret = true;
5961 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5963 r.in.domain_handle = handle;
5964 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5965 r.in.rid = rid;
5966 r.out.group_handle = &group_handle;
5968 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5969 "OpenGroup failed");
5970 if (!NT_STATUS_IS_OK(r.out.result)) {
5971 torture_result(tctx, TORTURE_FAIL, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5972 return false;
5975 if (!torture_setting_bool(tctx, "samba3", false)) {
5976 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5977 ret = false;
5981 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5982 ret = false;
5985 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5986 ret = false;
5989 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5990 ret = false;
5993 return ret;
5996 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5997 struct torture_context *tctx,
5998 struct policy_handle *handle, uint32_t rid)
6000 struct samr_OpenAlias r;
6001 struct policy_handle alias_handle;
6002 bool ret = true;
6004 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
6006 r.in.domain_handle = handle;
6007 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6008 r.in.rid = rid;
6009 r.out.alias_handle = &alias_handle;
6011 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
6012 "OpenAlias failed");
6013 if (!NT_STATUS_IS_OK(r.out.result)) {
6014 torture_result(tctx, TORTURE_FAIL, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6015 return false;
6018 if (!torture_setting_bool(tctx, "samba3", false)) {
6019 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
6020 ret = false;
6024 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6025 ret = false;
6028 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6029 ret = false;
6032 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6033 ret = false;
6036 return ret;
6039 static bool check_mask(struct dcerpc_binding_handle *b,
6040 struct torture_context *tctx,
6041 struct policy_handle *handle, uint32_t rid,
6042 uint32_t acct_flag_mask)
6044 struct samr_OpenUser r;
6045 struct samr_QueryUserInfo q;
6046 union samr_UserInfo *info;
6047 struct policy_handle user_handle;
6048 bool ret = true;
6050 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6052 r.in.domain_handle = handle;
6053 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6054 r.in.rid = rid;
6055 r.out.user_handle = &user_handle;
6057 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6058 "OpenUser failed");
6059 if (!NT_STATUS_IS_OK(r.out.result)) {
6060 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6061 return false;
6064 q.in.user_handle = &user_handle;
6065 q.in.level = 16;
6066 q.out.info = &info;
6068 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6069 "QueryUserInfo failed");
6070 if (!NT_STATUS_IS_OK(q.out.result)) {
6071 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed - %s\n",
6072 nt_errstr(q.out.result));
6073 ret = false;
6074 } else {
6075 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
6076 torture_result(tctx, TORTURE_FAIL, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
6077 acct_flag_mask, info->info16.acct_flags, rid);
6078 ret = false;
6082 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6083 ret = false;
6086 return ret;
6089 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
6090 struct torture_context *tctx,
6091 struct policy_handle *handle)
6093 struct samr_EnumDomainUsers r;
6094 uint32_t mask, resume_handle=0;
6095 int i, mask_idx;
6096 bool ret = true;
6097 struct samr_LookupNames n;
6098 struct samr_LookupRids lr ;
6099 struct lsa_Strings names;
6100 struct samr_Ids rids, types;
6101 struct samr_SamArray *sam = NULL;
6102 uint32_t num_entries = 0;
6104 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
6105 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
6106 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
6107 ACB_PWNOEXP, 0};
6109 torture_comment(tctx, "Testing EnumDomainUsers\n");
6111 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
6112 r.in.domain_handle = handle;
6113 r.in.resume_handle = &resume_handle;
6114 r.in.acct_flags = mask = masks[mask_idx];
6115 r.in.max_size = (uint32_t)-1;
6116 r.out.resume_handle = &resume_handle;
6117 r.out.num_entries = &num_entries;
6118 r.out.sam = &sam;
6120 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
6121 "EnumDomainUsers failed");
6122 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6123 !NT_STATUS_IS_OK(r.out.result)) {
6124 torture_result(tctx, TORTURE_FAIL, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
6125 return false;
6128 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6130 if (sam->count == 0) {
6131 continue;
6134 for (i=0;i<sam->count;i++) {
6135 if (mask) {
6136 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6137 ret = false;
6139 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6140 ret = false;
6145 torture_comment(tctx, "Testing LookupNames\n");
6146 n.in.domain_handle = handle;
6147 n.in.num_names = sam->count;
6148 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6149 n.out.rids = &rids;
6150 n.out.types = &types;
6151 for (i=0;i<sam->count;i++) {
6152 n.in.names[i].string = sam->entries[i].name.string;
6154 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6155 "LookupNames failed");
6156 if (!NT_STATUS_IS_OK(n.out.result)) {
6157 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6158 ret = false;
6162 torture_comment(tctx, "Testing LookupRids\n");
6163 lr.in.domain_handle = handle;
6164 lr.in.num_rids = sam->count;
6165 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6166 lr.out.names = &names;
6167 lr.out.types = &types;
6168 for (i=0;i<sam->count;i++) {
6169 lr.in.rids[i] = sam->entries[i].idx;
6171 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6172 "LookupRids failed");
6173 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6175 return ret;
6179 try blasting the server with a bunch of sync requests
6181 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6182 struct policy_handle *handle)
6184 struct samr_EnumDomainUsers r;
6185 uint32_t resume_handle=0;
6186 int i;
6187 #define ASYNC_COUNT 100
6188 struct tevent_req *req[ASYNC_COUNT];
6190 if (!torture_setting_bool(tctx, "dangerous", false)) {
6191 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6194 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6196 r.in.domain_handle = handle;
6197 r.in.resume_handle = &resume_handle;
6198 r.in.acct_flags = 0;
6199 r.in.max_size = (uint32_t)-1;
6200 r.out.resume_handle = &resume_handle;
6202 for (i=0;i<ASYNC_COUNT;i++) {
6203 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6206 for (i=0;i<ASYNC_COUNT;i++) {
6207 tevent_req_poll(req[i], tctx->ev);
6208 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6209 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6210 i, nt_errstr(r.out.result)));
6213 torture_comment(tctx, "%d async requests OK\n", i);
6215 return true;
6218 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6219 struct torture_context *tctx,
6220 struct policy_handle *handle)
6222 struct samr_EnumDomainGroups r;
6223 uint32_t resume_handle=0;
6224 struct samr_SamArray *sam = NULL;
6225 uint32_t num_entries = 0;
6226 int i;
6227 bool ret = true;
6228 bool universal_group_found = false;
6230 torture_comment(tctx, "Testing EnumDomainGroups\n");
6232 r.in.domain_handle = handle;
6233 r.in.resume_handle = &resume_handle;
6234 r.in.max_size = (uint32_t)-1;
6235 r.out.resume_handle = &resume_handle;
6236 r.out.num_entries = &num_entries;
6237 r.out.sam = &sam;
6239 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6240 "EnumDomainGroups failed");
6241 if (!NT_STATUS_IS_OK(r.out.result)) {
6242 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6243 return false;
6246 if (!sam) {
6247 return false;
6250 for (i=0;i<sam->count;i++) {
6251 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6252 ret = false;
6254 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6255 "Enterprise Admins") == 0)) {
6256 universal_group_found = true;
6260 /* when we are running this on s4 we should get back at least the
6261 * "Enterprise Admins" universal group. If we don't get a group entry
6262 * at all we probably are performing the test on the builtin domain.
6263 * So ignore this case. */
6264 if (torture_setting_bool(tctx, "samba4", false)) {
6265 if ((sam->count > 0) && (!universal_group_found)) {
6266 ret = false;
6270 return ret;
6273 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6274 struct torture_context *tctx,
6275 struct policy_handle *handle)
6277 struct samr_EnumDomainAliases r;
6278 uint32_t resume_handle=0;
6279 struct samr_SamArray *sam = NULL;
6280 uint32_t num_entries = 0;
6281 int i;
6282 bool ret = true;
6284 torture_comment(tctx, "Testing EnumDomainAliases\n");
6286 r.in.domain_handle = handle;
6287 r.in.resume_handle = &resume_handle;
6288 r.in.max_size = (uint32_t)-1;
6289 r.out.sam = &sam;
6290 r.out.num_entries = &num_entries;
6291 r.out.resume_handle = &resume_handle;
6293 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6294 "EnumDomainAliases failed");
6295 if (!NT_STATUS_IS_OK(r.out.result)) {
6296 torture_result(tctx, TORTURE_FAIL, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6297 return false;
6300 if (!sam) {
6301 return false;
6304 for (i=0;i<sam->count;i++) {
6305 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6306 ret = false;
6310 return ret;
6313 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6314 struct torture_context *tctx,
6315 struct policy_handle *handle)
6317 struct samr_GetDisplayEnumerationIndex r;
6318 bool ret = true;
6319 uint16_t levels[] = {1, 2, 3, 4, 5};
6320 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6321 struct lsa_String name;
6322 uint32_t idx = 0;
6323 int i;
6325 for (i=0;i<ARRAY_SIZE(levels);i++) {
6326 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6328 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6330 r.in.domain_handle = handle;
6331 r.in.level = levels[i];
6332 r.in.name = &name;
6333 r.out.idx = &idx;
6335 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6336 "GetDisplayEnumerationIndex failed");
6338 if (ok_lvl[i] &&
6339 !NT_STATUS_IS_OK(r.out.result) &&
6340 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6341 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6342 levels[i], nt_errstr(r.out.result));
6343 ret = false;
6346 init_lsa_String(&name, "zzzzzzzz");
6348 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6349 "GetDisplayEnumerationIndex failed");
6351 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6352 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6353 levels[i], nt_errstr(r.out.result));
6354 ret = false;
6358 return ret;
6361 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6362 struct torture_context *tctx,
6363 struct policy_handle *handle)
6365 struct samr_GetDisplayEnumerationIndex2 r;
6366 bool ret = true;
6367 uint16_t levels[] = {1, 2, 3, 4, 5};
6368 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6369 struct lsa_String name;
6370 uint32_t idx = 0;
6371 int i;
6373 for (i=0;i<ARRAY_SIZE(levels);i++) {
6374 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6376 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6378 r.in.domain_handle = handle;
6379 r.in.level = levels[i];
6380 r.in.name = &name;
6381 r.out.idx = &idx;
6383 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6384 "GetDisplayEnumerationIndex2 failed");
6385 if (ok_lvl[i] &&
6386 !NT_STATUS_IS_OK(r.out.result) &&
6387 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6388 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6389 levels[i], nt_errstr(r.out.result));
6390 ret = false;
6393 init_lsa_String(&name, "zzzzzzzz");
6395 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6396 "GetDisplayEnumerationIndex2 failed");
6397 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6398 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6399 levels[i], nt_errstr(r.out.result));
6400 ret = false;
6404 return ret;
6407 #define STRING_EQUAL_QUERY(s1, s2, user) \
6408 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6409 /* odd, but valid */ \
6410 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6411 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: %s != %s (%s)\n", \
6412 #s1, user.string, s1.string, s2.string, __location__); \
6413 ret = false; \
6415 #define INT_EQUAL_QUERY(s1, s2, user) \
6416 if (s1 != s2) { \
6417 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6418 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6419 ret = false; \
6422 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6423 struct torture_context *tctx,
6424 struct samr_QueryDisplayInfo *querydisplayinfo,
6425 bool *seen_testuser)
6427 struct samr_OpenUser r;
6428 struct samr_QueryUserInfo q;
6429 union samr_UserInfo *info;
6430 struct policy_handle user_handle;
6431 int i, ret = true;
6432 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6433 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6434 for (i = 0; ; i++) {
6435 switch (querydisplayinfo->in.level) {
6436 case 1:
6437 if (i >= querydisplayinfo->out.info->info1.count) {
6438 return ret;
6440 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6441 break;
6442 case 2:
6443 if (i >= querydisplayinfo->out.info->info2.count) {
6444 return ret;
6446 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6447 break;
6448 case 3:
6449 /* Groups */
6450 case 4:
6451 case 5:
6452 /* Not interested in validating just the account name */
6453 return true;
6456 r.out.user_handle = &user_handle;
6458 switch (querydisplayinfo->in.level) {
6459 case 1:
6460 case 2:
6461 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6462 "OpenUser failed");
6463 if (!NT_STATUS_IS_OK(r.out.result)) {
6464 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6465 return false;
6469 q.in.user_handle = &user_handle;
6470 q.in.level = 21;
6471 q.out.info = &info;
6472 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6473 "QueryUserInfo failed");
6474 if (!NT_STATUS_IS_OK(r.out.result)) {
6475 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6476 return false;
6479 switch (querydisplayinfo->in.level) {
6480 case 1:
6481 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6482 *seen_testuser = true;
6484 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6485 info->info21.full_name, info->info21.account_name);
6486 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6487 info->info21.account_name, info->info21.account_name);
6488 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6489 info->info21.description, info->info21.account_name);
6490 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6491 info->info21.rid, info->info21.account_name);
6492 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6493 info->info21.acct_flags, info->info21.account_name);
6495 break;
6496 case 2:
6497 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6498 info->info21.account_name, info->info21.account_name);
6499 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6500 info->info21.description, info->info21.account_name);
6501 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6502 info->info21.rid, info->info21.account_name);
6503 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6504 info->info21.acct_flags, info->info21.account_name);
6506 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6507 torture_result(tctx, TORTURE_FAIL, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6508 info->info21.account_name.string);
6511 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6512 torture_result(tctx, TORTURE_FAIL, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6513 info->info21.account_name.string,
6514 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6515 info->info21.acct_flags);
6516 return false;
6519 break;
6522 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6523 return false;
6526 return ret;
6529 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6530 struct torture_context *tctx,
6531 struct policy_handle *handle)
6533 struct samr_QueryDisplayInfo r;
6534 struct samr_QueryDomainInfo dom_info;
6535 union samr_DomainInfo *info = NULL;
6536 bool ret = true;
6537 uint16_t levels[] = {1, 2, 3, 4, 5};
6538 int i;
6539 bool seen_testuser = false;
6540 uint32_t total_size;
6541 uint32_t returned_size;
6542 union samr_DispInfo disp_info;
6545 for (i=0;i<ARRAY_SIZE(levels);i++) {
6546 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6548 r.in.start_idx = 0;
6549 r.out.result = STATUS_MORE_ENTRIES;
6550 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6551 r.in.domain_handle = handle;
6552 r.in.level = levels[i];
6553 r.in.max_entries = 2;
6554 r.in.buf_size = (uint32_t)-1;
6555 r.out.total_size = &total_size;
6556 r.out.returned_size = &returned_size;
6557 r.out.info = &disp_info;
6559 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6560 "QueryDisplayInfo failed");
6561 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6562 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
6563 levels[i], nt_errstr(r.out.result));
6564 ret = false;
6566 switch (r.in.level) {
6567 case 1:
6568 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6569 ret = false;
6571 r.in.start_idx += r.out.info->info1.count;
6572 break;
6573 case 2:
6574 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6575 ret = false;
6577 r.in.start_idx += r.out.info->info2.count;
6578 break;
6579 case 3:
6580 r.in.start_idx += r.out.info->info3.count;
6581 break;
6582 case 4:
6583 r.in.start_idx += r.out.info->info4.count;
6584 break;
6585 case 5:
6586 r.in.start_idx += r.out.info->info5.count;
6587 break;
6590 dom_info.in.domain_handle = handle;
6591 dom_info.in.level = 2;
6592 dom_info.out.info = &info;
6594 /* Check number of users returned is correct */
6595 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6596 "QueryDomainInfo failed");
6597 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6598 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6599 r.in.level, nt_errstr(dom_info.out.result));
6600 ret = false;
6601 break;
6603 switch (r.in.level) {
6604 case 1:
6605 case 4:
6606 if (info->general.num_users < r.in.start_idx) {
6607 /* On AD deployments this numbers don't match
6608 * since QueryDisplayInfo returns universal and
6609 * global groups, QueryDomainInfo only global
6610 * ones. */
6611 if (torture_setting_bool(tctx, "samba3", false)) {
6612 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6613 r.in.start_idx, info->general.num_groups,
6614 info->general.domain_name.string);
6615 ret = false;
6618 if (!seen_testuser) {
6619 struct policy_handle user_handle;
6620 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6621 torture_result(tctx, TORTURE_FAIL, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6622 info->general.domain_name.string);
6623 ret = false;
6624 test_samr_handle_Close(b, tctx, &user_handle);
6627 break;
6628 case 3:
6629 case 5:
6630 if (info->general.num_groups != r.in.start_idx) {
6631 /* On AD deployments this numbers don't match
6632 * since QueryDisplayInfo returns universal and
6633 * global groups, QueryDomainInfo only global
6634 * ones. */
6635 if (torture_setting_bool(tctx, "samba3", false)) {
6636 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6637 r.in.start_idx, info->general.num_groups,
6638 info->general.domain_name.string);
6639 ret = false;
6643 break;
6648 return ret;
6651 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6652 struct torture_context *tctx,
6653 struct policy_handle *handle)
6655 struct samr_QueryDisplayInfo2 r;
6656 bool ret = true;
6657 uint16_t levels[] = {1, 2, 3, 4, 5};
6658 int i;
6659 uint32_t total_size;
6660 uint32_t returned_size;
6661 union samr_DispInfo info;
6663 for (i=0;i<ARRAY_SIZE(levels);i++) {
6664 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6666 r.in.domain_handle = handle;
6667 r.in.level = levels[i];
6668 r.in.start_idx = 0;
6669 r.in.max_entries = 1000;
6670 r.in.buf_size = (uint32_t)-1;
6671 r.out.total_size = &total_size;
6672 r.out.returned_size = &returned_size;
6673 r.out.info = &info;
6675 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6676 "QueryDisplayInfo2 failed");
6677 if (!NT_STATUS_IS_OK(r.out.result)) {
6678 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo2 level %u failed - %s\n",
6679 levels[i], nt_errstr(r.out.result));
6680 ret = false;
6684 return ret;
6687 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6688 struct torture_context *tctx,
6689 struct policy_handle *handle)
6691 struct samr_QueryDisplayInfo3 r;
6692 bool ret = true;
6693 uint16_t levels[] = {1, 2, 3, 4, 5};
6694 int i;
6695 uint32_t total_size;
6696 uint32_t returned_size;
6697 union samr_DispInfo info;
6699 for (i=0;i<ARRAY_SIZE(levels);i++) {
6700 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6702 r.in.domain_handle = handle;
6703 r.in.level = levels[i];
6704 r.in.start_idx = 0;
6705 r.in.max_entries = 1000;
6706 r.in.buf_size = (uint32_t)-1;
6707 r.out.total_size = &total_size;
6708 r.out.returned_size = &returned_size;
6709 r.out.info = &info;
6711 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6712 "QueryDisplayInfo3 failed");
6713 if (!NT_STATUS_IS_OK(r.out.result)) {
6714 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo3 level %u failed - %s\n",
6715 levels[i], nt_errstr(r.out.result));
6716 ret = false;
6720 return ret;
6724 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6725 struct torture_context *tctx,
6726 struct policy_handle *handle)
6728 struct samr_QueryDisplayInfo r;
6729 bool ret = true;
6730 uint32_t total_size;
6731 uint32_t returned_size;
6732 union samr_DispInfo info;
6734 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6736 r.in.domain_handle = handle;
6737 r.in.level = 1;
6738 r.in.start_idx = 0;
6739 r.in.max_entries = 1;
6740 r.in.buf_size = (uint32_t)-1;
6741 r.out.total_size = &total_size;
6742 r.out.returned_size = &returned_size;
6743 r.out.info = &info;
6745 do {
6746 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6747 "QueryDisplayInfo failed");
6748 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6749 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6750 torture_result(tctx, TORTURE_FAIL, "expected idx %d but got %d\n",
6751 r.in.start_idx + 1,
6752 r.out.info->info1.entries[0].idx);
6753 break;
6756 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6757 !NT_STATUS_IS_OK(r.out.result)) {
6758 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
6759 r.in.level, nt_errstr(r.out.result));
6760 ret = false;
6761 break;
6763 r.in.start_idx++;
6764 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6765 NT_STATUS_IS_OK(r.out.result)) &&
6766 *r.out.returned_size != 0);
6768 return ret;
6771 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6772 struct torture_context *tctx,
6773 struct policy_handle *handle)
6775 struct samr_QueryDomainInfo r;
6776 union samr_DomainInfo *info = NULL;
6777 struct samr_SetDomainInfo s;
6778 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6779 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6780 int i;
6781 bool ret = true;
6782 struct dcerpc_binding_handle *b = p->binding_handle;
6783 const char *domain_comment = talloc_asprintf(tctx,
6784 "Tortured by Samba4 RPC-SAMR: %s",
6785 timestring(tctx, time(NULL)));
6787 s.in.domain_handle = handle;
6788 s.in.level = 4;
6789 s.in.info = talloc(tctx, union samr_DomainInfo);
6791 s.in.info->oem.oem_information.string = domain_comment;
6792 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6793 "SetDomainInfo failed");
6794 if (!NT_STATUS_IS_OK(s.out.result)) {
6795 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u (set comment) failed - %s\n",
6796 s.in.level, nt_errstr(s.out.result));
6797 return false;
6800 for (i=0;i<ARRAY_SIZE(levels);i++) {
6801 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6803 r.in.domain_handle = handle;
6804 r.in.level = levels[i];
6805 r.out.info = &info;
6807 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6808 "QueryDomainInfo failed");
6809 if (!NT_STATUS_IS_OK(r.out.result)) {
6810 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6811 r.in.level, nt_errstr(r.out.result));
6812 ret = false;
6813 continue;
6816 switch (levels[i]) {
6817 case 2:
6818 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6819 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6820 levels[i], info->general.oem_information.string, domain_comment);
6821 if (!torture_setting_bool(tctx, "samba3", false)) {
6822 ret = false;
6825 if (!info->general.primary.string) {
6826 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
6827 levels[i]);
6828 ret = false;
6829 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6830 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6831 if (torture_setting_bool(tctx, "samba3", false)) {
6832 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",
6833 levels[i], info->general.primary.string, dcerpc_server_name(p));
6837 break;
6838 case 4:
6839 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6840 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6841 levels[i], info->oem.oem_information.string, domain_comment);
6842 if (!torture_setting_bool(tctx, "samba3", false)) {
6843 ret = false;
6846 break;
6847 case 6:
6848 if (!info->info6.primary.string) {
6849 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
6850 levels[i]);
6851 ret = false;
6853 break;
6854 case 11:
6855 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6856 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6857 levels[i], info->general2.general.oem_information.string, domain_comment);
6858 if (!torture_setting_bool(tctx, "samba3", false)) {
6859 ret = false;
6862 break;
6865 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6867 s.in.domain_handle = handle;
6868 s.in.level = levels[i];
6869 s.in.info = info;
6871 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6872 "SetDomainInfo failed");
6873 if (set_ok[i]) {
6874 if (!NT_STATUS_IS_OK(s.out.result)) {
6875 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u failed - %s\n",
6876 r.in.level, nt_errstr(s.out.result));
6877 ret = false;
6878 continue;
6880 } else {
6881 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6882 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6883 r.in.level, nt_errstr(s.out.result));
6884 ret = false;
6885 continue;
6889 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6890 "QueryDomainInfo failed");
6891 if (!NT_STATUS_IS_OK(r.out.result)) {
6892 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6893 r.in.level, nt_errstr(r.out.result));
6894 ret = false;
6895 continue;
6899 return ret;
6903 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6904 struct torture_context *tctx,
6905 struct policy_handle *handle)
6907 struct samr_QueryDomainInfo2 r;
6908 union samr_DomainInfo *info = NULL;
6909 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6910 int i;
6911 bool ret = true;
6913 for (i=0;i<ARRAY_SIZE(levels);i++) {
6914 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6916 r.in.domain_handle = handle;
6917 r.in.level = levels[i];
6918 r.out.info = &info;
6920 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6921 "QueryDomainInfo2 failed");
6922 if (!NT_STATUS_IS_OK(r.out.result)) {
6923 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo2 level %u failed - %s\n",
6924 r.in.level, nt_errstr(r.out.result));
6925 ret = false;
6926 continue;
6930 return true;
6933 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6934 set of group names. */
6935 static bool test_GroupList(struct dcerpc_binding_handle *b,
6936 struct torture_context *tctx,
6937 struct dom_sid *domain_sid,
6938 struct policy_handle *handle)
6940 struct samr_EnumDomainGroups q1;
6941 struct samr_QueryDisplayInfo q2;
6942 NTSTATUS status;
6943 uint32_t resume_handle=0;
6944 struct samr_SamArray *sam = NULL;
6945 uint32_t num_entries = 0;
6946 int i;
6947 bool ret = true;
6948 uint32_t total_size;
6949 uint32_t returned_size;
6950 union samr_DispInfo info;
6952 int num_names = 0;
6953 const char **names = NULL;
6955 bool builtin_domain = dom_sid_compare(domain_sid,
6956 &global_sid_Builtin) == 0;
6958 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6960 q1.in.domain_handle = handle;
6961 q1.in.resume_handle = &resume_handle;
6962 q1.in.max_size = 5;
6963 q1.out.resume_handle = &resume_handle;
6964 q1.out.num_entries = &num_entries;
6965 q1.out.sam = &sam;
6967 status = STATUS_MORE_ENTRIES;
6968 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6969 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6970 "EnumDomainGroups failed");
6971 status = q1.out.result;
6973 if (!NT_STATUS_IS_OK(status) &&
6974 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6975 break;
6977 for (i=0; i<*q1.out.num_entries; i++) {
6978 add_string_to_array(tctx,
6979 sam->entries[i].name.string,
6980 &names, &num_names);
6984 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6986 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6988 if (builtin_domain) {
6989 torture_assert(tctx, num_names == 0,
6990 "EnumDomainGroups shouldn't return any group in the builtin domain!");
6993 q2.in.domain_handle = handle;
6994 q2.in.level = 5;
6995 q2.in.start_idx = 0;
6996 q2.in.max_entries = 5;
6997 q2.in.buf_size = (uint32_t)-1;
6998 q2.out.total_size = &total_size;
6999 q2.out.returned_size = &returned_size;
7000 q2.out.info = &info;
7002 status = STATUS_MORE_ENTRIES;
7003 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7004 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
7005 "QueryDisplayInfo failed");
7006 status = q2.out.result;
7007 if (!NT_STATUS_IS_OK(status) &&
7008 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7009 break;
7011 for (i=0; i<q2.out.info->info5.count; i++) {
7012 int j;
7013 const char *name = q2.out.info->info5.entries[i].account_name.string;
7014 bool found = false;
7015 for (j=0; j<num_names; j++) {
7016 if (names[j] == NULL)
7017 continue;
7018 if (strequal(names[j], name)) {
7019 names[j] = NULL;
7020 found = true;
7021 break;
7025 if ((!found) && (!builtin_domain)) {
7026 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7027 name);
7028 ret = false;
7031 q2.in.start_idx += q2.out.info->info5.count;
7034 if (!NT_STATUS_IS_OK(status)) {
7035 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level 5 failed - %s\n",
7036 nt_errstr(status));
7037 ret = false;
7040 if (builtin_domain) {
7041 torture_assert(tctx, q2.in.start_idx != 0,
7042 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
7045 for (i=0; i<num_names; i++) {
7046 if (names[i] != NULL) {
7047 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
7048 names[i]);
7049 ret = false;
7053 return ret;
7056 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
7057 struct torture_context *tctx,
7058 struct policy_handle *group_handle)
7060 struct samr_DeleteDomainGroup d;
7062 torture_comment(tctx, "Testing DeleteDomainGroup\n");
7064 d.in.group_handle = group_handle;
7065 d.out.group_handle = group_handle;
7067 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
7068 "DeleteDomainGroup failed");
7069 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
7071 return true;
7074 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
7075 struct torture_context *tctx,
7076 struct policy_handle *domain_handle)
7078 struct samr_TestPrivateFunctionsDomain r;
7079 bool ret = true;
7081 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
7083 r.in.domain_handle = domain_handle;
7085 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
7086 "TestPrivateFunctionsDomain failed");
7087 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
7089 return ret;
7092 static bool test_RidToSid(struct dcerpc_binding_handle *b,
7093 struct torture_context *tctx,
7094 struct dom_sid *domain_sid,
7095 struct policy_handle *domain_handle)
7097 struct samr_RidToSid r;
7098 bool ret = true;
7099 struct dom_sid *calc_sid, *out_sid;
7100 int rids[] = { 0, 42, 512, 10200 };
7101 int i;
7103 for (i=0;i<ARRAY_SIZE(rids);i++) {
7104 torture_comment(tctx, "Testing RidToSid\n");
7106 calc_sid = dom_sid_dup(tctx, domain_sid);
7107 r.in.domain_handle = domain_handle;
7108 r.in.rid = rids[i];
7109 r.out.sid = &out_sid;
7111 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
7112 "RidToSid failed");
7113 if (!NT_STATUS_IS_OK(r.out.result)) {
7114 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
7115 ret = false;
7116 } else {
7117 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
7119 if (!dom_sid_equal(calc_sid, out_sid)) {
7120 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
7121 dom_sid_string(tctx, out_sid),
7122 dom_sid_string(tctx, calc_sid));
7123 ret = false;
7128 return ret;
7131 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7132 struct torture_context *tctx,
7133 struct policy_handle *domain_handle)
7135 struct samr_GetBootKeyInformation r;
7136 bool ret = true;
7137 uint32_t unknown = 0;
7138 NTSTATUS status;
7140 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7142 r.in.domain_handle = domain_handle;
7143 r.out.unknown = &unknown;
7145 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7146 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7147 status = r.out.result;
7149 if (!NT_STATUS_IS_OK(status)) {
7150 /* w2k3 seems to fail this sometimes and pass it sometimes */
7151 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7154 return ret;
7157 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7158 struct torture_context *tctx,
7159 struct policy_handle *domain_handle,
7160 struct policy_handle *group_handle)
7162 NTSTATUS status;
7163 struct samr_AddGroupMember r;
7164 struct samr_DeleteGroupMember d;
7165 struct samr_QueryGroupMember q;
7166 struct samr_RidAttrArray *rids = NULL;
7167 struct samr_SetMemberAttributesOfGroup s;
7168 uint32_t rid;
7169 bool found_member = false;
7170 int i;
7172 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7173 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7175 r.in.group_handle = group_handle;
7176 r.in.rid = rid;
7177 r.in.flags = 0; /* ??? */
7179 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7181 d.in.group_handle = group_handle;
7182 d.in.rid = rid;
7184 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7185 "DeleteGroupMember failed");
7186 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7188 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7189 "AddGroupMember failed");
7190 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7192 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7193 "AddGroupMember failed");
7194 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7196 if (torture_setting_bool(tctx, "samba4", false) ||
7197 torture_setting_bool(tctx, "samba3", false)) {
7198 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7199 } else {
7200 /* this one is quite strange. I am using random inputs in the
7201 hope of triggering an error that might give us a clue */
7203 s.in.group_handle = group_handle;
7204 s.in.unknown1 = random();
7205 s.in.unknown2 = random();
7207 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7208 "SetMemberAttributesOfGroup failed");
7209 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7212 q.in.group_handle = group_handle;
7213 q.out.rids = &rids;
7215 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7216 "QueryGroupMember failed");
7217 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7218 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7220 for (i=0; i < rids->count; i++) {
7221 if (rids->rids[i] == rid) {
7222 found_member = true;
7226 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7228 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7229 "DeleteGroupMember failed");
7230 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7232 rids = NULL;
7233 found_member = false;
7235 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7236 "QueryGroupMember failed");
7237 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7238 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7240 for (i=0; i < rids->count; i++) {
7241 if (rids->rids[i] == rid) {
7242 found_member = true;
7246 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7248 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7249 "AddGroupMember failed");
7250 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7252 return true;
7256 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7257 struct torture_context *tctx,
7258 struct policy_handle *domain_handle,
7259 const char *group_name,
7260 struct policy_handle *group_handle,
7261 struct dom_sid *domain_sid,
7262 bool test_group)
7264 struct samr_CreateDomainGroup r;
7265 uint32_t rid;
7266 struct lsa_String name;
7267 bool ret = true;
7269 init_lsa_String(&name, group_name);
7271 r.in.domain_handle = domain_handle;
7272 r.in.name = &name;
7273 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7274 r.out.group_handle = group_handle;
7275 r.out.rid = &rid;
7277 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7279 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7280 "CreateDomainGroup failed");
7282 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7283 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7284 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7285 return true;
7286 } else {
7287 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7288 nt_errstr(r.out.result));
7289 return false;
7293 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7294 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7295 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7296 nt_errstr(r.out.result));
7297 return false;
7299 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7300 "CreateDomainGroup failed");
7302 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7303 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7305 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7306 nt_errstr(r.out.result));
7307 return false;
7309 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7310 "CreateDomainGroup failed");
7312 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7314 if (!test_group) {
7315 return ret;
7318 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7319 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7320 ret = false;
7323 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7324 ret = false;
7327 return ret;
7332 its not totally clear what this does. It seems to accept any sid you like.
7334 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7335 struct torture_context *tctx,
7336 struct policy_handle *domain_handle)
7338 struct samr_RemoveMemberFromForeignDomain r;
7340 r.in.domain_handle = domain_handle;
7341 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7343 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7344 "RemoveMemberFromForeignDomain failed");
7345 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7347 return true;
7350 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7351 struct torture_context *tctx,
7352 struct policy_handle *domain_handle,
7353 uint32_t *total_num_entries_p)
7355 NTSTATUS status;
7356 struct samr_EnumDomainUsers r;
7357 uint32_t resume_handle = 0;
7358 uint32_t num_entries = 0;
7359 uint32_t total_num_entries = 0;
7360 struct samr_SamArray *sam;
7362 r.in.domain_handle = domain_handle;
7363 r.in.acct_flags = 0;
7364 r.in.max_size = (uint32_t)-1;
7365 r.in.resume_handle = &resume_handle;
7367 r.out.sam = &sam;
7368 r.out.num_entries = &num_entries;
7369 r.out.resume_handle = &resume_handle;
7371 torture_comment(tctx, "Testing EnumDomainUsers\n");
7373 do {
7374 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7375 "EnumDomainUsers failed");
7376 if (NT_STATUS_IS_ERR(r.out.result)) {
7377 torture_assert_ntstatus_ok(tctx, r.out.result,
7378 "failed to enumerate users");
7380 status = r.out.result;
7382 total_num_entries += num_entries;
7383 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7385 if (total_num_entries_p) {
7386 *total_num_entries_p = total_num_entries;
7389 return true;
7392 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7393 struct torture_context *tctx,
7394 struct policy_handle *domain_handle,
7395 uint32_t *total_num_entries_p)
7397 NTSTATUS status;
7398 struct samr_EnumDomainGroups r;
7399 uint32_t resume_handle = 0;
7400 uint32_t num_entries = 0;
7401 uint32_t total_num_entries = 0;
7402 struct samr_SamArray *sam;
7404 r.in.domain_handle = domain_handle;
7405 r.in.max_size = (uint32_t)-1;
7406 r.in.resume_handle = &resume_handle;
7408 r.out.sam = &sam;
7409 r.out.num_entries = &num_entries;
7410 r.out.resume_handle = &resume_handle;
7412 torture_comment(tctx, "Testing EnumDomainGroups\n");
7414 do {
7415 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7416 "EnumDomainGroups failed");
7417 if (NT_STATUS_IS_ERR(r.out.result)) {
7418 torture_assert_ntstatus_ok(tctx, r.out.result,
7419 "failed to enumerate groups");
7421 status = r.out.result;
7423 total_num_entries += num_entries;
7424 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7426 if (total_num_entries_p) {
7427 *total_num_entries_p = total_num_entries;
7430 return true;
7433 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7434 struct torture_context *tctx,
7435 struct policy_handle *domain_handle,
7436 uint32_t *total_num_entries_p)
7438 NTSTATUS status;
7439 struct samr_EnumDomainAliases r;
7440 uint32_t resume_handle = 0;
7441 uint32_t num_entries = 0;
7442 uint32_t total_num_entries = 0;
7443 struct samr_SamArray *sam;
7445 r.in.domain_handle = domain_handle;
7446 r.in.max_size = (uint32_t)-1;
7447 r.in.resume_handle = &resume_handle;
7449 r.out.sam = &sam;
7450 r.out.num_entries = &num_entries;
7451 r.out.resume_handle = &resume_handle;
7453 torture_comment(tctx, "Testing EnumDomainAliases\n");
7455 do {
7456 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7457 "EnumDomainAliases failed");
7458 if (NT_STATUS_IS_ERR(r.out.result)) {
7459 torture_assert_ntstatus_ok(tctx, r.out.result,
7460 "failed to enumerate aliases");
7462 status = r.out.result;
7464 total_num_entries += num_entries;
7465 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7467 if (total_num_entries_p) {
7468 *total_num_entries_p = total_num_entries;
7471 return true;
7474 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7475 struct torture_context *tctx,
7476 struct policy_handle *handle,
7477 uint16_t level,
7478 uint32_t *total_num_entries_p)
7480 NTSTATUS status;
7481 struct samr_QueryDisplayInfo r;
7482 uint32_t total_num_entries = 0;
7484 r.in.domain_handle = handle;
7485 r.in.level = level;
7486 r.in.start_idx = 0;
7487 r.in.max_entries = (uint32_t)-1;
7488 r.in.buf_size = (uint32_t)-1;
7490 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7492 do {
7493 uint32_t total_size;
7494 uint32_t returned_size;
7495 union samr_DispInfo info;
7497 r.out.total_size = &total_size;
7498 r.out.returned_size = &returned_size;
7499 r.out.info = &info;
7501 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7502 "failed to query displayinfo");
7503 if (NT_STATUS_IS_ERR(r.out.result)) {
7504 torture_assert_ntstatus_ok(tctx, r.out.result,
7505 "failed to query displayinfo");
7507 status = r.out.result;
7509 if (*r.out.returned_size == 0) {
7510 break;
7513 switch (r.in.level) {
7514 case 1:
7515 total_num_entries += info.info1.count;
7516 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7517 break;
7518 case 2:
7519 total_num_entries += info.info2.count;
7520 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7521 break;
7522 case 3:
7523 total_num_entries += info.info3.count;
7524 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7525 break;
7526 case 4:
7527 total_num_entries += info.info4.count;
7528 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7529 break;
7530 case 5:
7531 total_num_entries += info.info5.count;
7532 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7533 break;
7534 default:
7535 return false;
7538 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7540 if (total_num_entries_p) {
7541 *total_num_entries_p = total_num_entries;
7544 return true;
7547 static bool test_ManyObjects(struct dcerpc_pipe *p,
7548 struct torture_context *tctx,
7549 struct policy_handle *domain_handle,
7550 struct dom_sid *domain_sid,
7551 struct torture_samr_context *ctx)
7553 uint32_t num_total = ctx->num_objects_large_dc;
7554 uint32_t num_enum = 0;
7555 uint32_t num_disp = 0;
7556 uint32_t num_created = 0;
7557 uint32_t num_anounced = 0;
7558 uint32_t i;
7559 struct dcerpc_binding_handle *b = p->binding_handle;
7561 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7563 /* query */
7566 struct samr_QueryDomainInfo2 r;
7567 union samr_DomainInfo *info;
7568 r.in.domain_handle = domain_handle;
7569 r.in.level = 2;
7570 r.out.info = &info;
7572 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7573 "QueryDomainInfo2 failed");
7574 torture_assert_ntstatus_ok(tctx, r.out.result,
7575 "failed to query domain info");
7577 switch (ctx->choice) {
7578 case TORTURE_SAMR_MANY_ACCOUNTS:
7579 num_anounced = info->general.num_users;
7580 break;
7581 case TORTURE_SAMR_MANY_GROUPS:
7582 num_anounced = info->general.num_groups;
7583 break;
7584 case TORTURE_SAMR_MANY_ALIASES:
7585 num_anounced = info->general.num_aliases;
7586 break;
7587 default:
7588 return false;
7592 /* create */
7594 for (i=0; i < num_total; i++) {
7596 const char *name = NULL;
7598 switch (ctx->choice) {
7599 case TORTURE_SAMR_MANY_ACCOUNTS:
7600 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7601 torture_assert(tctx,
7602 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7603 "failed to create user");
7604 break;
7605 case TORTURE_SAMR_MANY_GROUPS:
7606 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7607 torture_assert(tctx,
7608 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7609 "failed to create group");
7610 break;
7611 case TORTURE_SAMR_MANY_ALIASES:
7612 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7613 torture_assert(tctx,
7614 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7615 "failed to create alias");
7616 break;
7617 default:
7618 return false;
7620 if (!ndr_policy_handle_empty(&handles[i])) {
7621 num_created++;
7625 /* enum */
7627 switch (ctx->choice) {
7628 case TORTURE_SAMR_MANY_ACCOUNTS:
7629 torture_assert(tctx,
7630 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7631 "failed to enum users");
7632 break;
7633 case TORTURE_SAMR_MANY_GROUPS:
7634 torture_assert(tctx,
7635 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7636 "failed to enum groups");
7637 break;
7638 case TORTURE_SAMR_MANY_ALIASES:
7639 torture_assert(tctx,
7640 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7641 "failed to enum aliases");
7642 break;
7643 default:
7644 return false;
7647 /* dispinfo */
7649 switch (ctx->choice) {
7650 case TORTURE_SAMR_MANY_ACCOUNTS:
7651 torture_assert(tctx,
7652 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
7653 "failed to query display info");
7654 break;
7655 case TORTURE_SAMR_MANY_GROUPS:
7656 torture_assert(tctx,
7657 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
7658 "failed to query display info");
7659 break;
7660 case TORTURE_SAMR_MANY_ALIASES:
7661 /* no aliases in dispinfo */
7662 break;
7663 default:
7664 return false;
7667 /* close or delete */
7669 for (i=0; i < num_total; i++) {
7671 if (ndr_policy_handle_empty(&handles[i])) {
7672 continue;
7675 if (torture_setting_bool(tctx, "samba3", false)) {
7676 torture_assert(tctx,
7677 test_samr_handle_Close(b, tctx, &handles[i]),
7678 "failed to close handle");
7679 } else {
7680 switch (ctx->choice) {
7681 case TORTURE_SAMR_MANY_ACCOUNTS:
7682 torture_assert(tctx,
7683 test_DeleteUser(b, tctx, &handles[i]),
7684 "failed to delete user");
7685 break;
7686 case TORTURE_SAMR_MANY_GROUPS:
7687 torture_assert(tctx,
7688 test_DeleteDomainGroup(b, tctx, &handles[i]),
7689 "failed to delete group");
7690 break;
7691 case TORTURE_SAMR_MANY_ALIASES:
7692 torture_assert(tctx,
7693 test_DeleteAlias(b, tctx, &handles[i]),
7694 "failed to delete alias");
7695 break;
7696 default:
7697 return false;
7702 talloc_free(handles);
7704 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7705 torture_comment(tctx,
7706 "unexpected number of results (%u) returned in enum call, expected %u\n",
7707 num_enum, num_anounced + num_created);
7709 torture_comment(tctx,
7710 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7711 num_disp, num_anounced + num_created);
7714 return true;
7717 static bool test_Connect(struct dcerpc_binding_handle *b,
7718 struct torture_context *tctx,
7719 struct policy_handle *handle);
7721 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7722 struct torture_samr_context *ctx, struct dom_sid *sid)
7724 struct samr_OpenDomain r;
7725 struct policy_handle domain_handle;
7726 struct policy_handle alias_handle;
7727 struct policy_handle user_handle;
7728 struct policy_handle group_handle;
7729 bool ret = true;
7730 struct dcerpc_binding_handle *b = p->binding_handle;
7732 ZERO_STRUCT(alias_handle);
7733 ZERO_STRUCT(user_handle);
7734 ZERO_STRUCT(group_handle);
7735 ZERO_STRUCT(domain_handle);
7737 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7739 r.in.connect_handle = &ctx->handle;
7740 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7741 r.in.sid = sid;
7742 r.out.domain_handle = &domain_handle;
7744 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7745 "OpenDomain failed");
7746 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7748 /* run the domain tests with the main handle closed - this tests
7749 the servers reference counting */
7750 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7752 switch (ctx->choice) {
7753 case TORTURE_SAMR_PASSWORDS:
7754 case TORTURE_SAMR_USER_PRIVILEGES:
7755 if (!torture_setting_bool(tctx, "samba3", false)) {
7756 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7758 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7759 if (!ret) {
7760 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7762 break;
7763 case TORTURE_SAMR_USER_ATTRIBUTES:
7764 if (!torture_setting_bool(tctx, "samba3", false)) {
7765 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7767 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7768 /* This test needs 'complex' users to validate */
7769 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7770 if (!ret) {
7771 torture_result(tctx, TORTURE_FAIL, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7773 break;
7774 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7775 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7776 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7777 if (!torture_setting_bool(tctx, "samba3", false)) {
7778 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7780 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7781 if (!ret) {
7782 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7784 break;
7785 case TORTURE_SAMR_MANY_ACCOUNTS:
7786 case TORTURE_SAMR_MANY_GROUPS:
7787 case TORTURE_SAMR_MANY_ALIASES:
7788 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7789 if (!ret) {
7790 torture_result(tctx, TORTURE_FAIL, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7792 break;
7793 case TORTURE_SAMR_OTHER:
7794 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7795 if (!ret) {
7796 torture_result(tctx, TORTURE_FAIL, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7798 if (!torture_setting_bool(tctx, "samba3", false)) {
7799 ret &= test_QuerySecurity(b, tctx, &domain_handle);
7801 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7802 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7803 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7804 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7805 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7806 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7807 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7808 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7809 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7810 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7811 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7812 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7813 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7815 if (torture_setting_bool(tctx, "samba4", false)) {
7816 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7817 } else {
7818 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7819 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7821 ret &= test_GroupList(b, tctx, sid, &domain_handle);
7822 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7823 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7824 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7825 if (!ret) {
7826 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7828 break;
7831 if (!ndr_policy_handle_empty(&user_handle) &&
7832 !test_DeleteUser(b, tctx, &user_handle)) {
7833 ret = false;
7836 if (!ndr_policy_handle_empty(&alias_handle) &&
7837 !test_DeleteAlias(b, tctx, &alias_handle)) {
7838 ret = false;
7841 if (!ndr_policy_handle_empty(&group_handle) &&
7842 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7843 ret = false;
7846 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7848 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7849 /* reconnect the main handle */
7851 if (!ret) {
7852 torture_result(tctx, TORTURE_FAIL, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7855 return ret;
7858 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7859 struct torture_samr_context *ctx, const char *domain)
7861 struct samr_LookupDomain r;
7862 struct dom_sid2 *sid = NULL;
7863 struct lsa_String n1;
7864 struct lsa_String n2;
7865 bool ret = true;
7866 struct dcerpc_binding_handle *b = p->binding_handle;
7868 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7870 /* check for correct error codes */
7871 r.in.connect_handle = &ctx->handle;
7872 r.in.domain_name = &n2;
7873 r.out.sid = &sid;
7874 n2.string = NULL;
7876 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7877 "LookupDomain failed");
7878 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7880 init_lsa_String(&n2, "xxNODOMAINxx");
7882 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7883 "LookupDomain failed");
7884 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7886 r.in.connect_handle = &ctx->handle;
7888 init_lsa_String(&n1, domain);
7889 r.in.domain_name = &n1;
7891 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7892 "LookupDomain failed");
7893 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7895 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7896 ret = false;
7899 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7900 ret = false;
7903 return ret;
7907 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7908 struct torture_samr_context *ctx)
7910 struct samr_EnumDomains r;
7911 uint32_t resume_handle = 0;
7912 uint32_t num_entries = 0;
7913 struct samr_SamArray *sam = NULL;
7914 int i;
7915 bool ret = true;
7916 struct dcerpc_binding_handle *b = p->binding_handle;
7918 r.in.connect_handle = &ctx->handle;
7919 r.in.resume_handle = &resume_handle;
7920 r.in.buf_size = (uint32_t)-1;
7921 r.out.resume_handle = &resume_handle;
7922 r.out.num_entries = &num_entries;
7923 r.out.sam = &sam;
7925 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7926 "EnumDomains failed");
7927 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7929 if (!*r.out.sam) {
7930 return false;
7933 for (i=0;i<sam->count;i++) {
7934 if (!test_LookupDomain(p, tctx, ctx,
7935 sam->entries[i].name.string)) {
7936 ret = false;
7940 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7941 "EnumDomains failed");
7942 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7944 return ret;
7948 static bool test_Connect(struct dcerpc_binding_handle *b,
7949 struct torture_context *tctx,
7950 struct policy_handle *handle)
7952 struct samr_Connect r;
7953 struct samr_Connect2 r2;
7954 struct samr_Connect3 r3;
7955 struct samr_Connect4 r4;
7956 struct samr_Connect5 r5;
7957 union samr_ConnectInfo info;
7958 struct policy_handle h;
7959 uint32_t level_out = 0;
7960 bool ret = true, got_handle = false;
7962 torture_comment(tctx, "Testing samr_Connect\n");
7964 r.in.system_name = NULL;
7965 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7966 r.out.connect_handle = &h;
7968 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7969 "Connect failed");
7970 if (!NT_STATUS_IS_OK(r.out.result)) {
7971 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7972 ret = false;
7973 } else {
7974 got_handle = true;
7975 *handle = h;
7978 torture_comment(tctx, "Testing samr_Connect2\n");
7980 r2.in.system_name = NULL;
7981 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7982 r2.out.connect_handle = &h;
7984 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7985 "Connect2 failed");
7986 if (!NT_STATUS_IS_OK(r2.out.result)) {
7987 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7988 ret = false;
7989 } else {
7990 if (got_handle) {
7991 test_samr_handle_Close(b, tctx, handle);
7993 got_handle = true;
7994 *handle = h;
7997 torture_comment(tctx, "Testing samr_Connect3\n");
7999 r3.in.system_name = NULL;
8000 r3.in.unknown = 0;
8001 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8002 r3.out.connect_handle = &h;
8004 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
8005 "Connect3 failed");
8006 if (!NT_STATUS_IS_OK(r3.out.result)) {
8007 torture_result(tctx, TORTURE_FAIL, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
8008 ret = false;
8009 } else {
8010 if (got_handle) {
8011 test_samr_handle_Close(b, tctx, handle);
8013 got_handle = true;
8014 *handle = h;
8017 torture_comment(tctx, "Testing samr_Connect4\n");
8019 r4.in.system_name = "";
8020 r4.in.client_version = 0;
8021 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8022 r4.out.connect_handle = &h;
8024 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8025 "Connect4 failed");
8026 if (!NT_STATUS_IS_OK(r4.out.result)) {
8027 torture_result(tctx, TORTURE_FAIL, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8028 ret = false;
8029 } else {
8030 if (got_handle) {
8031 test_samr_handle_Close(b, tctx, handle);
8033 got_handle = true;
8034 *handle = h;
8037 torture_comment(tctx, "Testing samr_Connect5\n");
8039 info.info1.client_version = 0;
8040 info.info1.unknown2 = 0;
8042 r5.in.system_name = "";
8043 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8044 r5.in.level_in = 1;
8045 r5.out.level_out = &level_out;
8046 r5.in.info_in = &info;
8047 r5.out.info_out = &info;
8048 r5.out.connect_handle = &h;
8050 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
8051 "Connect5 failed");
8052 if (!NT_STATUS_IS_OK(r5.out.result)) {
8053 torture_result(tctx, TORTURE_FAIL, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
8054 ret = false;
8055 } else {
8056 if (got_handle) {
8057 test_samr_handle_Close(b, tctx, handle);
8059 got_handle = true;
8060 *handle = h;
8063 return ret;
8067 static bool test_samr_ValidatePassword(struct torture_context *tctx,
8068 struct dcerpc_pipe *p)
8070 struct samr_ValidatePassword r;
8071 union samr_ValidatePasswordReq req;
8072 union samr_ValidatePasswordRep *repp = NULL;
8073 NTSTATUS status;
8074 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
8075 int i;
8076 struct dcerpc_binding_handle *b = p->binding_handle;
8078 torture_comment(tctx, "Testing samr_ValidatePassword\n");
8080 if (p->conn->transport.transport != NCACN_IP_TCP) {
8081 torture_comment(tctx, "samr_ValidatePassword only should succeed over NCACN_IP_TCP!\n");
8084 ZERO_STRUCT(r);
8085 r.in.level = NetValidatePasswordReset;
8086 r.in.req = &req;
8087 r.out.rep = &repp;
8089 ZERO_STRUCT(req);
8090 req.req3.account.string = "non-existent-account-aklsdji";
8092 for (i=0; passwords[i]; i++) {
8093 req.req3.password.string = passwords[i];
8095 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
8096 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
8097 torture_skip(tctx, "ValidatePassword not supported by server\n");
8099 torture_assert_ntstatus_ok(tctx, status,
8100 "samr_ValidatePassword failed");
8101 torture_assert_ntstatus_ok(tctx, r.out.result,
8102 "samr_ValidatePassword failed");
8103 torture_comment(tctx, "Server %s password '%s' with code %i\n",
8104 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
8105 req.req3.password.string, repp->ctr3.status);
8108 return true;
8111 bool torture_rpc_samr(struct torture_context *torture)
8113 NTSTATUS status;
8114 struct dcerpc_pipe *p;
8115 bool ret = true;
8116 struct torture_samr_context *ctx;
8117 struct dcerpc_binding_handle *b;
8119 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8120 if (!NT_STATUS_IS_OK(status)) {
8121 return false;
8123 b = p->binding_handle;
8125 ctx = talloc_zero(torture, struct torture_samr_context);
8127 ctx->choice = TORTURE_SAMR_OTHER;
8129 ret &= test_Connect(b, torture, &ctx->handle);
8131 if (!torture_setting_bool(torture, "samba3", false)) {
8132 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8135 ret &= test_EnumDomains(p, torture, ctx);
8137 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8139 ret &= test_Shutdown(b, torture, &ctx->handle);
8141 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8143 return ret;
8147 bool torture_rpc_samr_users(struct torture_context *torture)
8149 NTSTATUS status;
8150 struct dcerpc_pipe *p;
8151 bool ret = true;
8152 struct torture_samr_context *ctx;
8153 struct dcerpc_binding_handle *b;
8155 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8156 if (!NT_STATUS_IS_OK(status)) {
8157 return false;
8159 b = p->binding_handle;
8161 ctx = talloc_zero(torture, struct torture_samr_context);
8163 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8165 ret &= test_Connect(b, torture, &ctx->handle);
8167 if (!torture_setting_bool(torture, "samba3", false)) {
8168 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8171 ret &= test_EnumDomains(p, torture, ctx);
8173 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8175 ret &= test_Shutdown(b, torture, &ctx->handle);
8177 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8179 return ret;
8183 bool torture_rpc_samr_passwords(struct torture_context *torture)
8185 NTSTATUS status;
8186 struct dcerpc_pipe *p;
8187 bool ret = true;
8188 struct torture_samr_context *ctx;
8189 struct dcerpc_binding_handle *b;
8191 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8192 if (!NT_STATUS_IS_OK(status)) {
8193 return false;
8195 b = p->binding_handle;
8197 ctx = talloc_zero(torture, struct torture_samr_context);
8199 ctx->choice = TORTURE_SAMR_PASSWORDS;
8201 ret &= test_Connect(b, torture, &ctx->handle);
8203 ret &= test_EnumDomains(p, torture, ctx);
8205 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8207 return ret;
8210 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8211 struct dcerpc_pipe *p2,
8212 struct cli_credentials *machine_credentials)
8214 NTSTATUS status;
8215 struct dcerpc_pipe *p;
8216 bool ret = true;
8217 struct torture_samr_context *ctx;
8218 struct dcerpc_binding_handle *b;
8220 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8221 if (!NT_STATUS_IS_OK(status)) {
8222 return false;
8224 b = p->binding_handle;
8226 ctx = talloc_zero(torture, struct torture_samr_context);
8228 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8229 ctx->machine_credentials = machine_credentials;
8231 ret &= test_Connect(b, torture, &ctx->handle);
8233 ret &= test_EnumDomains(p, torture, ctx);
8235 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8237 return ret;
8240 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8242 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8243 struct torture_rpc_tcase *tcase;
8245 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8246 &ndr_table_samr,
8247 TEST_ACCOUNT_NAME_PWD);
8249 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8250 torture_rpc_samr_pwdlastset);
8252 return suite;
8255 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8256 struct dcerpc_pipe *p2,
8257 struct cli_credentials *machine_credentials)
8259 NTSTATUS status;
8260 struct dcerpc_pipe *p;
8261 bool ret = true;
8262 struct torture_samr_context *ctx;
8263 struct dcerpc_binding_handle *b;
8265 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8266 if (!NT_STATUS_IS_OK(status)) {
8267 return false;
8269 b = p->binding_handle;
8271 ctx = talloc_zero(torture, struct torture_samr_context);
8273 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8274 ctx->machine_credentials = machine_credentials;
8276 ret &= test_Connect(b, torture, &ctx->handle);
8278 ret &= test_EnumDomains(p, torture, ctx);
8280 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8282 return ret;
8285 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8287 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8288 struct torture_rpc_tcase *tcase;
8290 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8291 &ndr_table_samr,
8292 TEST_ACCOUNT_NAME_PWD);
8294 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8295 torture_rpc_samr_users_privileges_delete_user);
8297 return suite;
8300 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8301 struct dcerpc_pipe *p2,
8302 void *data)
8304 NTSTATUS status;
8305 struct dcerpc_pipe *p;
8306 bool ret = true;
8307 struct torture_samr_context *ctx =
8308 talloc_get_type_abort(data, struct torture_samr_context);
8309 struct dcerpc_binding_handle *b;
8311 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8312 if (!NT_STATUS_IS_OK(status)) {
8313 return false;
8315 b = p->binding_handle;
8317 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8318 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8319 ctx->num_objects_large_dc);
8321 ret &= test_Connect(b, torture, &ctx->handle);
8323 ret &= test_EnumDomains(p, torture, ctx);
8325 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8327 return ret;
8330 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8331 struct dcerpc_pipe *p2,
8332 void *data)
8334 NTSTATUS status;
8335 struct dcerpc_pipe *p;
8336 bool ret = true;
8337 struct torture_samr_context *ctx =
8338 talloc_get_type_abort(data, struct torture_samr_context);
8339 struct dcerpc_binding_handle *b;
8341 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8342 if (!NT_STATUS_IS_OK(status)) {
8343 return false;
8345 b = p->binding_handle;
8347 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8348 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8349 ctx->num_objects_large_dc);
8351 ret &= test_Connect(b, torture, &ctx->handle);
8353 ret &= test_EnumDomains(p, torture, ctx);
8355 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8357 return ret;
8360 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8361 struct dcerpc_pipe *p2,
8362 void *data)
8364 NTSTATUS status;
8365 struct dcerpc_pipe *p;
8366 bool ret = true;
8367 struct torture_samr_context *ctx =
8368 talloc_get_type_abort(data, struct torture_samr_context);
8369 struct dcerpc_binding_handle *b;
8371 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8372 if (!NT_STATUS_IS_OK(status)) {
8373 return false;
8375 b = p->binding_handle;
8377 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8378 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8379 ctx->num_objects_large_dc);
8381 ret &= test_Connect(b, torture, &ctx->handle);
8383 ret &= test_EnumDomains(p, torture, ctx);
8385 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8387 return ret;
8390 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8392 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8393 struct torture_rpc_tcase *tcase;
8394 struct torture_samr_context *ctx;
8396 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8398 ctx = talloc_zero(suite, struct torture_samr_context);
8399 ctx->num_objects_large_dc = 150;
8401 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8402 torture_rpc_samr_many_aliases, ctx);
8403 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8404 torture_rpc_samr_many_groups, ctx);
8405 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8406 torture_rpc_samr_many_accounts, ctx);
8408 return suite;
8411 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8412 struct dcerpc_pipe *p2,
8413 struct cli_credentials *machine_credentials)
8415 NTSTATUS status;
8416 struct dcerpc_pipe *p;
8417 bool ret = true;
8418 struct torture_samr_context *ctx;
8419 struct dcerpc_binding_handle *b;
8421 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8422 if (!NT_STATUS_IS_OK(status)) {
8423 return false;
8425 b = p->binding_handle;
8427 ctx = talloc_zero(torture, struct torture_samr_context);
8429 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8430 ctx->machine_credentials = machine_credentials;
8432 ret &= test_Connect(b, torture, &ctx->handle);
8434 ret &= test_EnumDomains(p, torture, ctx);
8436 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8438 return ret;
8441 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8443 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8444 struct torture_rpc_tcase *tcase;
8446 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8447 &ndr_table_samr,
8448 TEST_ACCOUNT_NAME_PWD);
8450 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8451 torture_rpc_samr_badpwdcount);
8453 return suite;
8456 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8457 struct dcerpc_pipe *p2,
8458 struct cli_credentials *machine_credentials)
8460 NTSTATUS status;
8461 struct dcerpc_pipe *p;
8462 bool ret = true;
8463 struct torture_samr_context *ctx;
8464 struct dcerpc_binding_handle *b;
8466 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8467 if (!NT_STATUS_IS_OK(status)) {
8468 return false;
8470 b = p->binding_handle;
8472 ctx = talloc_zero(torture, struct torture_samr_context);
8474 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8475 ctx->machine_credentials = machine_credentials;
8477 ret &= test_Connect(b, torture, &ctx->handle);
8479 ret &= test_EnumDomains(p, torture, ctx);
8481 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8483 return ret;
8486 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8488 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8489 struct torture_rpc_tcase *tcase;
8491 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8492 &ndr_table_samr,
8493 TEST_ACCOUNT_NAME_PWD);
8495 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8496 torture_rpc_samr_lockout);
8498 return suite;
8501 struct torture_suite *torture_rpc_samr_passwords_validate(TALLOC_CTX *mem_ctx)
8503 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.validate");
8504 struct torture_rpc_tcase *tcase;
8506 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
8507 &ndr_table_samr);
8508 torture_rpc_tcase_add_test(tcase, "validate",
8509 test_samr_ValidatePassword);
8511 return suite;