torture-samr: Add testing of account lockout and password change behaviour
[Samba.git] / source4 / torture / rpc / samr.c
blob293f335363ae0b642910333dc858e76ef7b110b9
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 static bool test_ChangePasswordUser2_ntstatus(struct dcerpc_pipe *p, struct torture_context *tctx,
2302 const char *acct_name,
2303 const char *password, NTSTATUS status)
2305 struct samr_ChangePasswordUser2 r;
2306 bool ret = true;
2307 struct lsa_String server, account;
2308 struct samr_CryptPassword nt_pass, lm_pass;
2309 struct samr_Password nt_verifier, lm_verifier;
2310 const char *oldpass;
2311 struct dcerpc_binding_handle *b = p->binding_handle;
2312 uint8_t old_nt_hash[16], new_nt_hash[16];
2313 uint8_t old_lm_hash[16], new_lm_hash[16];
2315 struct samr_GetDomPwInfo dom_pw_info;
2316 struct samr_PwInfo info;
2318 struct lsa_String domain_name;
2319 char *newpass;
2320 int policy_min_pw_len = 0;
2322 domain_name.string = "";
2323 dom_pw_info.in.domain_name = &domain_name;
2324 dom_pw_info.out.info = &info;
2326 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2328 oldpass = password;
2330 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2331 "GetDomPwInfo failed");
2332 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2333 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2336 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2338 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2339 init_lsa_String(&account, acct_name);
2341 E_md4hash(oldpass, old_nt_hash);
2342 E_md4hash(newpass, new_nt_hash);
2344 E_deshash(oldpass, old_lm_hash);
2345 E_deshash(newpass, new_lm_hash);
2347 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2348 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2349 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2351 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2352 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2353 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2355 r.in.server = &server;
2356 r.in.account = &account;
2357 r.in.nt_password = &nt_pass;
2358 r.in.nt_verifier = &nt_verifier;
2359 r.in.lm_change = 1;
2360 r.in.lm_password = &lm_pass;
2361 r.in.lm_verifier = &lm_verifier;
2363 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2364 "ChangePasswordUser2 failed");
2365 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2366 __location__, __FUNCTION__,
2367 oldpass, newpass, nt_errstr(r.out.result));
2369 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2370 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2371 } else {
2372 torture_assert_ntstatus_equal(tctx, r.out.result, status, "ChangePasswordUser2 returned unexpected value");
2375 return true;
2379 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2380 const char *account_string,
2381 int policy_min_pw_len,
2382 char **password,
2383 const char *newpass,
2384 NTTIME last_password_change,
2385 bool handle_reject_reason)
2387 struct samr_ChangePasswordUser3 r;
2388 bool ret = true;
2389 struct lsa_String server, account, account_bad;
2390 struct samr_CryptPassword nt_pass, lm_pass;
2391 struct samr_Password nt_verifier, lm_verifier;
2392 char *oldpass;
2393 struct dcerpc_binding_handle *b = p->binding_handle;
2394 uint8_t old_nt_hash[16], new_nt_hash[16];
2395 uint8_t old_lm_hash[16], new_lm_hash[16];
2396 NTTIME t;
2397 struct samr_DomInfo1 *dominfo = NULL;
2398 struct userPwdChangeFailureInformation *reject = NULL;
2400 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2402 if (newpass == NULL) {
2403 do {
2404 if (policy_min_pw_len == 0) {
2405 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2406 } else {
2407 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2409 } while (check_password_quality(newpass) == false);
2410 } else {
2411 torture_comment(tctx, "Using password '%s'\n", newpass);
2414 torture_assert(tctx, *password != NULL,
2415 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2417 oldpass = *password;
2418 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2419 init_lsa_String(&account, account_string);
2421 E_md4hash(oldpass, old_nt_hash);
2422 E_md4hash(newpass, new_nt_hash);
2424 E_deshash(oldpass, old_lm_hash);
2425 E_deshash(newpass, new_lm_hash);
2427 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2428 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2429 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2431 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2432 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2433 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2435 /* Break the verification */
2436 nt_verifier.hash[0]++;
2438 r.in.server = &server;
2439 r.in.account = &account;
2440 r.in.nt_password = &nt_pass;
2441 r.in.nt_verifier = &nt_verifier;
2442 r.in.lm_change = 1;
2443 r.in.lm_password = &lm_pass;
2444 r.in.lm_verifier = &lm_verifier;
2445 r.in.password3 = NULL;
2446 r.out.dominfo = &dominfo;
2447 r.out.reject = &reject;
2449 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2450 "ChangePasswordUser3 failed");
2451 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2452 __location__, __FUNCTION__,
2453 oldpass, newpass, nt_errstr(r.out.result));
2454 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2455 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2456 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2457 nt_errstr(r.out.result));
2458 ret = false;
2461 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2462 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2463 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2465 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2466 /* Break the NT hash */
2467 old_nt_hash[0]++;
2468 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2469 /* Unbreak it again */
2470 old_nt_hash[0]--;
2471 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2473 r.in.server = &server;
2474 r.in.account = &account;
2475 r.in.nt_password = &nt_pass;
2476 r.in.nt_verifier = &nt_verifier;
2477 r.in.lm_change = 1;
2478 r.in.lm_password = &lm_pass;
2479 r.in.lm_verifier = &lm_verifier;
2480 r.in.password3 = NULL;
2481 r.out.dominfo = &dominfo;
2482 r.out.reject = &reject;
2484 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2485 "ChangePasswordUser3 failed");
2486 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2487 __location__, __FUNCTION__,
2488 oldpass, newpass, nt_errstr(r.out.result));
2489 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2490 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2491 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2492 nt_errstr(r.out.result));
2493 ret = false;
2496 /* This shouldn't be a valid name */
2497 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2499 r.in.account = &account_bad;
2500 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2501 "ChangePasswordUser3 failed");
2502 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2503 __location__, __FUNCTION__,
2504 oldpass, newpass, nt_errstr(r.out.result));
2505 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2506 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2507 nt_errstr(r.out.result));
2508 ret = false;
2511 E_md4hash(oldpass, old_nt_hash);
2512 E_md4hash(newpass, new_nt_hash);
2514 E_deshash(oldpass, old_lm_hash);
2515 E_deshash(newpass, new_lm_hash);
2517 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2518 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2519 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2521 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2522 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2523 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2525 r.in.server = &server;
2526 r.in.account = &account;
2527 r.in.nt_password = &nt_pass;
2528 r.in.nt_verifier = &nt_verifier;
2529 r.in.lm_change = 1;
2530 r.in.lm_password = &lm_pass;
2531 r.in.lm_verifier = &lm_verifier;
2532 r.in.password3 = NULL;
2533 r.out.dominfo = &dominfo;
2534 r.out.reject = &reject;
2536 unix_to_nt_time(&t, time(NULL));
2538 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2539 "ChangePasswordUser3 failed");
2540 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2541 __location__, __FUNCTION__,
2542 oldpass, newpass, nt_errstr(r.out.result));
2544 torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2545 "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2546 __location__,
2547 (dominfo == NULL)? "NULL" : "present",
2548 reject ? "true" : "false",
2549 handle_reject_reason ? "true" : "false",
2550 null_nttime(last_password_change) ? "null" : "not null",
2551 dominfo ? (long long)dominfo->min_password_age : (long long)0);
2553 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2554 && dominfo
2555 && reject
2556 && handle_reject_reason
2557 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2558 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2560 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2561 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2562 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2563 return false;
2567 /* We tested the order of precendence which is as follows:
2569 * pwd min_age
2570 * pwd length
2571 * pwd complexity
2572 * pwd history
2574 Guenther */
2576 if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
2577 (last_password_change - dominfo->min_password_age > t)) {
2579 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2580 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2581 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2582 return false;
2585 } else if ((dominfo->min_password_length > 0) &&
2586 (strlen(newpass) < dominfo->min_password_length)) {
2588 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2589 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2590 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2591 return false;
2594 } else if ((dominfo->password_history_length > 0) &&
2595 strequal(oldpass, newpass)) {
2597 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2598 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2599 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2600 return false;
2602 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2604 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2605 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2606 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2607 return false;
2612 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2613 /* retry with adjusted size */
2614 return test_ChangePasswordUser3(p, tctx, account_string,
2615 dominfo->min_password_length,
2616 password, NULL, 0, false);
2620 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2621 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2622 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2623 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2624 return false;
2626 /* Perhaps the server has a 'min password age' set? */
2628 } else {
2629 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2631 *password = talloc_strdup(tctx, newpass);
2634 return ret;
2637 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2638 const char *account_string,
2639 struct policy_handle *handle,
2640 char **password)
2642 NTSTATUS status;
2643 struct samr_ChangePasswordUser3 r;
2644 struct samr_SetUserInfo s;
2645 union samr_UserInfo u;
2646 DATA_BLOB session_key;
2647 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2648 uint8_t confounder[16];
2649 MD5_CTX ctx;
2651 bool ret = true;
2652 struct lsa_String server, account;
2653 struct samr_CryptPassword nt_pass;
2654 struct samr_Password nt_verifier;
2655 DATA_BLOB new_random_pass;
2656 char *newpass;
2657 char *oldpass;
2658 struct dcerpc_binding_handle *b = p->binding_handle;
2659 uint8_t old_nt_hash[16], new_nt_hash[16];
2660 NTTIME t;
2661 struct samr_DomInfo1 *dominfo = NULL;
2662 struct userPwdChangeFailureInformation *reject = NULL;
2664 new_random_pass = samr_very_rand_pass(tctx, 128);
2666 torture_assert(tctx, *password != NULL,
2667 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2669 oldpass = *password;
2670 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2671 init_lsa_String(&account, account_string);
2673 s.in.user_handle = handle;
2674 s.in.info = &u;
2675 s.in.level = 25;
2677 ZERO_STRUCT(u);
2679 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2681 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2683 status = dcerpc_fetch_session_key(p, &session_key);
2684 if (!NT_STATUS_IS_OK(status)) {
2685 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
2686 s.in.level, nt_errstr(status));
2687 return false;
2690 generate_random_buffer((uint8_t *)confounder, 16);
2692 MD5Init(&ctx);
2693 MD5Update(&ctx, confounder, 16);
2694 MD5Update(&ctx, session_key.data, session_key.length);
2695 MD5Final(confounded_session_key.data, &ctx);
2697 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2698 memcpy(&u.info25.password.data[516], confounder, 16);
2700 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2702 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2703 "SetUserInfo failed");
2704 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2705 __location__, __FUNCTION__,
2706 oldpass, "RANDOM", nt_errstr(s.out.result));
2707 if (!NT_STATUS_IS_OK(s.out.result)) {
2708 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
2709 s.in.level, nt_errstr(s.out.result));
2710 ret = false;
2713 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2715 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2717 new_random_pass = samr_very_rand_pass(tctx, 128);
2719 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2721 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2722 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2723 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2725 r.in.server = &server;
2726 r.in.account = &account;
2727 r.in.nt_password = &nt_pass;
2728 r.in.nt_verifier = &nt_verifier;
2729 r.in.lm_change = 0;
2730 r.in.lm_password = NULL;
2731 r.in.lm_verifier = NULL;
2732 r.in.password3 = NULL;
2733 r.out.dominfo = &dominfo;
2734 r.out.reject = &reject;
2736 unix_to_nt_time(&t, time(NULL));
2738 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2739 "ChangePasswordUser3 failed");
2740 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2741 __location__, __FUNCTION__,
2742 oldpass, "RANDOM", nt_errstr(r.out.result));
2744 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2745 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2746 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2747 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2748 return false;
2750 /* Perhaps the server has a 'min password age' set? */
2752 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2753 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2754 ret = false;
2757 newpass = samr_rand_pass(tctx, 128);
2759 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2761 E_md4hash(newpass, new_nt_hash);
2763 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2764 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2765 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2767 r.in.server = &server;
2768 r.in.account = &account;
2769 r.in.nt_password = &nt_pass;
2770 r.in.nt_verifier = &nt_verifier;
2771 r.in.lm_change = 0;
2772 r.in.lm_password = NULL;
2773 r.in.lm_verifier = NULL;
2774 r.in.password3 = NULL;
2775 r.out.dominfo = &dominfo;
2776 r.out.reject = &reject;
2778 unix_to_nt_time(&t, time(NULL));
2780 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2781 "ChangePasswordUser3 failed");
2782 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2783 __location__, __FUNCTION__,
2784 oldpass, newpass, nt_errstr(r.out.result));
2786 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2787 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2788 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2789 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2790 return false;
2792 /* Perhaps the server has a 'min password age' set? */
2794 } else {
2795 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2796 *password = talloc_strdup(tctx, newpass);
2799 return ret;
2803 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2804 struct torture_context *tctx,
2805 struct policy_handle *alias_handle)
2807 struct samr_GetMembersInAlias r;
2808 struct lsa_SidArray sids;
2810 torture_comment(tctx, "Testing GetMembersInAlias\n");
2812 r.in.alias_handle = alias_handle;
2813 r.out.sids = &sids;
2815 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2816 "GetMembersInAlias failed");
2817 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2819 return true;
2822 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2823 struct torture_context *tctx,
2824 struct policy_handle *alias_handle,
2825 const struct dom_sid *domain_sid)
2827 struct samr_AddAliasMember r;
2828 struct samr_DeleteAliasMember d;
2829 struct dom_sid *sid;
2831 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2833 torture_comment(tctx, "Testing AddAliasMember\n");
2834 r.in.alias_handle = alias_handle;
2835 r.in.sid = sid;
2837 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2838 "AddAliasMember failed");
2839 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2841 d.in.alias_handle = alias_handle;
2842 d.in.sid = sid;
2844 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2845 "DeleteAliasMember failed");
2846 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2848 return true;
2851 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2852 struct torture_context *tctx,
2853 struct policy_handle *alias_handle)
2855 struct samr_AddMultipleMembersToAlias a;
2856 struct samr_RemoveMultipleMembersFromAlias r;
2857 struct lsa_SidArray sids;
2859 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2860 a.in.alias_handle = alias_handle;
2861 a.in.sids = &sids;
2863 sids.num_sids = 3;
2864 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2866 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2867 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2868 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2870 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2871 "AddMultipleMembersToAlias failed");
2872 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2875 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2876 r.in.alias_handle = alias_handle;
2877 r.in.sids = &sids;
2879 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2880 "RemoveMultipleMembersFromAlias failed");
2881 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2883 /* strange! removing twice doesn't give any error */
2884 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2885 "RemoveMultipleMembersFromAlias failed");
2886 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2888 /* but removing an alias that isn't there does */
2889 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2891 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2892 "RemoveMultipleMembersFromAlias failed");
2893 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2895 return true;
2898 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2899 struct torture_context *tctx,
2900 struct policy_handle *domain_handle)
2902 struct samr_GetAliasMembership r;
2903 struct lsa_SidArray sids;
2904 struct samr_Ids rids;
2906 torture_comment(tctx, "Testing GetAliasMembership\n");
2908 r.in.domain_handle = domain_handle;
2909 r.in.sids = &sids;
2910 r.out.rids = &rids;
2912 sids.num_sids = 0;
2913 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2915 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2916 "GetAliasMembership failed");
2917 torture_assert_ntstatus_ok(tctx, r.out.result,
2918 "samr_GetAliasMembership failed");
2920 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2921 "protocol misbehaviour");
2923 sids.num_sids = 1;
2924 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2925 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2927 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2928 "samr_GetAliasMembership failed");
2929 torture_assert_ntstatus_ok(tctx, r.out.result,
2930 "samr_GetAliasMembership failed");
2932 #if 0
2933 /* only true for w2k8 it seems
2934 * win7, xp, w2k3 will return a 0 length array pointer */
2936 if (rids.ids && (rids.count == 0)) {
2937 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2939 #endif
2940 if (!rids.ids && rids.count) {
2941 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2944 return true;
2947 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2948 struct torture_context *tctx,
2949 struct policy_handle *user_handle)
2951 struct samr_TestPrivateFunctionsUser r;
2953 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2955 r.in.user_handle = user_handle;
2957 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2958 "TestPrivateFunctionsUser failed");
2959 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2961 return true;
2964 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2965 struct torture_context *tctx,
2966 struct policy_handle *handle,
2967 bool use_info2,
2968 NTTIME *pwdlastset)
2970 NTSTATUS status;
2971 uint16_t levels[] = { /* 3, */ 5, 21 };
2972 int i;
2973 NTTIME pwdlastset3 = 0;
2974 NTTIME pwdlastset5 = 0;
2975 NTTIME pwdlastset21 = 0;
2977 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2978 use_info2 ? "2":"");
2980 for (i=0; i<ARRAY_SIZE(levels); i++) {
2982 struct samr_QueryUserInfo r;
2983 struct samr_QueryUserInfo2 r2;
2984 union samr_UserInfo *info;
2986 if (use_info2) {
2987 r2.in.user_handle = handle;
2988 r2.in.level = levels[i];
2989 r2.out.info = &info;
2990 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2991 "QueryUserInfo2 failed");
2992 status = r2.out.result;
2994 } else {
2995 r.in.user_handle = handle;
2996 r.in.level = levels[i];
2997 r.out.info = &info;
2998 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2999 "QueryUserInfo failed");
3000 status = r.out.result;
3003 if (!NT_STATUS_IS_OK(status) &&
3004 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
3005 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo%s level %u failed - %s\n",
3006 use_info2 ? "2":"", levels[i], nt_errstr(status));
3007 return false;
3010 switch (levels[i]) {
3011 case 3:
3012 pwdlastset3 = info->info3.last_password_change;
3013 break;
3014 case 5:
3015 pwdlastset5 = info->info5.last_password_change;
3016 break;
3017 case 21:
3018 pwdlastset21 = info->info21.last_password_change;
3019 break;
3020 default:
3021 return false;
3024 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
3025 "pwdlastset mixup"); */
3026 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
3027 "pwdlastset mixup");
3029 *pwdlastset = pwdlastset21;
3031 torture_comment(tctx, "(pwdlastset: %llu)\n",
3032 (unsigned long long) *pwdlastset);
3034 return true;
3037 static bool test_SamLogon(struct torture_context *tctx,
3038 struct dcerpc_pipe *p,
3039 struct cli_credentials *machine_credentials,
3040 struct cli_credentials *test_credentials,
3041 NTSTATUS expected_result,
3042 bool interactive)
3044 NTSTATUS status;
3045 struct netr_LogonSamLogonEx r;
3046 union netr_LogonLevel logon;
3047 union netr_Validation validation;
3048 uint8_t authoritative;
3049 struct netr_IdentityInfo identity;
3050 struct netr_NetworkInfo ninfo;
3051 struct netr_PasswordInfo pinfo;
3052 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
3053 int flags = CLI_CRED_NTLM_AUTH;
3054 uint32_t samlogon_flags = 0;
3055 struct netlogon_creds_CredentialState *creds;
3056 struct netr_Authenticator a;
3057 struct dcerpc_binding_handle *b = p->binding_handle;
3059 torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), "");
3061 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
3062 flags |= CLI_CRED_LANMAN_AUTH;
3065 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
3066 flags |= CLI_CRED_NTLMv2_AUTH;
3069 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
3070 &identity.account_name.string,
3071 &identity.domain_name.string);
3073 identity.parameter_control =
3074 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
3075 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
3076 identity.logon_id_low = 0;
3077 identity.logon_id_high = 0;
3078 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
3080 if (interactive) {
3081 netlogon_creds_client_authenticator(creds, &a);
3083 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
3084 ZERO_STRUCT(pinfo.lmpassword.hash);
3086 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
3088 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3089 netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
3090 netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
3091 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
3092 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
3093 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
3094 } else {
3095 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
3096 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
3099 pinfo.identity_info = identity;
3100 logon.password = &pinfo;
3102 r.in.logon_level = NetlogonInteractiveInformation;
3103 } else {
3104 generate_random_buffer(ninfo.challenge,
3105 sizeof(ninfo.challenge));
3106 chal = data_blob_const(ninfo.challenge,
3107 sizeof(ninfo.challenge));
3109 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3110 cli_credentials_get_domain(test_credentials));
3112 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3113 &flags,
3114 chal,
3115 names_blob,
3116 &lm_resp, &nt_resp,
3117 NULL, NULL);
3118 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3120 ninfo.lm.data = lm_resp.data;
3121 ninfo.lm.length = lm_resp.length;
3123 ninfo.nt.data = nt_resp.data;
3124 ninfo.nt.length = nt_resp.length;
3126 ninfo.identity_info = identity;
3127 logon.network = &ninfo;
3129 r.in.logon_level = NetlogonNetworkInformation;
3132 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3133 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3134 r.in.logon = &logon;
3135 r.in.flags = &samlogon_flags;
3136 r.out.flags = &samlogon_flags;
3137 r.out.validation = &validation;
3138 r.out.authoritative = &authoritative;
3140 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3142 r.in.validation_level = 6;
3144 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3145 "netr_LogonSamLogonEx failed");
3146 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3147 r.in.validation_level = 3;
3148 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3149 "netr_LogonSamLogonEx failed");
3151 if (!NT_STATUS_IS_OK(r.out.result)) {
3152 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3153 return true;
3154 } else {
3155 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3158 return true;
3161 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3162 struct dcerpc_pipe *p,
3163 struct cli_credentials *machine_creds,
3164 const char *acct_name,
3165 const char *password,
3166 NTSTATUS expected_samlogon_result,
3167 bool interactive)
3169 bool ret = true;
3170 struct cli_credentials *test_credentials;
3172 test_credentials = cli_credentials_init(tctx);
3174 cli_credentials_set_workstation(test_credentials,
3175 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3176 cli_credentials_set_domain(test_credentials,
3177 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3178 cli_credentials_set_username(test_credentials,
3179 acct_name, CRED_SPECIFIED);
3180 cli_credentials_set_password(test_credentials,
3181 password, CRED_SPECIFIED);
3183 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3184 interactive ? "interactive" : "network", acct_name, password);
3186 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
3187 expected_samlogon_result, interactive)) {
3188 torture_result(tctx, TORTURE_FAIL, "new password did not work\n");
3189 ret = false;
3192 return ret;
3195 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3196 struct dcerpc_pipe *np,
3197 struct torture_context *tctx,
3198 struct policy_handle *handle,
3199 uint16_t level,
3200 uint32_t fields_present,
3201 uint8_t password_expired,
3202 bool *matched_expected_error,
3203 bool use_setinfo2,
3204 const char *acct_name,
3205 char **password,
3206 struct cli_credentials *machine_creds,
3207 bool use_queryinfo2,
3208 NTTIME *pwdlastset,
3209 NTSTATUS expected_samlogon_result)
3211 const char *fields = NULL;
3212 bool ret = true;
3213 struct dcerpc_binding_handle *b = p->binding_handle;
3215 switch (level) {
3216 case 21:
3217 case 23:
3218 case 25:
3219 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3220 fields_present);
3221 break;
3222 default:
3223 break;
3226 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3227 "(password_expired: %d) %s\n",
3228 use_setinfo2 ? "2":"", level, password_expired,
3229 fields ? fields : "");
3231 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3232 fields_present,
3233 password,
3234 password_expired,
3235 use_setinfo2,
3236 matched_expected_error)) {
3237 ret = false;
3240 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3241 use_queryinfo2,
3242 pwdlastset)) {
3243 ret = false;
3246 if (*matched_expected_error == true) {
3247 return ret;
3250 if (!test_SamLogon_with_creds(tctx, np,
3251 machine_creds,
3252 acct_name,
3253 *password,
3254 expected_samlogon_result,
3255 false)) {
3256 ret = false;
3259 return ret;
3262 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3263 struct cli_credentials *credentials,
3264 struct dcerpc_pipe **p)
3266 struct dcerpc_binding *b;
3267 NTSTATUS status;
3269 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3270 "failed to get rpc binding");
3272 /* We have to use schannel, otherwise the SamLogonEx fails
3273 * with INTERNAL_ERROR */
3275 status = dcerpc_binding_set_flags(b,
3276 DCERPC_SCHANNEL | DCERPC_SIGN |
3277 DCERPC_SCHANNEL_AUTO,
3278 DCERPC_AUTH_OPTIONS);
3279 torture_assert_ntstatus_ok(tctx, status, "set flags");
3281 torture_assert_ntstatus_ok(tctx,
3282 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3283 credentials, tctx->ev, tctx->lp_ctx),
3284 "failed to bind to netlogon");
3286 return true;
3289 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3290 struct torture_context *tctx,
3291 uint32_t acct_flags,
3292 const char *acct_name,
3293 struct policy_handle *handle,
3294 char **password,
3295 struct cli_credentials *machine_credentials)
3297 int s = 0, q = 0, f = 0, l = 0, z = 0;
3298 bool ret = true;
3299 int delay = 50000;
3300 bool set_levels[] = { false, true };
3301 bool query_levels[] = { false, true };
3302 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3303 uint32_t nonzeros[] = { 1, 24 };
3304 uint32_t fields_present[] = {
3306 SAMR_FIELD_EXPIRED_FLAG,
3307 SAMR_FIELD_LAST_PWD_CHANGE,
3308 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3309 SAMR_FIELD_COMMENT,
3310 SAMR_FIELD_NT_PASSWORD_PRESENT,
3311 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3312 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3313 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3314 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3315 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3316 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3318 struct dcerpc_pipe *np = NULL;
3320 if (torture_setting_bool(tctx, "samba3", false) ||
3321 torture_setting_bool(tctx, "samba4", false)) {
3322 delay = 999999;
3323 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3324 delay);
3327 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3329 /* set to 1 to enable testing for all possible opcode
3330 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3331 combinations */
3332 #if 0
3333 #define TEST_ALL_LEVELS 1
3334 #define TEST_SET_LEVELS 1
3335 #define TEST_QUERY_LEVELS 1
3336 #endif
3337 #ifdef TEST_ALL_LEVELS
3338 for (l=0; l<ARRAY_SIZE(levels); l++) {
3339 #else
3340 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3341 #endif
3342 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3343 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3344 #ifdef TEST_SET_LEVELS
3345 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3346 #endif
3347 #ifdef TEST_QUERY_LEVELS
3348 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3349 #endif
3350 NTTIME pwdlastset_old = 0;
3351 NTTIME pwdlastset_new = 0;
3352 bool matched_expected_error = false;
3353 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3355 torture_comment(tctx, "------------------------------\n"
3356 "Testing pwdLastSet attribute for flags: 0x%08x "
3357 "(s: %d (l: %d), q: %d)\n",
3358 acct_flags, s, levels[l], q);
3360 switch (levels[l]) {
3361 case 21:
3362 case 23:
3363 case 25:
3364 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3365 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3366 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3368 break;
3372 /* set #1 */
3374 /* set a password and force password change (pwdlastset 0) by
3375 * setting the password expired flag to a non-0 value */
3377 if (!test_SetPassword_level(p, np, tctx, handle,
3378 levels[l],
3379 fields_present[f],
3380 nonzeros[z],
3381 &matched_expected_error,
3382 set_levels[s],
3383 acct_name,
3384 password,
3385 machine_credentials,
3386 query_levels[q],
3387 &pwdlastset_new,
3388 expected_samlogon_result)) {
3389 ret = false;
3392 if (matched_expected_error == true) {
3393 /* skipping on expected failure */
3394 continue;
3397 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3398 * set without the SAMR_FIELD_EXPIRED_FLAG */
3400 switch (levels[l]) {
3401 case 21:
3402 case 23:
3403 case 25:
3404 if ((pwdlastset_new != 0) &&
3405 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3406 torture_comment(tctx, "not considering a non-0 "
3407 "pwdLastSet as a an error as the "
3408 "SAMR_FIELD_EXPIRED_FLAG has not "
3409 "been set\n");
3410 break;
3412 break;
3413 default:
3414 if (pwdlastset_new != 0) {
3415 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3416 "expected pwdLastSet 0 but got %llu\n",
3417 (unsigned long long) pwdlastset_old);
3418 ret = false;
3420 break;
3423 switch (levels[l]) {
3424 case 21:
3425 case 23:
3426 case 25:
3427 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3428 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3429 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3430 (pwdlastset_old >= pwdlastset_new)) {
3431 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3432 ret = false;
3434 break;
3437 pwdlastset_old = pwdlastset_new;
3439 usleep(delay);
3441 /* set #2 */
3443 /* set a password, pwdlastset needs to get updated (increased
3444 * value), password_expired value used here is 0 */
3446 if (!test_SetPassword_level(p, np, tctx, handle,
3447 levels[l],
3448 fields_present[f],
3450 &matched_expected_error,
3451 set_levels[s],
3452 acct_name,
3453 password,
3454 machine_credentials,
3455 query_levels[q],
3456 &pwdlastset_new,
3457 expected_samlogon_result)) {
3458 ret = false;
3461 /* when a password has been changed, pwdlastset must not be 0 afterwards
3462 * and must be larger then the old value */
3464 switch (levels[l]) {
3465 case 21:
3466 case 23:
3467 case 25:
3468 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3469 * password has been changed, old and new pwdlastset
3470 * need to be the same value */
3472 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3473 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3474 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3476 torture_assert_int_equal(tctx, pwdlastset_old,
3477 pwdlastset_new, "pwdlastset must be equal");
3478 break;
3480 break;
3481 default:
3482 if (pwdlastset_old >= pwdlastset_new) {
3483 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3484 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3485 (unsigned long long) pwdlastset_old,
3486 (unsigned long long) pwdlastset_new);
3487 ret = false;
3489 if (pwdlastset_new == 0) {
3490 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3491 "expected non-0 pwdlastset, got: %llu\n",
3492 (unsigned long long) pwdlastset_new);
3493 ret = false;
3495 break;
3498 switch (levels[l]) {
3499 case 21:
3500 case 23:
3501 case 25:
3502 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3503 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3504 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3505 (pwdlastset_old >= pwdlastset_new)) {
3506 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3507 ret = false;
3509 break;
3512 pwdlastset_old = pwdlastset_new;
3514 usleep(delay);
3516 /* set #2b */
3518 /* set a password, pwdlastset needs to get updated (increased
3519 * value), password_expired value used here is 0 */
3521 if (!test_SetPassword_level(p, np, tctx, handle,
3522 levels[l],
3523 fields_present[f],
3525 &matched_expected_error,
3526 set_levels[s],
3527 acct_name,
3528 password,
3529 machine_credentials,
3530 query_levels[q],
3531 &pwdlastset_new,
3532 expected_samlogon_result)) {
3533 ret = false;
3536 /* when a password has been changed, pwdlastset must not be 0 afterwards
3537 * and must be larger then the old value */
3539 switch (levels[l]) {
3540 case 21:
3541 case 23:
3542 case 25:
3544 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3545 * password has been changed, old and new pwdlastset
3546 * need to be the same value */
3548 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3549 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3550 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3552 torture_assert_int_equal(tctx, pwdlastset_old,
3553 pwdlastset_new, "pwdlastset must be equal");
3554 break;
3556 break;
3557 default:
3558 if (pwdlastset_old >= pwdlastset_new) {
3559 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3560 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3561 (unsigned long long) pwdlastset_old,
3562 (unsigned long long) pwdlastset_new);
3563 ret = false;
3565 if (pwdlastset_new == 0) {
3566 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3567 "expected non-0 pwdlastset, got: %llu\n",
3568 (unsigned long long) pwdlastset_new);
3569 ret = false;
3571 break;
3574 switch (levels[l]) {
3575 case 21:
3576 case 23:
3577 case 25:
3578 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3579 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3580 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3581 (pwdlastset_old >= pwdlastset_new)) {
3582 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3583 ret = false;
3585 break;
3588 pwdlastset_old = pwdlastset_new;
3590 usleep(delay);
3592 /* set #3 */
3594 /* set a password and force password change (pwdlastset 0) by
3595 * setting the password expired flag to a non-0 value */
3597 if (!test_SetPassword_level(p, np, tctx, handle,
3598 levels[l],
3599 fields_present[f],
3600 nonzeros[z],
3601 &matched_expected_error,
3602 set_levels[s],
3603 acct_name,
3604 password,
3605 machine_credentials,
3606 query_levels[q],
3607 &pwdlastset_new,
3608 expected_samlogon_result)) {
3609 ret = false;
3612 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3613 * set without the SAMR_FIELD_EXPIRED_FLAG */
3615 switch (levels[l]) {
3616 case 21:
3617 case 23:
3618 case 25:
3619 if ((pwdlastset_new != 0) &&
3620 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3621 torture_comment(tctx, "not considering a non-0 "
3622 "pwdLastSet as a an error as the "
3623 "SAMR_FIELD_EXPIRED_FLAG has not "
3624 "been set\n");
3625 break;
3628 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3629 * password has been changed, old and new pwdlastset
3630 * need to be the same value */
3632 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3633 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3634 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3636 torture_assert_int_equal(tctx, pwdlastset_old,
3637 pwdlastset_new, "pwdlastset must be equal");
3638 break;
3640 break;
3641 default:
3642 if (pwdlastset_new != 0) {
3643 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3644 "expected pwdLastSet 0, got %llu\n",
3645 (unsigned long long) pwdlastset_old);
3646 ret = false;
3648 break;
3651 switch (levels[l]) {
3652 case 21:
3653 case 23:
3654 case 25:
3655 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3656 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3657 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3658 (pwdlastset_old >= pwdlastset_new)) {
3659 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3660 ret = false;
3662 break;
3665 /* if the level we are testing does not have a fields_present
3666 * field, skip all fields present tests by setting f to to
3667 * arraysize */
3668 switch (levels[l]) {
3669 case 18:
3670 case 24:
3671 case 26:
3672 f = ARRAY_SIZE(fields_present);
3673 break;
3676 #ifdef TEST_QUERY_LEVELS
3678 #endif
3679 #ifdef TEST_SET_LEVELS
3681 #endif
3682 } /* fields present */
3683 } /* nonzeros */
3684 } /* levels */
3686 #undef TEST_SET_LEVELS
3687 #undef TEST_QUERY_LEVELS
3689 talloc_free(np);
3691 return ret;
3694 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3695 struct torture_context *tctx,
3696 struct policy_handle *handle,
3697 uint32_t *badpwdcount)
3699 union samr_UserInfo *info;
3700 struct samr_QueryUserInfo r;
3702 r.in.user_handle = handle;
3703 r.in.level = 3;
3704 r.out.info = &info;
3706 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3708 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3709 "failed to query userinfo");
3710 torture_assert_ntstatus_ok(tctx, r.out.result,
3711 "failed to query userinfo");
3713 *badpwdcount = info->info3.bad_password_count;
3715 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3717 return true;
3720 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3721 struct torture_context *tctx,
3722 struct policy_handle *user_handle,
3723 uint32_t acct_flags)
3725 struct samr_SetUserInfo r;
3726 union samr_UserInfo user_info;
3728 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3730 user_info.info16.acct_flags = acct_flags;
3732 r.in.user_handle = user_handle;
3733 r.in.level = 16;
3734 r.in.info = &user_info;
3736 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3737 "failed to set account flags");
3738 torture_assert_ntstatus_ok(tctx, r.out.result,
3739 "failed to set account flags");
3741 return true;
3744 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3745 struct torture_context *tctx,
3746 struct policy_handle *user_handle,
3747 uint32_t acct_flags,
3748 char **password)
3750 struct dcerpc_binding_handle *b = p->binding_handle;
3752 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3753 "failed to set password");
3755 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3757 torture_assert(tctx,
3758 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3759 acct_flags & ~ACB_DISABLED),
3760 "failed to enable user");
3762 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3763 "failed to set password");
3765 return true;
3768 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3769 struct torture_context *tctx,
3770 struct policy_handle *domain_handle,
3771 enum samr_DomainInfoClass level,
3772 union samr_DomainInfo *info)
3774 struct samr_SetDomainInfo r;
3776 r.in.domain_handle = domain_handle;
3777 r.in.level = level;
3778 r.in.info = info;
3780 torture_assert_ntstatus_ok(tctx,
3781 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3782 "failed to set domain info");
3783 torture_assert_ntstatus_ok(tctx, r.out.result,
3784 "failed to set domain info");
3786 return true;
3789 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3790 struct torture_context *tctx,
3791 struct policy_handle *domain_handle,
3792 enum samr_DomainInfoClass level,
3793 union samr_DomainInfo *info,
3794 NTSTATUS expected)
3796 struct samr_SetDomainInfo r;
3798 r.in.domain_handle = domain_handle;
3799 r.in.level = level;
3800 r.in.info = info;
3802 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3803 "SetDomainInfo failed");
3804 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3806 return true;
3809 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3810 struct torture_context *tctx,
3811 struct policy_handle *domain_handle,
3812 enum samr_DomainInfoClass level,
3813 union samr_DomainInfo **q_info)
3815 struct samr_QueryDomainInfo2 r;
3817 r.in.domain_handle = domain_handle;
3818 r.in.level = level;
3819 r.out.info = q_info;
3821 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3822 "failed to query domain info");
3823 torture_assert_ntstatus_ok(tctx, r.out.result,
3824 "failed to query domain info");
3826 return true;
3829 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3830 struct dcerpc_pipe *np,
3831 struct torture_context *tctx,
3832 uint32_t acct_flags,
3833 const char *acct_name,
3834 struct policy_handle *domain_handle,
3835 struct policy_handle *user_handle,
3836 char **password,
3837 struct cli_credentials *machine_credentials,
3838 const char *comment,
3839 bool disable,
3840 bool interactive,
3841 NTSTATUS expected_success_status,
3842 struct samr_DomInfo1 *info1,
3843 struct samr_DomInfo12 *info12)
3845 union samr_DomainInfo info;
3846 char **passwords;
3847 int i;
3848 uint32_t badpwdcount, tmp;
3849 uint32_t password_history_length = 12;
3850 uint32_t lockout_threshold = 15;
3851 uint32_t lockout_seconds = 5;
3852 uint64_t delta_time_factor = 10 * 1000 * 1000;
3853 struct dcerpc_binding_handle *b = p->binding_handle;
3855 if (torture_setting_bool(tctx, "samba3", false)) {
3856 lockout_seconds = 60;
3859 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3861 torture_assert(tctx, password_history_length < lockout_threshold,
3862 "password history length needs to be smaller than account lockout threshold for this test");
3865 /* set policies */
3867 info.info1 = *info1;
3868 info.info1.password_history_length = password_history_length;
3869 info.info1.min_password_age = 0;
3871 torture_assert(tctx,
3872 test_SetDomainInfo(b, tctx, domain_handle,
3873 DomainPasswordInformation, &info),
3874 "failed to set password history length and min passwd age");
3876 info.info12 = *info12;
3877 info.info12.lockout_threshold = lockout_threshold;
3879 /* set lockout duration of 5 seconds */
3880 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3881 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
3883 torture_assert(tctx,
3884 test_SetDomainInfo(b, tctx, domain_handle,
3885 DomainLockoutInformation, &info),
3886 "failed to set lockout threshold");
3888 /* reset bad pwd count */
3890 torture_assert(tctx,
3891 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3894 /* enable or disable account */
3895 if (disable) {
3896 torture_assert(tctx,
3897 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3898 acct_flags | ACB_DISABLED),
3899 "failed to disable user");
3900 } else {
3901 torture_assert(tctx,
3902 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3903 acct_flags & ~ACB_DISABLED),
3904 "failed to enable user");
3908 /* setup password history */
3910 passwords = talloc_array(tctx, char *, password_history_length);
3912 for (i=0; i < password_history_length; i++) {
3914 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3915 "failed to set password");
3916 passwords[i] = talloc_strdup(tctx, *password);
3918 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3919 acct_name, passwords[i],
3920 expected_success_status, interactive)) {
3921 torture_fail(tctx, "failed to auth with latest password");
3924 torture_assert(tctx,
3925 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3927 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3931 /* test with wrong password */
3933 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3934 acct_name, "random_crap",
3935 NT_STATUS_WRONG_PASSWORD, interactive)) {
3936 torture_fail(tctx, "succeeded to authenticate with wrong password");
3939 torture_assert(tctx,
3940 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3942 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3945 /* test with latest good password */
3947 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3948 passwords[password_history_length-1],
3949 expected_success_status, interactive)) {
3950 torture_fail(tctx, "succeeded to authenticate with wrong password");
3953 torture_assert(tctx,
3954 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3956 if (disable) {
3957 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3958 } else {
3959 /* only enabled accounts get the bad pwd count reset upon
3960 * successful logon */
3961 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3964 tmp = badpwdcount;
3967 /* test password history */
3969 for (i=0; i < password_history_length; i++) {
3971 torture_comment(tctx, "Testing bad password count behavior with "
3972 "password #%d of #%d\n", i, password_history_length);
3974 /* - network samlogon will succeed auth and not
3975 * increase badpwdcount for 2 last entries
3976 * - interactive samlogon only for the last one */
3978 if (i == password_history_length - 1 ||
3979 (i == password_history_length - 2 && !interactive)) {
3981 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3982 acct_name, passwords[i],
3983 expected_success_status, interactive)) {
3984 torture_fail(tctx, talloc_asprintf(tctx, "did not successfully to obtain %s for %s login with old password (#%d of #%d in history)",
3985 nt_errstr(expected_success_status),
3986 interactive ? "interactive" : "network", i, password_history_length));
3989 torture_assert(tctx,
3990 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3992 if (disable) {
3993 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3994 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3995 } else {
3996 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3997 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4000 tmp = badpwdcount;
4002 continue;
4005 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4006 acct_name, passwords[i],
4007 NT_STATUS_WRONG_PASSWORD, interactive)) {
4008 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
4011 torture_assert(tctx,
4012 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4014 /* - network samlogon will fail auth but not increase
4015 * badpwdcount for 3rd last entry
4016 * - interactive samlogon for 3rd and 2nd last entry */
4018 if (i == password_history_length - 3 ||
4019 (i == password_history_length - 2 && interactive)) {
4020 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
4021 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
4022 } else {
4023 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
4024 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
4027 tmp = badpwdcount;
4030 return true;
4033 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
4034 struct torture_context *tctx,
4035 uint32_t acct_flags,
4036 const char *acct_name,
4037 struct policy_handle *domain_handle,
4038 struct policy_handle *user_handle,
4039 char **password,
4040 struct cli_credentials *machine_credentials)
4042 union samr_DomainInfo *q_info, s_info;
4043 struct samr_DomInfo1 info1, _info1;
4044 struct samr_DomInfo12 info12, _info12;
4045 bool ret = true;
4046 struct dcerpc_binding_handle *b = p->binding_handle;
4047 struct dcerpc_pipe *np;
4048 int i;
4050 struct {
4051 const char *comment;
4052 bool disabled;
4053 bool interactive;
4054 NTSTATUS expected_success_status;
4055 } creds[] = {
4057 .comment = "network logon (disabled account)",
4058 .disabled = true,
4059 .interactive = false,
4060 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4063 .comment = "network logon (enabled account)",
4064 .disabled = false,
4065 .interactive = false,
4066 .expected_success_status= NT_STATUS_OK
4069 .comment = "interactive logon (disabled account)",
4070 .disabled = true,
4071 .interactive = true,
4072 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4075 .comment = "interactive logon (enabled account)",
4076 .disabled = false,
4077 .interactive = true,
4078 .expected_success_status= NT_STATUS_OK
4082 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4084 /* backup old policies */
4086 torture_assert(tctx,
4087 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4088 DomainPasswordInformation, &q_info),
4089 "failed to query domain info level 1");
4091 info1 = q_info->info1;
4092 _info1 = info1;
4094 torture_assert(tctx,
4095 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4096 DomainLockoutInformation, &q_info),
4097 "failed to query domain info level 12");
4099 info12 = q_info->info12;
4100 _info12 = info12;
4102 /* run tests */
4104 for (i=0; i < ARRAY_SIZE(creds); i++) {
4106 /* skip trust tests for now */
4107 if (acct_flags & ACB_WSTRUST ||
4108 acct_flags & ACB_SVRTRUST ||
4109 acct_flags & ACB_DOMTRUST) {
4110 continue;
4113 if (!test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4114 domain_handle, user_handle, password,
4115 machine_credentials,
4116 creds[i].comment,
4117 creds[i].disabled,
4118 creds[i].interactive,
4119 creds[i].expected_success_status,
4120 &_info1, &_info12)) {
4121 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4122 ret = false;
4123 } else {
4124 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4128 /* restore policies */
4130 s_info.info1 = info1;
4132 torture_assert(tctx,
4133 test_SetDomainInfo(b, tctx, domain_handle,
4134 DomainPasswordInformation, &s_info),
4135 "failed to set password information");
4137 s_info.info12 = info12;
4139 torture_assert(tctx,
4140 test_SetDomainInfo(b, tctx, domain_handle,
4141 DomainLockoutInformation, &s_info),
4142 "failed to set lockout information");
4144 return ret;
4147 static bool test_QueryUserInfo_lockout(struct dcerpc_binding_handle *b,
4148 struct torture_context *tctx,
4149 struct policy_handle *domain_handle,
4150 const char *acct_name,
4151 uint16_t raw_bad_password_count,
4152 uint16_t effective_bad_password_count,
4153 uint32_t effective_acb_lockout)
4155 struct policy_handle user_handle;
4156 union samr_UserInfo *i;
4157 struct samr_QueryUserInfo r;
4159 NTSTATUS status = test_OpenUser_byname(b, tctx, domain_handle, acct_name, &user_handle);
4160 if (!NT_STATUS_IS_OK(status)) {
4161 return false;
4164 r.in.user_handle = &user_handle;
4165 r.in.level = 3;
4166 r.out.info = &i;
4167 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4168 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4169 "failed to query userinfo");
4170 torture_assert_ntstatus_ok(tctx, r.out.result,
4171 "failed to query userinfo");
4172 torture_comment(tctx, " (acct_flags: 0x%08x) (raw_bad_pwd_count: %u)\n",
4173 i->info3.acct_flags, i->info3.bad_password_count);
4174 torture_assert_int_equal(tctx, i->info3.bad_password_count,
4175 raw_bad_password_count,
4176 "raw badpwdcount");
4177 torture_assert_int_equal(tctx, i->info3.acct_flags & ACB_AUTOLOCK,
4178 effective_acb_lockout,
4179 "effective acb_lockout");
4180 TALLOC_FREE(i);
4182 r.in.user_handle = &user_handle;
4183 r.in.level = 5;
4184 r.out.info = &i;
4185 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4186 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4187 "failed to query userinfo");
4188 torture_assert_ntstatus_ok(tctx, r.out.result,
4189 "failed to query userinfo");
4190 torture_comment(tctx, " (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
4191 i->info5.acct_flags, i->info5.bad_password_count);
4192 torture_assert_int_equal(tctx, i->info5.bad_password_count,
4193 effective_bad_password_count,
4194 "effective badpwdcount");
4195 torture_assert_int_equal(tctx, i->info5.acct_flags & ACB_AUTOLOCK,
4196 effective_acb_lockout,
4197 "effective acb_lockout");
4198 TALLOC_FREE(i);
4200 r.in.user_handle = &user_handle;
4201 r.in.level = 16;
4202 r.out.info = &i;
4203 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4204 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4205 "failed to query userinfo");
4206 torture_assert_ntstatus_ok(tctx, r.out.result,
4207 "failed to query userinfo");
4208 torture_comment(tctx, " (acct_flags: 0x%08x)\n",
4209 i->info16.acct_flags);
4210 torture_assert_int_equal(tctx, i->info16.acct_flags & ACB_AUTOLOCK,
4211 effective_acb_lockout,
4212 "effective acb_lockout");
4213 TALLOC_FREE(i);
4215 r.in.user_handle = &user_handle;
4216 r.in.level = 21;
4217 r.out.info = &i;
4218 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4219 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4220 "failed to query userinfo");
4221 torture_assert_ntstatus_ok(tctx, r.out.result,
4222 "failed to query userinfo");
4223 torture_comment(tctx, " (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
4224 i->info21.acct_flags, i->info21.bad_password_count);
4225 torture_assert_int_equal(tctx, i->info21.bad_password_count,
4226 effective_bad_password_count,
4227 "effective badpwdcount");
4228 torture_assert_int_equal(tctx, i->info21.acct_flags & ACB_AUTOLOCK,
4229 effective_acb_lockout,
4230 "effective acb_lockout");
4231 TALLOC_FREE(i);
4233 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
4234 return false;
4237 return true;
4240 static bool test_Password_lockout(struct dcerpc_pipe *p,
4241 struct dcerpc_pipe *np,
4242 struct torture_context *tctx,
4243 uint32_t acct_flags,
4244 const char *acct_name,
4245 struct policy_handle *domain_handle,
4246 struct policy_handle *user_handle,
4247 char **password,
4248 struct cli_credentials *machine_credentials,
4249 const char *comment,
4250 bool disable,
4251 bool interactive,
4252 uint32_t password_history_length,
4253 NTSTATUS expected_success_status,
4254 struct samr_DomInfo1 *info1,
4255 struct samr_DomInfo12 *info12)
4257 union samr_DomainInfo info;
4258 uint64_t lockout_threshold = 1;
4259 uint32_t lockout_seconds = 5;
4260 uint64_t delta_time_factor = 10 * 1000 * 1000;
4261 struct dcerpc_binding_handle *b = p->binding_handle;
4263 if (torture_setting_bool(tctx, "samba3", false)) {
4264 lockout_seconds = 60;
4267 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4269 /* set policies */
4271 info.info1 = *info1;
4273 torture_comment(tctx, "setting password history length to %d.\n", password_history_length);
4274 info.info1.password_history_length = password_history_length;
4276 torture_comment(tctx, "setting min password again.\n");
4277 info.info1.min_password_age = 0;
4279 torture_assert(tctx,
4280 test_SetDomainInfo(b, tctx, domain_handle,
4281 DomainPasswordInformation, &info),
4282 "failed to set password history length");
4284 info.info12 = *info12;
4285 info.info12.lockout_threshold = lockout_threshold;
4287 /* set lockout duration < lockout window: should fail */
4288 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4289 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4291 torture_assert(tctx,
4292 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4293 DomainLockoutInformation, &info,
4294 NT_STATUS_INVALID_PARAMETER),
4295 "setting lockout duration < lockout window gave unexpected result");
4297 info.info12.lockout_duration = 0;
4298 info.info12.lockout_window = 0;
4300 torture_assert(tctx,
4301 test_SetDomainInfo(b, tctx, domain_handle,
4302 DomainLockoutInformation, &info),
4303 "failed to set lockout window and duration to 0");
4306 /* set lockout duration of 5 seconds */
4307 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4308 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4310 torture_assert(tctx,
4311 test_SetDomainInfo(b, tctx, domain_handle,
4312 DomainLockoutInformation, &info),
4313 "failed to set lockout window and duration to 5 seconds");
4315 /* reset bad pwd count */
4317 torture_assert(tctx,
4318 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4321 /* enable or disable account */
4323 if (disable) {
4324 torture_assert(tctx,
4325 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4326 acct_flags | ACB_DISABLED),
4327 "failed to disable user");
4328 } else {
4329 torture_assert(tctx,
4330 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4331 acct_flags & ~ACB_DISABLED),
4332 "failed to enable user");
4336 /* test logon with right password */
4338 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4339 acct_name, *password,
4340 expected_success_status, interactive)) {
4341 torture_fail(tctx, "failed to auth with latest password");
4344 torture_assert(tctx,
4345 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4346 0, 0, 0),
4347 "expected account to not be locked");
4349 /* test with wrong password ==> lockout */
4351 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4352 acct_name, "random_crap",
4353 NT_STATUS_WRONG_PASSWORD, interactive)) {
4354 torture_fail(tctx, "succeeded to authenticate with wrong password");
4358 * curiously, windows does _not_ return fresh values of
4359 * effective bad_password_count and ACB_AUTOLOCK.
4361 torture_assert(tctx,
4362 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4363 1, 1, ACB_AUTOLOCK),
4364 "expected account to not be locked");
4366 /* test with good password */
4368 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4369 *password,
4370 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4372 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4375 /* bad pwd count should not get updated */
4376 torture_assert(tctx,
4377 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4378 1, 1, ACB_AUTOLOCK),
4379 "expected account to be locked");
4381 torture_assert(tctx,
4382 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password,
4383 NT_STATUS_ACCOUNT_LOCKED_OUT),
4384 "got wrong status from ChangePasswordUser2");
4386 /* bad pwd count should not get updated */
4387 torture_assert(tctx,
4388 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4389 1, 1, ACB_AUTOLOCK),
4390 "expected account to be locked");
4392 torture_assert(tctx,
4393 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
4394 "got wrong status from ChangePasswordUser2");
4396 /* bad pwd count should not get updated */
4397 torture_assert(tctx,
4398 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4399 1, 1, ACB_AUTOLOCK),
4400 "expected account to be locked");
4402 /* with bad password */
4404 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4405 acct_name, "random_crap2",
4406 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4408 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4411 /* bad pwd count should not get updated */
4412 torture_assert(tctx,
4413 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4414 1, 1, ACB_AUTOLOCK),
4415 "expected account to be locked");
4417 /* let lockout duration expire ==> unlock */
4419 torture_comment(tctx, "let lockout duration expire...\n");
4420 sleep(lockout_seconds + 1);
4422 torture_assert(tctx,
4423 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4424 1, 0, 0),
4425 "expected account to not be locked");
4427 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4428 *password,
4429 expected_success_status, interactive))
4431 torture_fail(tctx, "failed to authenticate after lockout expired");
4434 if (NT_STATUS_IS_OK(expected_success_status)) {
4435 torture_assert(tctx,
4436 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4437 0, 0, 0),
4438 "expected account to not be locked");
4439 } else {
4440 torture_assert(tctx,
4441 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4442 1, 0, 0),
4443 "expected account to not be locked");
4446 torture_assert(tctx,
4447 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4448 "got wrong status from ChangePasswordUser2");
4450 torture_assert(tctx,
4451 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4452 1, 1, ACB_AUTOLOCK),
4453 "expected account to be locked");
4455 torture_assert(tctx,
4456 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
4457 "got wrong status from ChangePasswordUser2");
4459 torture_assert(tctx,
4460 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4461 1, 1, ACB_AUTOLOCK),
4462 "expected account to be locked");
4464 torture_assert(tctx,
4465 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
4466 "got wrong status from ChangePasswordUser2");
4468 torture_assert(tctx,
4469 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4470 1, 1, ACB_AUTOLOCK),
4471 "expected account to be locked");
4473 /* let lockout duration expire ==> unlock */
4475 torture_comment(tctx, "let lockout duration expire...\n");
4476 sleep(lockout_seconds + 1);
4478 torture_assert(tctx,
4479 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4480 1, 0, 0),
4481 "expected account to not be locked");
4483 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4484 *password,
4485 expected_success_status, interactive))
4487 torture_fail(tctx, "failed to authenticate after lockout expired");
4490 if (NT_STATUS_IS_OK(expected_success_status)) {
4491 torture_assert(tctx,
4492 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4493 0, 0, 0),
4494 "expected account to not be locked");
4495 } else {
4496 torture_assert(tctx,
4497 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4498 1, 0, 0),
4499 "expected account to not be locked");
4502 /* Testing ChangePasswordUser behaviour with 3 attempts */
4503 info.info12.lockout_threshold = 3;
4505 torture_assert(tctx,
4506 test_SetDomainInfo(b, tctx, domain_handle,
4507 DomainLockoutInformation, &info),
4508 "failed to set lockout threshold to 3");
4510 if (NT_STATUS_IS_OK(expected_success_status)) {
4511 torture_assert(tctx,
4512 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4513 0, 0, 0),
4514 "expected account to not be locked");
4515 } else {
4516 torture_assert(tctx,
4517 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4518 1, 0, 0),
4519 "expected account to not be locked");
4522 torture_assert(tctx,
4523 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4524 "got wrong status from ChangePasswordUser2");
4526 /* bad pwd count will get updated */
4527 torture_assert(tctx,
4528 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4529 1, 1, 0),
4530 "expected account to not be locked");
4532 torture_assert(tctx,
4533 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4534 "got wrong status from ChangePasswordUser2");
4536 /* bad pwd count will get updated */
4537 torture_assert(tctx,
4538 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4539 2, 2, 0),
4540 "expected account to not be locked");
4542 torture_assert(tctx,
4543 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4544 "got wrong status from ChangePasswordUser2");
4546 /* bad pwd count should get updated */
4547 torture_assert(tctx,
4548 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4549 3, 3, ACB_AUTOLOCK),
4550 "expected account to be locked");
4552 torture_assert(tctx,
4553 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
4554 "got wrong status from ChangePasswordUser2");
4556 /* bad pwd count should not get updated */
4557 torture_assert(tctx,
4558 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4559 3, 3, ACB_AUTOLOCK),
4560 "expected account to be locked");
4562 /* let lockout duration expire ==> unlock */
4564 torture_comment(tctx, "let lockout duration expire...\n");
4565 sleep(lockout_seconds + 1);
4567 torture_assert(tctx,
4568 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4569 3, 0, 0),
4570 "expected account to not be locked");
4572 torture_assert(tctx,
4573 test_ChangePasswordUser2(p, tctx, acct_name, password, NULL, false),
4574 "got wrong status from ChangePasswordUser2");
4576 torture_assert(tctx,
4577 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4578 3, 0, 0),
4579 "expected account to not be locked");
4581 /* Used to reset the badPwdCount for the other tests */
4582 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4583 *password,
4584 expected_success_status, interactive))
4586 torture_fail(tctx, "failed to authenticate after lockout expired");
4589 if (NT_STATUS_IS_OK(expected_success_status)) {
4590 torture_assert(tctx,
4591 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4592 0, 0, 0),
4593 "expected account to not be locked");
4594 } else {
4595 torture_assert(tctx,
4596 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4597 3, 0, 0),
4598 "expected account to not be locked");
4601 return true;
4604 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4605 struct torture_context *tctx,
4606 uint32_t acct_flags,
4607 const char *acct_name,
4608 struct policy_handle *domain_handle,
4609 struct policy_handle *user_handle,
4610 char **password,
4611 struct cli_credentials *machine_credentials)
4613 union samr_DomainInfo *q_info, s_info;
4614 struct samr_DomInfo1 info1, _info1;
4615 struct samr_DomInfo12 info12, _info12;
4616 bool ret = true;
4617 struct dcerpc_binding_handle *b = p->binding_handle;
4618 struct dcerpc_pipe *np;
4619 int i;
4621 struct {
4622 const char *comment;
4623 bool disabled;
4624 bool interactive;
4625 uint32_t password_history_length;
4626 NTSTATUS expected_success_status;
4627 } creds[] = {
4629 .comment = "network logon (disabled account)",
4630 .disabled = true,
4631 .interactive = false,
4632 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4635 .comment = "network logon (enabled account)",
4636 .disabled = false,
4637 .interactive = false,
4638 .expected_success_status= NT_STATUS_OK
4641 .comment = "network logon (enabled account, history len = 1)",
4642 .disabled = false,
4643 .interactive = false,
4644 .expected_success_status= NT_STATUS_OK,
4645 .password_history_length = 1
4648 .comment = "interactive logon (disabled account)",
4649 .disabled = true,
4650 .interactive = true,
4651 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4654 .comment = "interactive logon (enabled account)",
4655 .disabled = false,
4656 .interactive = true,
4657 .expected_success_status= NT_STATUS_OK
4660 .comment = "interactive logon (enabled account, history len = 1)",
4661 .disabled = false,
4662 .interactive = true,
4663 .expected_success_status= NT_STATUS_OK,
4664 .password_history_length = 1
4668 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4670 /* backup old policies */
4672 torture_assert(tctx,
4673 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4674 DomainPasswordInformation, &q_info),
4675 "failed to query domain info level 1");
4677 info1 = q_info->info1;
4678 _info1 = info1;
4680 torture_assert(tctx,
4681 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4682 DomainLockoutInformation, &q_info),
4683 "failed to query domain info level 12");
4685 info12 = q_info->info12;
4686 _info12 = info12;
4688 /* run tests */
4690 for (i=0; i < ARRAY_SIZE(creds); i++) {
4691 bool test_passed;
4692 /* skip trust tests for now */
4693 if (acct_flags & ACB_WSTRUST ||
4694 acct_flags & ACB_SVRTRUST ||
4695 acct_flags & ACB_DOMTRUST) {
4696 continue;
4699 test_passed = test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4700 domain_handle, user_handle, password,
4701 machine_credentials,
4702 creds[i].comment,
4703 creds[i].disabled,
4704 creds[i].interactive,
4705 creds[i].password_history_length,
4706 creds[i].expected_success_status,
4707 &_info1, &_info12);
4708 ret &= test_passed;
4709 if (!test_passed) {
4710 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4711 break;
4712 } else {
4713 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4717 /* restore policies */
4719 s_info.info1 = info1;
4721 torture_assert(tctx,
4722 test_SetDomainInfo(b, tctx, domain_handle,
4723 DomainPasswordInformation, &s_info),
4724 "failed to set password information");
4726 s_info.info12 = info12;
4728 torture_assert(tctx,
4729 test_SetDomainInfo(b, tctx, domain_handle,
4730 DomainLockoutInformation, &s_info),
4731 "failed to set lockout information");
4733 return ret;
4736 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4737 struct dcerpc_pipe *lp,
4738 struct torture_context *tctx,
4739 struct policy_handle *domain_handle,
4740 struct policy_handle *lsa_handle,
4741 struct policy_handle *user_handle,
4742 const struct dom_sid *domain_sid,
4743 uint32_t rid,
4744 struct cli_credentials *machine_credentials)
4746 bool ret = true;
4747 struct dcerpc_binding_handle *b = p->binding_handle;
4748 struct dcerpc_binding_handle *lb = lp->binding_handle;
4750 struct policy_handle lsa_acct_handle;
4751 struct dom_sid *user_sid;
4753 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4756 struct lsa_EnumAccountRights r;
4757 struct lsa_RightSet rights;
4759 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4761 r.in.handle = lsa_handle;
4762 r.in.sid = user_sid;
4763 r.out.rights = &rights;
4765 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4766 "lsa_EnumAccountRights failed");
4767 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4768 "Expected enum rights for account to fail");
4772 struct lsa_RightSet rights;
4773 struct lsa_StringLarge names[2];
4774 struct lsa_AddAccountRights r;
4776 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4778 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4779 init_lsa_StringLarge(&names[1], NULL);
4781 rights.count = 1;
4782 rights.names = names;
4784 r.in.handle = lsa_handle;
4785 r.in.sid = user_sid;
4786 r.in.rights = &rights;
4788 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4789 "lsa_AddAccountRights failed");
4790 torture_assert_ntstatus_ok(tctx, r.out.result,
4791 "Failed to add privileges");
4795 struct lsa_EnumAccounts r;
4796 uint32_t resume_handle = 0;
4797 struct lsa_SidArray lsa_sid_array;
4798 int i;
4799 bool found_sid = false;
4801 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4803 r.in.handle = lsa_handle;
4804 r.in.num_entries = 0x1000;
4805 r.in.resume_handle = &resume_handle;
4806 r.out.sids = &lsa_sid_array;
4807 r.out.resume_handle = &resume_handle;
4809 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4810 "lsa_EnumAccounts failed");
4811 torture_assert_ntstatus_ok(tctx, r.out.result,
4812 "Failed to enum accounts");
4814 for (i=0; i < lsa_sid_array.num_sids; i++) {
4815 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4816 found_sid = true;
4820 torture_assert(tctx, found_sid,
4821 "failed to list privileged account");
4825 struct lsa_EnumAccountRights r;
4826 struct lsa_RightSet user_rights;
4828 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4830 r.in.handle = lsa_handle;
4831 r.in.sid = user_sid;
4832 r.out.rights = &user_rights;
4834 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4835 "lsa_EnumAccountRights failed");
4836 torture_assert_ntstatus_ok(tctx, r.out.result,
4837 "Failed to enum rights for account");
4839 if (user_rights.count < 1) {
4840 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4841 return false;
4846 struct lsa_OpenAccount r;
4848 torture_comment(tctx, "Testing LSA OpenAccount\n");
4850 r.in.handle = lsa_handle;
4851 r.in.sid = user_sid;
4852 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4853 r.out.acct_handle = &lsa_acct_handle;
4855 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4856 "lsa_OpenAccount failed");
4857 torture_assert_ntstatus_ok(tctx, r.out.result,
4858 "Failed to open lsa account");
4862 struct lsa_GetSystemAccessAccount r;
4863 uint32_t access_mask;
4865 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4867 r.in.handle = &lsa_acct_handle;
4868 r.out.access_mask = &access_mask;
4870 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4871 "lsa_GetSystemAccessAccount failed");
4872 torture_assert_ntstatus_ok(tctx, r.out.result,
4873 "Failed to get lsa system access account");
4877 struct lsa_Close r;
4879 torture_comment(tctx, "Testing LSA Close\n");
4881 r.in.handle = &lsa_acct_handle;
4882 r.out.handle = &lsa_acct_handle;
4884 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4885 "lsa_Close failed");
4886 torture_assert_ntstatus_ok(tctx, r.out.result,
4887 "Failed to close lsa");
4891 struct samr_DeleteUser r;
4893 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4895 r.in.user_handle = user_handle;
4896 r.out.user_handle = user_handle;
4898 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4899 "DeleteUser failed");
4900 torture_assert_ntstatus_ok(tctx, r.out.result,
4901 "DeleteUser failed");
4905 struct lsa_EnumAccounts r;
4906 uint32_t resume_handle = 0;
4907 struct lsa_SidArray lsa_sid_array;
4908 int i;
4909 bool found_sid = false;
4911 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4913 r.in.handle = lsa_handle;
4914 r.in.num_entries = 0x1000;
4915 r.in.resume_handle = &resume_handle;
4916 r.out.sids = &lsa_sid_array;
4917 r.out.resume_handle = &resume_handle;
4919 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4920 "lsa_EnumAccounts failed");
4921 torture_assert_ntstatus_ok(tctx, r.out.result,
4922 "Failed to enum accounts");
4924 for (i=0; i < lsa_sid_array.num_sids; i++) {
4925 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4926 found_sid = true;
4930 torture_assert(tctx, found_sid,
4931 "failed to list privileged account");
4935 struct lsa_EnumAccountRights r;
4936 struct lsa_RightSet user_rights;
4938 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4940 r.in.handle = lsa_handle;
4941 r.in.sid = user_sid;
4942 r.out.rights = &user_rights;
4944 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4945 "lsa_EnumAccountRights failed");
4946 torture_assert_ntstatus_ok(tctx, r.out.result,
4947 "Failed to enum rights for account");
4949 if (user_rights.count < 1) {
4950 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4951 return false;
4956 struct lsa_OpenAccount r;
4958 torture_comment(tctx, "Testing LSA OpenAccount\n");
4960 r.in.handle = lsa_handle;
4961 r.in.sid = user_sid;
4962 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4963 r.out.acct_handle = &lsa_acct_handle;
4965 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4966 "lsa_OpenAccount failed");
4967 torture_assert_ntstatus_ok(tctx, r.out.result,
4968 "Failed to open lsa account");
4972 struct lsa_GetSystemAccessAccount r;
4973 uint32_t access_mask;
4975 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4977 r.in.handle = &lsa_acct_handle;
4978 r.out.access_mask = &access_mask;
4980 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4981 "lsa_GetSystemAccessAccount failed");
4982 torture_assert_ntstatus_ok(tctx, r.out.result,
4983 "Failed to get lsa system access account");
4987 struct lsa_DeleteObject r;
4989 torture_comment(tctx, "Testing LSA DeleteObject\n");
4991 r.in.handle = &lsa_acct_handle;
4992 r.out.handle = &lsa_acct_handle;
4994 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4995 "lsa_DeleteObject failed");
4996 torture_assert_ntstatus_ok(tctx, r.out.result,
4997 "Failed to delete object");
5001 struct lsa_EnumAccounts r;
5002 uint32_t resume_handle = 0;
5003 struct lsa_SidArray lsa_sid_array;
5004 int i;
5005 bool found_sid = false;
5007 torture_comment(tctx, "Testing LSA EnumAccounts\n");
5009 r.in.handle = lsa_handle;
5010 r.in.num_entries = 0x1000;
5011 r.in.resume_handle = &resume_handle;
5012 r.out.sids = &lsa_sid_array;
5013 r.out.resume_handle = &resume_handle;
5015 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
5016 "lsa_EnumAccounts failed");
5017 torture_assert_ntstatus_ok(tctx, r.out.result,
5018 "Failed to enum accounts");
5020 for (i=0; i < lsa_sid_array.num_sids; i++) {
5021 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
5022 found_sid = true;
5026 torture_assert(tctx, !found_sid,
5027 "should not have listed privileged account");
5031 struct lsa_EnumAccountRights r;
5032 struct lsa_RightSet user_rights;
5034 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
5036 r.in.handle = lsa_handle;
5037 r.in.sid = user_sid;
5038 r.out.rights = &user_rights;
5040 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
5041 "lsa_EnumAccountRights failed");
5042 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
5043 "Failed to enum rights for account");
5046 return ret;
5049 static bool test_user_ops(struct dcerpc_pipe *p,
5050 struct torture_context *tctx,
5051 struct policy_handle *user_handle,
5052 struct policy_handle *domain_handle,
5053 const struct dom_sid *domain_sid,
5054 uint32_t base_acct_flags,
5055 const char *base_acct_name, enum torture_samr_choice which_ops,
5056 struct cli_credentials *machine_credentials)
5058 char *password = NULL;
5059 struct samr_QueryUserInfo q;
5060 union samr_UserInfo *info;
5061 NTSTATUS status;
5062 struct dcerpc_binding_handle *b = p->binding_handle;
5064 bool ret = true;
5065 int i;
5066 uint32_t rid;
5067 const uint32_t password_fields[] = {
5068 SAMR_FIELD_NT_PASSWORD_PRESENT,
5069 SAMR_FIELD_LM_PASSWORD_PRESENT,
5070 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
5074 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
5075 if (!NT_STATUS_IS_OK(status)) {
5076 ret = false;
5079 switch (which_ops) {
5080 case TORTURE_SAMR_USER_ATTRIBUTES:
5081 if (!test_QuerySecurity(b, tctx, user_handle)) {
5082 ret = false;
5085 if (!test_QueryUserInfo(b, tctx, user_handle)) {
5086 ret = false;
5089 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
5090 ret = false;
5093 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
5094 base_acct_name)) {
5095 ret = false;
5098 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
5099 ret = false;
5102 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
5103 ret = false;
5106 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
5107 ret = false;
5109 break;
5110 case TORTURE_SAMR_PASSWORDS:
5111 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
5112 char simple_pass[9];
5113 char *v = generate_random_str(tctx, 1);
5115 ZERO_STRUCT(simple_pass);
5116 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5118 torture_comment(tctx, "Testing machine account password policy rules\n");
5120 /* Workstation trust accounts don't seem to need to honour password quality policy */
5121 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
5122 ret = false;
5125 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
5126 ret = false;
5129 /* reset again, to allow another 'user' password change */
5130 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
5131 ret = false;
5134 /* Try a 'short' password */
5135 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
5136 ret = false;
5139 /* Try a compleatly random password */
5140 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
5141 ret = false;
5145 for (i = 0; password_fields[i]; i++) {
5146 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
5147 ret = false;
5150 /* check it was set right */
5151 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5152 ret = false;
5156 for (i = 0; password_fields[i]; i++) {
5157 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
5158 ret = false;
5161 /* check it was set right */
5162 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5163 ret = false;
5167 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
5168 ret = false;
5171 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
5172 ret = false;
5175 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
5176 ret = false;
5179 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5180 ret = false;
5183 for (i = 0; password_fields[i]; i++) {
5185 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
5186 /* we need to skip as that would break
5187 * the ChangePasswordUser3 verify */
5188 continue;
5191 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
5192 ret = false;
5195 /* check it was set right */
5196 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5197 ret = false;
5201 q.in.user_handle = user_handle;
5202 q.in.level = 5;
5203 q.out.info = &info;
5205 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5206 "QueryUserInfo failed");
5207 if (!NT_STATUS_IS_OK(q.out.result)) {
5208 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5209 q.in.level, nt_errstr(q.out.result));
5210 ret = false;
5211 } else {
5212 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5213 if ((info->info5.acct_flags) != expected_flags) {
5214 /* FIXME: GD */
5215 if (!torture_setting_bool(tctx, "samba3", false)) {
5216 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5217 info->info5.acct_flags,
5218 expected_flags);
5219 ret = false;
5222 if (info->info5.rid != rid) {
5223 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
5224 info->info5.rid, rid);
5229 break;
5231 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
5233 /* test last password change timestamp behaviour */
5234 torture_assert(tctx, test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
5235 base_acct_name,
5236 user_handle, &password,
5237 machine_credentials),
5238 "pwdLastSet test failed\n");
5239 break;
5241 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
5243 /* test bad pwd count change behaviour */
5244 torture_assert(tctx, test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
5245 base_acct_name,
5246 domain_handle,
5247 user_handle, &password,
5248 machine_credentials),
5249 "badPwdCount test failed\n");
5250 break;
5252 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
5254 torture_assert(tctx, test_Password_lockout_wrap(p, tctx, base_acct_flags,
5255 base_acct_name,
5256 domain_handle,
5257 user_handle, &password,
5258 machine_credentials),
5259 "Lockout test failed");
5260 break;
5263 case TORTURE_SAMR_USER_PRIVILEGES: {
5265 struct dcerpc_pipe *lp;
5266 struct policy_handle *lsa_handle;
5267 struct dcerpc_binding_handle *lb;
5269 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
5270 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
5271 lb = lp->binding_handle;
5273 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
5274 ret = false;
5277 if (!test_DeleteUser_with_privs(p, lp, tctx,
5278 domain_handle, lsa_handle, user_handle,
5279 domain_sid, rid,
5280 machine_credentials)) {
5281 ret = false;
5284 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
5285 ret = false;
5288 if (!ret) {
5289 torture_result(tctx, TORTURE_FAIL, "privileged user delete test failed\n");
5292 break;
5294 case TORTURE_SAMR_OTHER:
5295 case TORTURE_SAMR_MANY_ACCOUNTS:
5296 case TORTURE_SAMR_MANY_GROUPS:
5297 case TORTURE_SAMR_MANY_ALIASES:
5298 /* We just need the account to exist */
5299 break;
5301 return ret;
5304 static bool test_alias_ops(struct dcerpc_binding_handle *b,
5305 struct torture_context *tctx,
5306 struct policy_handle *alias_handle,
5307 const struct dom_sid *domain_sid)
5309 bool ret = true;
5311 if (!torture_setting_bool(tctx, "samba3", false)) {
5312 if (!test_QuerySecurity(b, tctx, alias_handle)) {
5313 ret = false;
5317 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
5318 ret = false;
5321 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
5322 ret = false;
5325 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
5326 ret = false;
5329 if (torture_setting_bool(tctx, "samba3", false) ||
5330 torture_setting_bool(tctx, "samba4", false)) {
5331 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
5332 return ret;
5335 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
5336 ret = false;
5339 return ret;
5343 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
5344 struct torture_context *tctx,
5345 struct policy_handle *user_handle)
5347 struct samr_DeleteUser d;
5348 torture_comment(tctx, "Testing DeleteUser\n");
5350 d.in.user_handle = user_handle;
5351 d.out.user_handle = user_handle;
5353 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5354 "DeleteUser failed");
5355 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5357 return true;
5360 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5361 struct torture_context *tctx,
5362 struct policy_handle *handle, const char *name)
5364 NTSTATUS status;
5365 struct samr_DeleteUser d;
5366 struct policy_handle user_handle;
5367 uint32_t rid;
5369 status = test_LookupName(b, tctx, handle, name, &rid);
5370 if (!NT_STATUS_IS_OK(status)) {
5371 goto failed;
5374 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5375 if (!NT_STATUS_IS_OK(status)) {
5376 goto failed;
5379 d.in.user_handle = &user_handle;
5380 d.out.user_handle = &user_handle;
5381 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5382 "DeleteUser failed");
5383 if (!NT_STATUS_IS_OK(d.out.result)) {
5384 status = d.out.result;
5385 goto failed;
5388 return true;
5390 failed:
5391 torture_result(tctx, TORTURE_FAIL, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
5392 return false;
5396 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
5397 struct torture_context *tctx,
5398 struct policy_handle *handle, const char *name)
5400 NTSTATUS status;
5401 struct samr_OpenGroup r;
5402 struct samr_DeleteDomainGroup d;
5403 struct policy_handle group_handle;
5404 uint32_t rid;
5406 status = test_LookupName(b, tctx, handle, name, &rid);
5407 if (!NT_STATUS_IS_OK(status)) {
5408 goto failed;
5411 r.in.domain_handle = handle;
5412 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5413 r.in.rid = rid;
5414 r.out.group_handle = &group_handle;
5415 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5416 "OpenGroup failed");
5417 if (!NT_STATUS_IS_OK(r.out.result)) {
5418 status = r.out.result;
5419 goto failed;
5422 d.in.group_handle = &group_handle;
5423 d.out.group_handle = &group_handle;
5424 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
5425 "DeleteDomainGroup failed");
5426 if (!NT_STATUS_IS_OK(d.out.result)) {
5427 status = d.out.result;
5428 goto failed;
5431 return true;
5433 failed:
5434 torture_result(tctx, TORTURE_FAIL, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
5435 return false;
5439 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
5440 struct torture_context *tctx,
5441 struct policy_handle *domain_handle,
5442 const char *name)
5444 NTSTATUS status;
5445 struct samr_OpenAlias r;
5446 struct samr_DeleteDomAlias d;
5447 struct policy_handle alias_handle;
5448 uint32_t rid;
5450 torture_comment(tctx, "Testing DeleteAlias_byname\n");
5452 status = test_LookupName(b, tctx, domain_handle, name, &rid);
5453 if (!NT_STATUS_IS_OK(status)) {
5454 goto failed;
5457 r.in.domain_handle = domain_handle;
5458 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5459 r.in.rid = rid;
5460 r.out.alias_handle = &alias_handle;
5461 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5462 "OpenAlias failed");
5463 if (!NT_STATUS_IS_OK(r.out.result)) {
5464 status = r.out.result;
5465 goto failed;
5468 d.in.alias_handle = &alias_handle;
5469 d.out.alias_handle = &alias_handle;
5470 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5471 "DeleteDomAlias failed");
5472 if (!NT_STATUS_IS_OK(d.out.result)) {
5473 status = d.out.result;
5474 goto failed;
5477 return true;
5479 failed:
5480 torture_result(tctx, TORTURE_FAIL, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5481 return false;
5484 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5485 struct torture_context *tctx,
5486 struct policy_handle *alias_handle)
5488 struct samr_DeleteDomAlias d;
5489 bool ret = true;
5491 torture_comment(tctx, "Testing DeleteAlias\n");
5493 d.in.alias_handle = alias_handle;
5494 d.out.alias_handle = alias_handle;
5496 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5497 "DeleteDomAlias failed");
5498 if (!NT_STATUS_IS_OK(d.out.result)) {
5499 torture_result(tctx, TORTURE_FAIL, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5500 ret = false;
5503 return ret;
5506 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5507 struct torture_context *tctx,
5508 struct policy_handle *domain_handle,
5509 const char *alias_name,
5510 struct policy_handle *alias_handle,
5511 const struct dom_sid *domain_sid,
5512 bool test_alias)
5514 struct samr_CreateDomAlias r;
5515 struct lsa_String name;
5516 uint32_t rid;
5517 bool ret = true;
5519 init_lsa_String(&name, alias_name);
5520 r.in.domain_handle = domain_handle;
5521 r.in.alias_name = &name;
5522 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5523 r.out.alias_handle = alias_handle;
5524 r.out.rid = &rid;
5526 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5528 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5529 "CreateDomAlias failed");
5531 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5532 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5533 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5534 return true;
5535 } else {
5536 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5537 nt_errstr(r.out.result));
5538 return false;
5542 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5543 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5544 return false;
5546 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5547 "CreateDomAlias failed");
5550 if (!NT_STATUS_IS_OK(r.out.result)) {
5551 torture_result(tctx, TORTURE_FAIL, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5552 return false;
5555 if (!test_alias) {
5556 return ret;
5559 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5560 ret = false;
5563 return ret;
5566 static bool test_ChangePassword(struct dcerpc_pipe *p,
5567 struct torture_context *tctx,
5568 const char *acct_name,
5569 struct policy_handle *domain_handle, char **password)
5571 bool ret = true;
5572 struct dcerpc_binding_handle *b = p->binding_handle;
5574 if (!*password) {
5575 return false;
5578 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5579 ret = false;
5582 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5583 ret = false;
5586 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5587 ret = false;
5590 /* test what happens when setting the old password again */
5591 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5592 ret = false;
5596 char simple_pass[9];
5597 char *v = generate_random_str(tctx, 1);
5599 ZERO_STRUCT(simple_pass);
5600 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5602 /* test what happens when picking a simple password */
5603 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5604 ret = false;
5608 /* set samr_SetDomainInfo level 1 with min_length 5 */
5610 struct samr_QueryDomainInfo r;
5611 union samr_DomainInfo *info = NULL;
5612 struct samr_SetDomainInfo s;
5613 uint16_t len_old, len;
5614 uint32_t pwd_prop_old;
5615 int64_t min_pwd_age_old;
5617 len = 5;
5619 r.in.domain_handle = domain_handle;
5620 r.in.level = 1;
5621 r.out.info = &info;
5623 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5624 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5625 "QueryDomainInfo failed");
5626 if (!NT_STATUS_IS_OK(r.out.result)) {
5627 return false;
5630 s.in.domain_handle = domain_handle;
5631 s.in.level = 1;
5632 s.in.info = info;
5634 /* remember the old min length, so we can reset it */
5635 len_old = s.in.info->info1.min_password_length;
5636 s.in.info->info1.min_password_length = len;
5637 pwd_prop_old = s.in.info->info1.password_properties;
5638 /* turn off password complexity checks for this test */
5639 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5641 min_pwd_age_old = s.in.info->info1.min_password_age;
5642 s.in.info->info1.min_password_age = 0;
5644 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5645 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5646 "SetDomainInfo failed");
5647 if (!NT_STATUS_IS_OK(s.out.result)) {
5648 return false;
5651 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5653 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5654 ret = false;
5657 s.in.info->info1.min_password_length = len_old;
5658 s.in.info->info1.password_properties = pwd_prop_old;
5659 s.in.info->info1.min_password_age = min_pwd_age_old;
5661 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5662 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5663 "SetDomainInfo failed");
5664 if (!NT_STATUS_IS_OK(s.out.result)) {
5665 return false;
5671 struct samr_OpenUser r;
5672 struct samr_QueryUserInfo q;
5673 union samr_UserInfo *info;
5674 struct samr_LookupNames n;
5675 struct policy_handle user_handle;
5676 struct samr_Ids rids, types;
5678 n.in.domain_handle = domain_handle;
5679 n.in.num_names = 1;
5680 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5681 n.in.names[0].string = acct_name;
5682 n.out.rids = &rids;
5683 n.out.types = &types;
5685 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5686 "LookupNames failed");
5687 if (!NT_STATUS_IS_OK(n.out.result)) {
5688 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5689 return false;
5692 r.in.domain_handle = domain_handle;
5693 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5694 r.in.rid = n.out.rids->ids[0];
5695 r.out.user_handle = &user_handle;
5697 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5698 "OpenUser failed");
5699 if (!NT_STATUS_IS_OK(r.out.result)) {
5700 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5701 return false;
5704 q.in.user_handle = &user_handle;
5705 q.in.level = 5;
5706 q.out.info = &info;
5708 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5709 "QueryUserInfo failed");
5710 if (!NT_STATUS_IS_OK(q.out.result)) {
5711 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5712 return false;
5715 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5717 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5718 info->info5.last_password_change, true)) {
5719 ret = false;
5723 /* we change passwords twice - this has the effect of verifying
5724 they were changed correctly for the final call */
5725 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5726 ret = false;
5729 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5730 ret = false;
5733 return ret;
5736 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5737 struct policy_handle *domain_handle,
5738 const char *user_name,
5739 struct policy_handle *user_handle_out,
5740 struct dom_sid *domain_sid,
5741 enum torture_samr_choice which_ops,
5742 struct cli_credentials *machine_credentials,
5743 bool test_user)
5746 TALLOC_CTX *user_ctx;
5748 struct samr_CreateUser r;
5749 struct samr_QueryUserInfo q;
5750 union samr_UserInfo *info;
5751 struct samr_DeleteUser d;
5752 uint32_t rid;
5754 /* This call creates a 'normal' account - check that it really does */
5755 const uint32_t acct_flags = ACB_NORMAL;
5756 struct lsa_String name;
5757 bool ret = true;
5758 struct dcerpc_binding_handle *b = p->binding_handle;
5760 struct policy_handle user_handle;
5761 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5762 init_lsa_String(&name, user_name);
5764 r.in.domain_handle = domain_handle;
5765 r.in.account_name = &name;
5766 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5767 r.out.user_handle = &user_handle;
5768 r.out.rid = &rid;
5770 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5772 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5773 "CreateUser failed");
5775 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5776 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5777 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5778 return true;
5779 } else {
5780 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5781 nt_errstr(r.out.result));
5782 return false;
5786 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5787 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5788 talloc_free(user_ctx);
5789 return false;
5791 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5792 "CreateUser failed");
5795 if (!NT_STATUS_IS_OK(r.out.result)) {
5796 talloc_free(user_ctx);
5797 torture_result(tctx, TORTURE_FAIL, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5798 return false;
5801 if (!test_user) {
5802 if (user_handle_out) {
5803 *user_handle_out = user_handle;
5805 return ret;
5809 q.in.user_handle = &user_handle;
5810 q.in.level = 16;
5811 q.out.info = &info;
5813 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5814 "QueryUserInfo failed");
5815 if (!NT_STATUS_IS_OK(q.out.result)) {
5816 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5817 q.in.level, nt_errstr(q.out.result));
5818 ret = false;
5819 } else {
5820 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5821 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5822 info->info16.acct_flags,
5823 acct_flags);
5824 ret = false;
5828 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5829 domain_sid, acct_flags, name.string, which_ops,
5830 machine_credentials)) {
5831 ret = false;
5834 if (user_handle_out) {
5835 *user_handle_out = user_handle;
5836 } else {
5837 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5839 d.in.user_handle = &user_handle;
5840 d.out.user_handle = &user_handle;
5842 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5843 "DeleteUser failed");
5844 if (!NT_STATUS_IS_OK(d.out.result)) {
5845 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5846 ret = false;
5852 talloc_free(user_ctx);
5854 return ret;
5858 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5859 struct policy_handle *domain_handle,
5860 struct dom_sid *domain_sid,
5861 enum torture_samr_choice which_ops,
5862 struct cli_credentials *machine_credentials)
5864 struct samr_CreateUser2 r;
5865 struct samr_QueryUserInfo q;
5866 union samr_UserInfo *info;
5867 struct samr_DeleteUser d;
5868 struct policy_handle user_handle;
5869 uint32_t rid;
5870 struct lsa_String name;
5871 bool ret = true;
5872 int i;
5873 struct dcerpc_binding_handle *b = p->binding_handle;
5875 struct {
5876 uint32_t acct_flags;
5877 const char *account_name;
5878 NTSTATUS nt_status;
5879 } account_types[] = {
5880 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5881 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5882 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5883 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5884 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5885 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5886 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5887 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5888 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5889 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5890 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5891 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5892 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5893 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5894 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5897 for (i = 0; account_types[i].account_name; i++) {
5898 TALLOC_CTX *user_ctx;
5899 uint32_t acct_flags = account_types[i].acct_flags;
5900 uint32_t access_granted;
5901 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5902 init_lsa_String(&name, account_types[i].account_name);
5904 r.in.domain_handle = domain_handle;
5905 r.in.account_name = &name;
5906 r.in.acct_flags = acct_flags;
5907 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5908 r.out.user_handle = &user_handle;
5909 r.out.access_granted = &access_granted;
5910 r.out.rid = &rid;
5912 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5914 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5915 "CreateUser2 failed");
5917 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5918 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5919 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5920 continue;
5921 } else {
5922 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5923 nt_errstr(r.out.result));
5924 ret = false;
5925 continue;
5929 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5930 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5931 talloc_free(user_ctx);
5932 ret = false;
5933 continue;
5935 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5936 "CreateUser2 failed");
5939 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5940 torture_result(tctx, TORTURE_FAIL, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5941 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5942 ret = false;
5945 if (NT_STATUS_IS_OK(r.out.result)) {
5946 q.in.user_handle = &user_handle;
5947 q.in.level = 5;
5948 q.out.info = &info;
5950 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5951 "QueryUserInfo failed");
5952 if (!NT_STATUS_IS_OK(q.out.result)) {
5953 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5954 q.in.level, nt_errstr(q.out.result));
5955 ret = false;
5956 } else {
5957 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5958 if (acct_flags == ACB_NORMAL) {
5959 expected_flags |= ACB_PW_EXPIRED;
5961 if ((info->info5.acct_flags) != expected_flags) {
5962 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5963 info->info5.acct_flags,
5964 expected_flags);
5965 ret = false;
5967 switch (acct_flags) {
5968 case ACB_SVRTRUST:
5969 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5970 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5971 DOMAIN_RID_DCS, info->info5.primary_gid);
5972 ret = false;
5974 break;
5975 case ACB_WSTRUST:
5976 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5977 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5978 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5979 ret = false;
5981 break;
5982 case ACB_NORMAL:
5983 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5984 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5985 DOMAIN_RID_USERS, info->info5.primary_gid);
5986 ret = false;
5988 break;
5992 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5993 domain_sid, acct_flags, name.string, which_ops,
5994 machine_credentials)) {
5995 ret = false;
5998 if (!ndr_policy_handle_empty(&user_handle)) {
5999 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
6001 d.in.user_handle = &user_handle;
6002 d.out.user_handle = &user_handle;
6004 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
6005 "DeleteUser failed");
6006 if (!NT_STATUS_IS_OK(d.out.result)) {
6007 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
6008 ret = false;
6012 talloc_free(user_ctx);
6015 return ret;
6018 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
6019 struct torture_context *tctx,
6020 struct policy_handle *handle)
6022 struct samr_QueryAliasInfo r;
6023 union samr_AliasInfo *info;
6024 uint16_t levels[] = {1, 2, 3};
6025 int i;
6026 bool ret = true;
6028 for (i=0;i<ARRAY_SIZE(levels);i++) {
6029 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
6031 r.in.alias_handle = handle;
6032 r.in.level = levels[i];
6033 r.out.info = &info;
6035 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
6036 "QueryAliasInfo failed");
6037 if (!NT_STATUS_IS_OK(r.out.result)) {
6038 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
6039 levels[i], nt_errstr(r.out.result));
6040 ret = false;
6044 return ret;
6047 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
6048 struct torture_context *tctx,
6049 struct policy_handle *handle)
6051 struct samr_QueryGroupInfo r;
6052 union samr_GroupInfo *info;
6053 uint16_t levels[] = {1, 2, 3, 4, 5};
6054 int i;
6055 bool ret = true;
6057 for (i=0;i<ARRAY_SIZE(levels);i++) {
6058 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
6060 r.in.group_handle = handle;
6061 r.in.level = levels[i];
6062 r.out.info = &info;
6064 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
6065 "QueryGroupInfo failed");
6066 if (!NT_STATUS_IS_OK(r.out.result)) {
6067 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
6068 levels[i], nt_errstr(r.out.result));
6069 ret = false;
6073 return ret;
6076 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
6077 struct torture_context *tctx,
6078 struct policy_handle *handle)
6080 struct samr_QueryGroupMember r;
6081 struct samr_RidAttrArray *rids = NULL;
6082 bool ret = true;
6084 torture_comment(tctx, "Testing QueryGroupMember\n");
6086 r.in.group_handle = handle;
6087 r.out.rids = &rids;
6089 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
6090 "QueryGroupMember failed");
6091 if (!NT_STATUS_IS_OK(r.out.result)) {
6092 torture_result(tctx, TORTURE_FAIL, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
6093 ret = false;
6096 return ret;
6100 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
6101 struct torture_context *tctx,
6102 struct policy_handle *handle)
6104 struct samr_QueryGroupInfo r;
6105 union samr_GroupInfo *info;
6106 struct samr_SetGroupInfo s;
6107 uint16_t levels[] = {1, 2, 3, 4};
6108 uint16_t set_ok[] = {0, 1, 1, 1};
6109 int i;
6110 bool ret = true;
6112 for (i=0;i<ARRAY_SIZE(levels);i++) {
6113 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
6115 r.in.group_handle = handle;
6116 r.in.level = levels[i];
6117 r.out.info = &info;
6119 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
6120 "QueryGroupInfo failed");
6121 if (!NT_STATUS_IS_OK(r.out.result)) {
6122 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
6123 levels[i], nt_errstr(r.out.result));
6124 ret = false;
6127 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
6129 s.in.group_handle = handle;
6130 s.in.level = levels[i];
6131 s.in.info = *r.out.info;
6133 #if 0
6134 /* disabled this, as it changes the name only from the point of view of samr,
6135 but leaves the name from the point of view of w2k3 internals (and ldap). This means
6136 the name is still reserved, so creating the old name fails, but deleting by the old name
6137 also fails */
6138 if (s.in.level == 2) {
6139 init_lsa_String(&s.in.info->string, "NewName");
6141 #endif
6143 if (s.in.level == 4) {
6144 init_lsa_String(&s.in.info->description, "test description");
6147 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
6148 "SetGroupInfo failed");
6149 if (set_ok[i]) {
6150 if (!NT_STATUS_IS_OK(s.out.result)) {
6151 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u failed - %s\n",
6152 r.in.level, nt_errstr(s.out.result));
6153 ret = false;
6154 continue;
6156 } else {
6157 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6158 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6159 r.in.level, nt_errstr(s.out.result));
6160 ret = false;
6161 continue;
6166 return ret;
6169 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
6170 struct torture_context *tctx,
6171 struct policy_handle *handle)
6173 struct samr_QueryUserInfo r;
6174 union samr_UserInfo *info;
6175 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6176 11, 12, 13, 14, 16, 17, 20, 21};
6177 int i;
6178 bool ret = true;
6180 for (i=0;i<ARRAY_SIZE(levels);i++) {
6181 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
6183 r.in.user_handle = handle;
6184 r.in.level = levels[i];
6185 r.out.info = &info;
6187 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
6188 "QueryUserInfo failed");
6189 if (!NT_STATUS_IS_OK(r.out.result)) {
6190 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
6191 levels[i], nt_errstr(r.out.result));
6192 ret = false;
6196 return ret;
6199 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
6200 struct torture_context *tctx,
6201 struct policy_handle *handle)
6203 struct samr_QueryUserInfo2 r;
6204 union samr_UserInfo *info;
6205 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6206 11, 12, 13, 14, 16, 17, 20, 21};
6207 int i;
6208 bool ret = true;
6210 for (i=0;i<ARRAY_SIZE(levels);i++) {
6211 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
6213 r.in.user_handle = handle;
6214 r.in.level = levels[i];
6215 r.out.info = &info;
6217 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
6218 "QueryUserInfo2 failed");
6219 if (!NT_STATUS_IS_OK(r.out.result)) {
6220 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo2 level %u failed - %s\n",
6221 levels[i], nt_errstr(r.out.result));
6222 ret = false;
6226 return ret;
6229 static bool test_OpenUser(struct dcerpc_binding_handle *b,
6230 struct torture_context *tctx,
6231 struct policy_handle *handle, uint32_t rid)
6233 struct samr_OpenUser r;
6234 struct policy_handle user_handle;
6235 bool ret = true;
6237 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6239 r.in.domain_handle = handle;
6240 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6241 r.in.rid = rid;
6242 r.out.user_handle = &user_handle;
6244 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6245 "OpenUser failed");
6246 if (!NT_STATUS_IS_OK(r.out.result)) {
6247 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6248 return false;
6251 if (!test_QuerySecurity(b, tctx, &user_handle)) {
6252 ret = false;
6255 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
6256 ret = false;
6259 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
6260 ret = false;
6263 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
6264 ret = false;
6267 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
6268 ret = false;
6271 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6272 ret = false;
6275 return ret;
6278 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
6279 struct torture_context *tctx,
6280 struct policy_handle *handle, uint32_t rid)
6282 struct samr_OpenGroup r;
6283 struct policy_handle group_handle;
6284 bool ret = true;
6286 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
6288 r.in.domain_handle = handle;
6289 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6290 r.in.rid = rid;
6291 r.out.group_handle = &group_handle;
6293 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
6294 "OpenGroup failed");
6295 if (!NT_STATUS_IS_OK(r.out.result)) {
6296 torture_result(tctx, TORTURE_FAIL, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6297 return false;
6300 if (!torture_setting_bool(tctx, "samba3", false)) {
6301 if (!test_QuerySecurity(b, tctx, &group_handle)) {
6302 ret = false;
6306 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
6307 ret = false;
6310 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
6311 ret = false;
6314 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
6315 ret = false;
6318 return ret;
6321 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
6322 struct torture_context *tctx,
6323 struct policy_handle *handle, uint32_t rid)
6325 struct samr_OpenAlias r;
6326 struct policy_handle alias_handle;
6327 bool ret = true;
6329 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
6331 r.in.domain_handle = handle;
6332 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6333 r.in.rid = rid;
6334 r.out.alias_handle = &alias_handle;
6336 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
6337 "OpenAlias failed");
6338 if (!NT_STATUS_IS_OK(r.out.result)) {
6339 torture_result(tctx, TORTURE_FAIL, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6340 return false;
6343 if (!torture_setting_bool(tctx, "samba3", false)) {
6344 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
6345 ret = false;
6349 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6350 ret = false;
6353 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6354 ret = false;
6357 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6358 ret = false;
6361 return ret;
6364 static bool check_mask(struct dcerpc_binding_handle *b,
6365 struct torture_context *tctx,
6366 struct policy_handle *handle, uint32_t rid,
6367 uint32_t acct_flag_mask)
6369 struct samr_OpenUser r;
6370 struct samr_QueryUserInfo q;
6371 union samr_UserInfo *info;
6372 struct policy_handle user_handle;
6373 bool ret = true;
6375 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6377 r.in.domain_handle = handle;
6378 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6379 r.in.rid = rid;
6380 r.out.user_handle = &user_handle;
6382 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6383 "OpenUser failed");
6384 if (!NT_STATUS_IS_OK(r.out.result)) {
6385 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6386 return false;
6389 q.in.user_handle = &user_handle;
6390 q.in.level = 16;
6391 q.out.info = &info;
6393 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6394 "QueryUserInfo failed");
6395 if (!NT_STATUS_IS_OK(q.out.result)) {
6396 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed - %s\n",
6397 nt_errstr(q.out.result));
6398 ret = false;
6399 } else {
6400 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
6401 torture_result(tctx, TORTURE_FAIL, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
6402 acct_flag_mask, info->info16.acct_flags, rid);
6403 ret = false;
6407 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6408 ret = false;
6411 return ret;
6414 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
6415 struct torture_context *tctx,
6416 struct policy_handle *handle)
6418 struct samr_EnumDomainUsers r;
6419 uint32_t mask, resume_handle=0;
6420 int i, mask_idx;
6421 bool ret = true;
6422 struct samr_LookupNames n;
6423 struct samr_LookupRids lr ;
6424 struct lsa_Strings names;
6425 struct samr_Ids rids, types;
6426 struct samr_SamArray *sam = NULL;
6427 uint32_t num_entries = 0;
6429 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
6430 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
6431 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
6432 ACB_PWNOEXP, 0};
6434 torture_comment(tctx, "Testing EnumDomainUsers\n");
6436 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
6437 r.in.domain_handle = handle;
6438 r.in.resume_handle = &resume_handle;
6439 r.in.acct_flags = mask = masks[mask_idx];
6440 r.in.max_size = (uint32_t)-1;
6441 r.out.resume_handle = &resume_handle;
6442 r.out.num_entries = &num_entries;
6443 r.out.sam = &sam;
6445 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
6446 "EnumDomainUsers failed");
6447 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6448 !NT_STATUS_IS_OK(r.out.result)) {
6449 torture_result(tctx, TORTURE_FAIL, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
6450 return false;
6453 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6455 if (sam->count == 0) {
6456 continue;
6459 for (i=0;i<sam->count;i++) {
6460 if (mask) {
6461 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6462 ret = false;
6464 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6465 ret = false;
6470 torture_comment(tctx, "Testing LookupNames\n");
6471 n.in.domain_handle = handle;
6472 n.in.num_names = sam->count;
6473 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6474 n.out.rids = &rids;
6475 n.out.types = &types;
6476 for (i=0;i<sam->count;i++) {
6477 n.in.names[i].string = sam->entries[i].name.string;
6479 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6480 "LookupNames failed");
6481 if (!NT_STATUS_IS_OK(n.out.result)) {
6482 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6483 ret = false;
6487 torture_comment(tctx, "Testing LookupRids\n");
6488 lr.in.domain_handle = handle;
6489 lr.in.num_rids = sam->count;
6490 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6491 lr.out.names = &names;
6492 lr.out.types = &types;
6493 for (i=0;i<sam->count;i++) {
6494 lr.in.rids[i] = sam->entries[i].idx;
6496 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6497 "LookupRids failed");
6498 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6500 return ret;
6504 try blasting the server with a bunch of sync requests
6506 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6507 struct policy_handle *handle)
6509 struct samr_EnumDomainUsers r;
6510 uint32_t resume_handle=0;
6511 int i;
6512 #define ASYNC_COUNT 100
6513 struct tevent_req *req[ASYNC_COUNT];
6515 if (!torture_setting_bool(tctx, "dangerous", false)) {
6516 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6519 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6521 r.in.domain_handle = handle;
6522 r.in.resume_handle = &resume_handle;
6523 r.in.acct_flags = 0;
6524 r.in.max_size = (uint32_t)-1;
6525 r.out.resume_handle = &resume_handle;
6527 for (i=0;i<ASYNC_COUNT;i++) {
6528 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6531 for (i=0;i<ASYNC_COUNT;i++) {
6532 tevent_req_poll(req[i], tctx->ev);
6533 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6534 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6535 i, nt_errstr(r.out.result)));
6538 torture_comment(tctx, "%d async requests OK\n", i);
6540 return true;
6543 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6544 struct torture_context *tctx,
6545 struct policy_handle *handle)
6547 struct samr_EnumDomainGroups r;
6548 uint32_t resume_handle=0;
6549 struct samr_SamArray *sam = NULL;
6550 uint32_t num_entries = 0;
6551 int i;
6552 bool ret = true;
6553 bool universal_group_found = false;
6555 torture_comment(tctx, "Testing EnumDomainGroups\n");
6557 r.in.domain_handle = handle;
6558 r.in.resume_handle = &resume_handle;
6559 r.in.max_size = (uint32_t)-1;
6560 r.out.resume_handle = &resume_handle;
6561 r.out.num_entries = &num_entries;
6562 r.out.sam = &sam;
6564 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6565 "EnumDomainGroups failed");
6566 if (!NT_STATUS_IS_OK(r.out.result)) {
6567 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6568 return false;
6571 if (!sam) {
6572 return false;
6575 for (i=0;i<sam->count;i++) {
6576 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6577 ret = false;
6579 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6580 "Enterprise Admins") == 0)) {
6581 universal_group_found = true;
6585 /* when we are running this on s4 we should get back at least the
6586 * "Enterprise Admins" universal group. If we don't get a group entry
6587 * at all we probably are performing the test on the builtin domain.
6588 * So ignore this case. */
6589 if (torture_setting_bool(tctx, "samba4", false)) {
6590 if ((sam->count > 0) && (!universal_group_found)) {
6591 ret = false;
6595 return ret;
6598 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6599 struct torture_context *tctx,
6600 struct policy_handle *handle)
6602 struct samr_EnumDomainAliases r;
6603 uint32_t resume_handle=0;
6604 struct samr_SamArray *sam = NULL;
6605 uint32_t num_entries = 0;
6606 int i;
6607 bool ret = true;
6609 torture_comment(tctx, "Testing EnumDomainAliases\n");
6611 r.in.domain_handle = handle;
6612 r.in.resume_handle = &resume_handle;
6613 r.in.max_size = (uint32_t)-1;
6614 r.out.sam = &sam;
6615 r.out.num_entries = &num_entries;
6616 r.out.resume_handle = &resume_handle;
6618 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6619 "EnumDomainAliases failed");
6620 if (!NT_STATUS_IS_OK(r.out.result)) {
6621 torture_result(tctx, TORTURE_FAIL, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6622 return false;
6625 if (!sam) {
6626 return false;
6629 for (i=0;i<sam->count;i++) {
6630 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6631 ret = false;
6635 return ret;
6638 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6639 struct torture_context *tctx,
6640 struct policy_handle *handle)
6642 struct samr_GetDisplayEnumerationIndex r;
6643 bool ret = true;
6644 uint16_t levels[] = {1, 2, 3, 4, 5};
6645 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6646 struct lsa_String name;
6647 uint32_t idx = 0;
6648 int i;
6650 for (i=0;i<ARRAY_SIZE(levels);i++) {
6651 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6653 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6655 r.in.domain_handle = handle;
6656 r.in.level = levels[i];
6657 r.in.name = &name;
6658 r.out.idx = &idx;
6660 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6661 "GetDisplayEnumerationIndex failed");
6663 if (ok_lvl[i] &&
6664 !NT_STATUS_IS_OK(r.out.result) &&
6665 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6666 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6667 levels[i], nt_errstr(r.out.result));
6668 ret = false;
6671 init_lsa_String(&name, "zzzzzzzz");
6673 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6674 "GetDisplayEnumerationIndex failed");
6676 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6677 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6678 levels[i], nt_errstr(r.out.result));
6679 ret = false;
6683 return ret;
6686 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6687 struct torture_context *tctx,
6688 struct policy_handle *handle)
6690 struct samr_GetDisplayEnumerationIndex2 r;
6691 bool ret = true;
6692 uint16_t levels[] = {1, 2, 3, 4, 5};
6693 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6694 struct lsa_String name;
6695 uint32_t idx = 0;
6696 int i;
6698 for (i=0;i<ARRAY_SIZE(levels);i++) {
6699 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6701 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6703 r.in.domain_handle = handle;
6704 r.in.level = levels[i];
6705 r.in.name = &name;
6706 r.out.idx = &idx;
6708 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6709 "GetDisplayEnumerationIndex2 failed");
6710 if (ok_lvl[i] &&
6711 !NT_STATUS_IS_OK(r.out.result) &&
6712 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6713 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6714 levels[i], nt_errstr(r.out.result));
6715 ret = false;
6718 init_lsa_String(&name, "zzzzzzzz");
6720 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6721 "GetDisplayEnumerationIndex2 failed");
6722 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6723 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6724 levels[i], nt_errstr(r.out.result));
6725 ret = false;
6729 return ret;
6732 #define STRING_EQUAL_QUERY(s1, s2, user) \
6733 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6734 /* odd, but valid */ \
6735 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6736 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: %s != %s (%s)\n", \
6737 #s1, user.string, s1.string, s2.string, __location__); \
6738 ret = false; \
6740 #define INT_EQUAL_QUERY(s1, s2, user) \
6741 if (s1 != s2) { \
6742 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6743 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6744 ret = false; \
6747 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6748 struct torture_context *tctx,
6749 struct samr_QueryDisplayInfo *querydisplayinfo,
6750 bool *seen_testuser)
6752 struct samr_OpenUser r;
6753 struct samr_QueryUserInfo q;
6754 union samr_UserInfo *info;
6755 struct policy_handle user_handle;
6756 int i, ret = true;
6757 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6758 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6759 for (i = 0; ; i++) {
6760 switch (querydisplayinfo->in.level) {
6761 case 1:
6762 if (i >= querydisplayinfo->out.info->info1.count) {
6763 return ret;
6765 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6766 break;
6767 case 2:
6768 if (i >= querydisplayinfo->out.info->info2.count) {
6769 return ret;
6771 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6772 break;
6773 case 3:
6774 /* Groups */
6775 case 4:
6776 case 5:
6777 /* Not interested in validating just the account name */
6778 return true;
6781 r.out.user_handle = &user_handle;
6783 switch (querydisplayinfo->in.level) {
6784 case 1:
6785 case 2:
6786 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6787 "OpenUser failed");
6788 if (!NT_STATUS_IS_OK(r.out.result)) {
6789 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6790 return false;
6794 q.in.user_handle = &user_handle;
6795 q.in.level = 21;
6796 q.out.info = &info;
6797 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6798 "QueryUserInfo failed");
6799 if (!NT_STATUS_IS_OK(r.out.result)) {
6800 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6801 return false;
6804 switch (querydisplayinfo->in.level) {
6805 case 1:
6806 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6807 *seen_testuser = true;
6809 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6810 info->info21.full_name, info->info21.account_name);
6811 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6812 info->info21.account_name, info->info21.account_name);
6813 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6814 info->info21.description, info->info21.account_name);
6815 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6816 info->info21.rid, info->info21.account_name);
6817 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6818 info->info21.acct_flags, info->info21.account_name);
6820 break;
6821 case 2:
6822 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6823 info->info21.account_name, info->info21.account_name);
6824 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6825 info->info21.description, info->info21.account_name);
6826 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6827 info->info21.rid, info->info21.account_name);
6828 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6829 info->info21.acct_flags, info->info21.account_name);
6831 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6832 torture_result(tctx, TORTURE_FAIL, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6833 info->info21.account_name.string);
6836 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6837 torture_result(tctx, TORTURE_FAIL, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6838 info->info21.account_name.string,
6839 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6840 info->info21.acct_flags);
6841 return false;
6844 break;
6847 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6848 return false;
6851 return ret;
6854 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6855 struct torture_context *tctx,
6856 struct policy_handle *handle)
6858 struct samr_QueryDisplayInfo r;
6859 struct samr_QueryDomainInfo dom_info;
6860 union samr_DomainInfo *info = NULL;
6861 bool ret = true;
6862 uint16_t levels[] = {1, 2, 3, 4, 5};
6863 int i;
6864 bool seen_testuser = false;
6865 uint32_t total_size;
6866 uint32_t returned_size;
6867 union samr_DispInfo disp_info;
6870 for (i=0;i<ARRAY_SIZE(levels);i++) {
6871 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6873 r.in.start_idx = 0;
6874 r.out.result = STATUS_MORE_ENTRIES;
6875 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6876 r.in.domain_handle = handle;
6877 r.in.level = levels[i];
6878 r.in.max_entries = 2;
6879 r.in.buf_size = (uint32_t)-1;
6880 r.out.total_size = &total_size;
6881 r.out.returned_size = &returned_size;
6882 r.out.info = &disp_info;
6884 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6885 "QueryDisplayInfo failed");
6886 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6887 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
6888 levels[i], nt_errstr(r.out.result));
6889 ret = false;
6891 switch (r.in.level) {
6892 case 1:
6893 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6894 ret = false;
6896 r.in.start_idx += r.out.info->info1.count;
6897 break;
6898 case 2:
6899 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6900 ret = false;
6902 r.in.start_idx += r.out.info->info2.count;
6903 break;
6904 case 3:
6905 r.in.start_idx += r.out.info->info3.count;
6906 break;
6907 case 4:
6908 r.in.start_idx += r.out.info->info4.count;
6909 break;
6910 case 5:
6911 r.in.start_idx += r.out.info->info5.count;
6912 break;
6915 dom_info.in.domain_handle = handle;
6916 dom_info.in.level = 2;
6917 dom_info.out.info = &info;
6919 /* Check number of users returned is correct */
6920 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6921 "QueryDomainInfo failed");
6922 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6923 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6924 r.in.level, nt_errstr(dom_info.out.result));
6925 ret = false;
6926 break;
6928 switch (r.in.level) {
6929 case 1:
6930 case 4:
6931 if (info->general.num_users < r.in.start_idx) {
6932 /* On AD deployments this numbers don't match
6933 * since QueryDisplayInfo returns universal and
6934 * global groups, QueryDomainInfo only global
6935 * ones. */
6936 if (torture_setting_bool(tctx, "samba3", false)) {
6937 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6938 r.in.start_idx, info->general.num_groups,
6939 info->general.domain_name.string);
6940 ret = false;
6943 if (!seen_testuser) {
6944 struct policy_handle user_handle;
6945 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6946 torture_result(tctx, TORTURE_FAIL, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6947 info->general.domain_name.string);
6948 ret = false;
6949 test_samr_handle_Close(b, tctx, &user_handle);
6952 break;
6953 case 3:
6954 case 5:
6955 if (info->general.num_groups != r.in.start_idx) {
6956 /* On AD deployments this numbers don't match
6957 * since QueryDisplayInfo returns universal and
6958 * global groups, QueryDomainInfo only global
6959 * ones. */
6960 if (torture_setting_bool(tctx, "samba3", false)) {
6961 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6962 r.in.start_idx, info->general.num_groups,
6963 info->general.domain_name.string);
6964 ret = false;
6968 break;
6973 return ret;
6976 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6977 struct torture_context *tctx,
6978 struct policy_handle *handle)
6980 struct samr_QueryDisplayInfo2 r;
6981 bool ret = true;
6982 uint16_t levels[] = {1, 2, 3, 4, 5};
6983 int i;
6984 uint32_t total_size;
6985 uint32_t returned_size;
6986 union samr_DispInfo info;
6988 for (i=0;i<ARRAY_SIZE(levels);i++) {
6989 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6991 r.in.domain_handle = handle;
6992 r.in.level = levels[i];
6993 r.in.start_idx = 0;
6994 r.in.max_entries = 1000;
6995 r.in.buf_size = (uint32_t)-1;
6996 r.out.total_size = &total_size;
6997 r.out.returned_size = &returned_size;
6998 r.out.info = &info;
7000 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
7001 "QueryDisplayInfo2 failed");
7002 if (!NT_STATUS_IS_OK(r.out.result)) {
7003 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo2 level %u failed - %s\n",
7004 levels[i], nt_errstr(r.out.result));
7005 ret = false;
7009 return ret;
7012 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
7013 struct torture_context *tctx,
7014 struct policy_handle *handle)
7016 struct samr_QueryDisplayInfo3 r;
7017 bool ret = true;
7018 uint16_t levels[] = {1, 2, 3, 4, 5};
7019 int i;
7020 uint32_t total_size;
7021 uint32_t returned_size;
7022 union samr_DispInfo info;
7024 for (i=0;i<ARRAY_SIZE(levels);i++) {
7025 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
7027 r.in.domain_handle = handle;
7028 r.in.level = levels[i];
7029 r.in.start_idx = 0;
7030 r.in.max_entries = 1000;
7031 r.in.buf_size = (uint32_t)-1;
7032 r.out.total_size = &total_size;
7033 r.out.returned_size = &returned_size;
7034 r.out.info = &info;
7036 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
7037 "QueryDisplayInfo3 failed");
7038 if (!NT_STATUS_IS_OK(r.out.result)) {
7039 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo3 level %u failed - %s\n",
7040 levels[i], nt_errstr(r.out.result));
7041 ret = false;
7045 return ret;
7049 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
7050 struct torture_context *tctx,
7051 struct policy_handle *handle)
7053 struct samr_QueryDisplayInfo r;
7054 bool ret = true;
7055 uint32_t total_size;
7056 uint32_t returned_size;
7057 union samr_DispInfo info;
7059 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
7061 r.in.domain_handle = handle;
7062 r.in.level = 1;
7063 r.in.start_idx = 0;
7064 r.in.max_entries = 1;
7065 r.in.buf_size = (uint32_t)-1;
7066 r.out.total_size = &total_size;
7067 r.out.returned_size = &returned_size;
7068 r.out.info = &info;
7070 do {
7071 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7072 "QueryDisplayInfo failed");
7073 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
7074 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
7075 torture_result(tctx, TORTURE_FAIL, "expected idx %d but got %d\n",
7076 r.in.start_idx + 1,
7077 r.out.info->info1.entries[0].idx);
7078 break;
7081 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
7082 !NT_STATUS_IS_OK(r.out.result)) {
7083 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
7084 r.in.level, nt_errstr(r.out.result));
7085 ret = false;
7086 break;
7088 r.in.start_idx++;
7089 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
7090 NT_STATUS_IS_OK(r.out.result)) &&
7091 *r.out.returned_size != 0);
7093 return ret;
7096 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
7097 struct torture_context *tctx,
7098 struct policy_handle *handle)
7100 struct samr_QueryDomainInfo r;
7101 union samr_DomainInfo *info = NULL;
7102 struct samr_SetDomainInfo s;
7103 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
7104 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
7105 int i;
7106 bool ret = true;
7107 struct dcerpc_binding_handle *b = p->binding_handle;
7108 const char *domain_comment = talloc_asprintf(tctx,
7109 "Tortured by Samba4 RPC-SAMR: %s",
7110 timestring(tctx, time(NULL)));
7112 s.in.domain_handle = handle;
7113 s.in.level = 4;
7114 s.in.info = talloc(tctx, union samr_DomainInfo);
7116 s.in.info->oem.oem_information.string = domain_comment;
7117 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
7118 "SetDomainInfo failed");
7119 if (!NT_STATUS_IS_OK(s.out.result)) {
7120 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u (set comment) failed - %s\n",
7121 s.in.level, nt_errstr(s.out.result));
7122 return false;
7125 for (i=0;i<ARRAY_SIZE(levels);i++) {
7126 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
7128 r.in.domain_handle = handle;
7129 r.in.level = levels[i];
7130 r.out.info = &info;
7132 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
7133 "QueryDomainInfo failed");
7134 if (!NT_STATUS_IS_OK(r.out.result)) {
7135 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7136 r.in.level, nt_errstr(r.out.result));
7137 ret = false;
7138 continue;
7141 switch (levels[i]) {
7142 case 2:
7143 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
7144 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
7145 levels[i], info->general.oem_information.string, domain_comment);
7146 if (!torture_setting_bool(tctx, "samba3", false)) {
7147 ret = false;
7150 if (!info->general.primary.string) {
7151 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
7152 levels[i]);
7153 ret = false;
7154 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
7155 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
7156 if (torture_setting_bool(tctx, "samba3", false)) {
7157 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",
7158 levels[i], info->general.primary.string, dcerpc_server_name(p));
7162 break;
7163 case 4:
7164 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
7165 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
7166 levels[i], info->oem.oem_information.string, domain_comment);
7167 if (!torture_setting_bool(tctx, "samba3", false)) {
7168 ret = false;
7171 break;
7172 case 6:
7173 if (!info->info6.primary.string) {
7174 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
7175 levels[i]);
7176 ret = false;
7178 break;
7179 case 11:
7180 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
7181 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
7182 levels[i], info->general2.general.oem_information.string, domain_comment);
7183 if (!torture_setting_bool(tctx, "samba3", false)) {
7184 ret = false;
7187 break;
7190 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
7192 s.in.domain_handle = handle;
7193 s.in.level = levels[i];
7194 s.in.info = info;
7196 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
7197 "SetDomainInfo failed");
7198 if (set_ok[i]) {
7199 if (!NT_STATUS_IS_OK(s.out.result)) {
7200 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u failed - %s\n",
7201 r.in.level, nt_errstr(s.out.result));
7202 ret = false;
7203 continue;
7205 } else {
7206 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
7207 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
7208 r.in.level, nt_errstr(s.out.result));
7209 ret = false;
7210 continue;
7214 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
7215 "QueryDomainInfo failed");
7216 if (!NT_STATUS_IS_OK(r.out.result)) {
7217 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7218 r.in.level, nt_errstr(r.out.result));
7219 ret = false;
7220 continue;
7224 return ret;
7228 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
7229 struct torture_context *tctx,
7230 struct policy_handle *handle)
7232 struct samr_QueryDomainInfo2 r;
7233 union samr_DomainInfo *info = NULL;
7234 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
7235 int i;
7236 bool ret = true;
7238 for (i=0;i<ARRAY_SIZE(levels);i++) {
7239 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
7241 r.in.domain_handle = handle;
7242 r.in.level = levels[i];
7243 r.out.info = &info;
7245 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7246 "QueryDomainInfo2 failed");
7247 if (!NT_STATUS_IS_OK(r.out.result)) {
7248 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo2 level %u failed - %s\n",
7249 r.in.level, nt_errstr(r.out.result));
7250 ret = false;
7251 continue;
7255 return true;
7258 /* Test whether querydispinfo level 5 and enumdomgroups return the same
7259 set of group names. */
7260 static bool test_GroupList(struct dcerpc_binding_handle *b,
7261 struct torture_context *tctx,
7262 struct dom_sid *domain_sid,
7263 struct policy_handle *handle)
7265 struct samr_EnumDomainGroups q1;
7266 struct samr_QueryDisplayInfo q2;
7267 NTSTATUS status;
7268 uint32_t resume_handle=0;
7269 struct samr_SamArray *sam = NULL;
7270 uint32_t num_entries = 0;
7271 int i;
7272 bool ret = true;
7273 uint32_t total_size;
7274 uint32_t returned_size;
7275 union samr_DispInfo info;
7277 int num_names = 0;
7278 const char **names = NULL;
7280 bool builtin_domain = dom_sid_compare(domain_sid,
7281 &global_sid_Builtin) == 0;
7283 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
7285 q1.in.domain_handle = handle;
7286 q1.in.resume_handle = &resume_handle;
7287 q1.in.max_size = 5;
7288 q1.out.resume_handle = &resume_handle;
7289 q1.out.num_entries = &num_entries;
7290 q1.out.sam = &sam;
7292 status = STATUS_MORE_ENTRIES;
7293 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7294 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
7295 "EnumDomainGroups failed");
7296 status = q1.out.result;
7298 if (!NT_STATUS_IS_OK(status) &&
7299 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7300 break;
7302 for (i=0; i<*q1.out.num_entries; i++) {
7303 add_string_to_array(tctx,
7304 sam->entries[i].name.string,
7305 &names, &num_names);
7309 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
7311 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
7313 if (builtin_domain) {
7314 torture_assert(tctx, num_names == 0,
7315 "EnumDomainGroups shouldn't return any group in the builtin domain!");
7318 q2.in.domain_handle = handle;
7319 q2.in.level = 5;
7320 q2.in.start_idx = 0;
7321 q2.in.max_entries = 5;
7322 q2.in.buf_size = (uint32_t)-1;
7323 q2.out.total_size = &total_size;
7324 q2.out.returned_size = &returned_size;
7325 q2.out.info = &info;
7327 status = STATUS_MORE_ENTRIES;
7328 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7329 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
7330 "QueryDisplayInfo failed");
7331 status = q2.out.result;
7332 if (!NT_STATUS_IS_OK(status) &&
7333 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7334 break;
7336 for (i=0; i<q2.out.info->info5.count; i++) {
7337 int j;
7338 const char *name = q2.out.info->info5.entries[i].account_name.string;
7339 bool found = false;
7340 for (j=0; j<num_names; j++) {
7341 if (names[j] == NULL)
7342 continue;
7343 if (strequal(names[j], name)) {
7344 names[j] = NULL;
7345 found = true;
7346 break;
7350 if ((!found) && (!builtin_domain)) {
7351 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7352 name);
7353 ret = false;
7356 q2.in.start_idx += q2.out.info->info5.count;
7359 if (!NT_STATUS_IS_OK(status)) {
7360 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level 5 failed - %s\n",
7361 nt_errstr(status));
7362 ret = false;
7365 if (builtin_domain) {
7366 torture_assert(tctx, q2.in.start_idx != 0,
7367 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
7370 for (i=0; i<num_names; i++) {
7371 if (names[i] != NULL) {
7372 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
7373 names[i]);
7374 ret = false;
7378 return ret;
7381 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
7382 struct torture_context *tctx,
7383 struct policy_handle *group_handle)
7385 struct samr_DeleteDomainGroup d;
7387 torture_comment(tctx, "Testing DeleteDomainGroup\n");
7389 d.in.group_handle = group_handle;
7390 d.out.group_handle = group_handle;
7392 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
7393 "DeleteDomainGroup failed");
7394 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
7396 return true;
7399 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
7400 struct torture_context *tctx,
7401 struct policy_handle *domain_handle)
7403 struct samr_TestPrivateFunctionsDomain r;
7404 bool ret = true;
7406 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
7408 r.in.domain_handle = domain_handle;
7410 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
7411 "TestPrivateFunctionsDomain failed");
7412 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
7414 return ret;
7417 static bool test_RidToSid(struct dcerpc_binding_handle *b,
7418 struct torture_context *tctx,
7419 struct dom_sid *domain_sid,
7420 struct policy_handle *domain_handle)
7422 struct samr_RidToSid r;
7423 bool ret = true;
7424 struct dom_sid *calc_sid, *out_sid;
7425 int rids[] = { 0, 42, 512, 10200 };
7426 int i;
7428 for (i=0;i<ARRAY_SIZE(rids);i++) {
7429 torture_comment(tctx, "Testing RidToSid\n");
7431 calc_sid = dom_sid_dup(tctx, domain_sid);
7432 r.in.domain_handle = domain_handle;
7433 r.in.rid = rids[i];
7434 r.out.sid = &out_sid;
7436 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
7437 "RidToSid failed");
7438 if (!NT_STATUS_IS_OK(r.out.result)) {
7439 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
7440 ret = false;
7441 } else {
7442 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
7444 if (!dom_sid_equal(calc_sid, out_sid)) {
7445 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
7446 dom_sid_string(tctx, out_sid),
7447 dom_sid_string(tctx, calc_sid));
7448 ret = false;
7453 return ret;
7456 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7457 struct torture_context *tctx,
7458 struct policy_handle *domain_handle)
7460 struct samr_GetBootKeyInformation r;
7461 bool ret = true;
7462 uint32_t unknown = 0;
7463 NTSTATUS status;
7465 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7467 r.in.domain_handle = domain_handle;
7468 r.out.unknown = &unknown;
7470 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7471 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7472 status = r.out.result;
7474 if (!NT_STATUS_IS_OK(status)) {
7475 /* w2k3 seems to fail this sometimes and pass it sometimes */
7476 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7479 return ret;
7482 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7483 struct torture_context *tctx,
7484 struct policy_handle *domain_handle,
7485 struct policy_handle *group_handle)
7487 NTSTATUS status;
7488 struct samr_AddGroupMember r;
7489 struct samr_DeleteGroupMember d;
7490 struct samr_QueryGroupMember q;
7491 struct samr_RidAttrArray *rids = NULL;
7492 struct samr_SetMemberAttributesOfGroup s;
7493 uint32_t rid;
7494 bool found_member = false;
7495 int i;
7497 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7498 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7500 r.in.group_handle = group_handle;
7501 r.in.rid = rid;
7502 r.in.flags = 0; /* ??? */
7504 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7506 d.in.group_handle = group_handle;
7507 d.in.rid = rid;
7509 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7510 "DeleteGroupMember failed");
7511 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7513 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7514 "AddGroupMember failed");
7515 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7517 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7518 "AddGroupMember failed");
7519 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7521 if (torture_setting_bool(tctx, "samba4", false) ||
7522 torture_setting_bool(tctx, "samba3", false)) {
7523 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7524 } else {
7525 /* this one is quite strange. I am using random inputs in the
7526 hope of triggering an error that might give us a clue */
7528 s.in.group_handle = group_handle;
7529 s.in.unknown1 = random();
7530 s.in.unknown2 = random();
7532 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7533 "SetMemberAttributesOfGroup failed");
7534 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7537 q.in.group_handle = group_handle;
7538 q.out.rids = &rids;
7540 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7541 "QueryGroupMember failed");
7542 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7543 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7545 for (i=0; i < rids->count; i++) {
7546 if (rids->rids[i] == rid) {
7547 found_member = true;
7551 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7553 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7554 "DeleteGroupMember failed");
7555 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7557 rids = NULL;
7558 found_member = false;
7560 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7561 "QueryGroupMember failed");
7562 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7563 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7565 for (i=0; i < rids->count; i++) {
7566 if (rids->rids[i] == rid) {
7567 found_member = true;
7571 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7573 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7574 "AddGroupMember failed");
7575 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7577 return true;
7581 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7582 struct torture_context *tctx,
7583 struct policy_handle *domain_handle,
7584 const char *group_name,
7585 struct policy_handle *group_handle,
7586 struct dom_sid *domain_sid,
7587 bool test_group)
7589 struct samr_CreateDomainGroup r;
7590 uint32_t rid;
7591 struct lsa_String name;
7592 bool ret = true;
7594 init_lsa_String(&name, group_name);
7596 r.in.domain_handle = domain_handle;
7597 r.in.name = &name;
7598 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7599 r.out.group_handle = group_handle;
7600 r.out.rid = &rid;
7602 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7604 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7605 "CreateDomainGroup failed");
7607 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7608 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7609 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7610 return true;
7611 } else {
7612 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7613 nt_errstr(r.out.result));
7614 return false;
7618 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7619 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7620 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7621 nt_errstr(r.out.result));
7622 return false;
7624 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7625 "CreateDomainGroup failed");
7627 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7628 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7630 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7631 nt_errstr(r.out.result));
7632 return false;
7634 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7635 "CreateDomainGroup failed");
7637 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7639 if (!test_group) {
7640 return ret;
7643 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7644 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7645 ret = false;
7648 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7649 ret = false;
7652 return ret;
7657 its not totally clear what this does. It seems to accept any sid you like.
7659 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7660 struct torture_context *tctx,
7661 struct policy_handle *domain_handle)
7663 struct samr_RemoveMemberFromForeignDomain r;
7665 r.in.domain_handle = domain_handle;
7666 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7668 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7669 "RemoveMemberFromForeignDomain failed");
7670 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7672 return true;
7675 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7676 struct torture_context *tctx,
7677 struct policy_handle *domain_handle,
7678 uint32_t *total_num_entries_p)
7680 NTSTATUS status;
7681 struct samr_EnumDomainUsers r;
7682 uint32_t resume_handle = 0;
7683 uint32_t num_entries = 0;
7684 uint32_t total_num_entries = 0;
7685 struct samr_SamArray *sam;
7687 r.in.domain_handle = domain_handle;
7688 r.in.acct_flags = 0;
7689 r.in.max_size = (uint32_t)-1;
7690 r.in.resume_handle = &resume_handle;
7692 r.out.sam = &sam;
7693 r.out.num_entries = &num_entries;
7694 r.out.resume_handle = &resume_handle;
7696 torture_comment(tctx, "Testing EnumDomainUsers\n");
7698 do {
7699 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7700 "EnumDomainUsers failed");
7701 if (NT_STATUS_IS_ERR(r.out.result)) {
7702 torture_assert_ntstatus_ok(tctx, r.out.result,
7703 "failed to enumerate users");
7705 status = r.out.result;
7707 total_num_entries += num_entries;
7708 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7710 if (total_num_entries_p) {
7711 *total_num_entries_p = total_num_entries;
7714 return true;
7717 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7718 struct torture_context *tctx,
7719 struct policy_handle *domain_handle,
7720 uint32_t *total_num_entries_p)
7722 NTSTATUS status;
7723 struct samr_EnumDomainGroups r;
7724 uint32_t resume_handle = 0;
7725 uint32_t num_entries = 0;
7726 uint32_t total_num_entries = 0;
7727 struct samr_SamArray *sam;
7729 r.in.domain_handle = domain_handle;
7730 r.in.max_size = (uint32_t)-1;
7731 r.in.resume_handle = &resume_handle;
7733 r.out.sam = &sam;
7734 r.out.num_entries = &num_entries;
7735 r.out.resume_handle = &resume_handle;
7737 torture_comment(tctx, "Testing EnumDomainGroups\n");
7739 do {
7740 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7741 "EnumDomainGroups failed");
7742 if (NT_STATUS_IS_ERR(r.out.result)) {
7743 torture_assert_ntstatus_ok(tctx, r.out.result,
7744 "failed to enumerate groups");
7746 status = r.out.result;
7748 total_num_entries += num_entries;
7749 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7751 if (total_num_entries_p) {
7752 *total_num_entries_p = total_num_entries;
7755 return true;
7758 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7759 struct torture_context *tctx,
7760 struct policy_handle *domain_handle,
7761 uint32_t *total_num_entries_p)
7763 NTSTATUS status;
7764 struct samr_EnumDomainAliases r;
7765 uint32_t resume_handle = 0;
7766 uint32_t num_entries = 0;
7767 uint32_t total_num_entries = 0;
7768 struct samr_SamArray *sam;
7770 r.in.domain_handle = domain_handle;
7771 r.in.max_size = (uint32_t)-1;
7772 r.in.resume_handle = &resume_handle;
7774 r.out.sam = &sam;
7775 r.out.num_entries = &num_entries;
7776 r.out.resume_handle = &resume_handle;
7778 torture_comment(tctx, "Testing EnumDomainAliases\n");
7780 do {
7781 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7782 "EnumDomainAliases failed");
7783 if (NT_STATUS_IS_ERR(r.out.result)) {
7784 torture_assert_ntstatus_ok(tctx, r.out.result,
7785 "failed to enumerate aliases");
7787 status = r.out.result;
7789 total_num_entries += num_entries;
7790 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7792 if (total_num_entries_p) {
7793 *total_num_entries_p = total_num_entries;
7796 return true;
7799 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7800 struct torture_context *tctx,
7801 struct policy_handle *handle,
7802 uint16_t level,
7803 uint32_t *total_num_entries_p)
7805 NTSTATUS status;
7806 struct samr_QueryDisplayInfo r;
7807 uint32_t total_num_entries = 0;
7809 r.in.domain_handle = handle;
7810 r.in.level = level;
7811 r.in.start_idx = 0;
7812 r.in.max_entries = (uint32_t)-1;
7813 r.in.buf_size = (uint32_t)-1;
7815 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7817 do {
7818 uint32_t total_size;
7819 uint32_t returned_size;
7820 union samr_DispInfo info;
7822 r.out.total_size = &total_size;
7823 r.out.returned_size = &returned_size;
7824 r.out.info = &info;
7826 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7827 "failed to query displayinfo");
7828 if (NT_STATUS_IS_ERR(r.out.result)) {
7829 torture_assert_ntstatus_ok(tctx, r.out.result,
7830 "failed to query displayinfo");
7832 status = r.out.result;
7834 if (*r.out.returned_size == 0) {
7835 break;
7838 switch (r.in.level) {
7839 case 1:
7840 total_num_entries += info.info1.count;
7841 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7842 break;
7843 case 2:
7844 total_num_entries += info.info2.count;
7845 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7846 break;
7847 case 3:
7848 total_num_entries += info.info3.count;
7849 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7850 break;
7851 case 4:
7852 total_num_entries += info.info4.count;
7853 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7854 break;
7855 case 5:
7856 total_num_entries += info.info5.count;
7857 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7858 break;
7859 default:
7860 return false;
7863 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7865 if (total_num_entries_p) {
7866 *total_num_entries_p = total_num_entries;
7869 return true;
7872 static bool test_ManyObjects(struct dcerpc_pipe *p,
7873 struct torture_context *tctx,
7874 struct policy_handle *domain_handle,
7875 struct dom_sid *domain_sid,
7876 struct torture_samr_context *ctx)
7878 uint32_t num_total = ctx->num_objects_large_dc;
7879 uint32_t num_enum = 0;
7880 uint32_t num_disp = 0;
7881 uint32_t num_created = 0;
7882 uint32_t num_anounced = 0;
7883 uint32_t i;
7884 struct dcerpc_binding_handle *b = p->binding_handle;
7886 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7888 /* query */
7891 struct samr_QueryDomainInfo2 r;
7892 union samr_DomainInfo *info;
7893 r.in.domain_handle = domain_handle;
7894 r.in.level = 2;
7895 r.out.info = &info;
7897 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7898 "QueryDomainInfo2 failed");
7899 torture_assert_ntstatus_ok(tctx, r.out.result,
7900 "failed to query domain info");
7902 switch (ctx->choice) {
7903 case TORTURE_SAMR_MANY_ACCOUNTS:
7904 num_anounced = info->general.num_users;
7905 break;
7906 case TORTURE_SAMR_MANY_GROUPS:
7907 num_anounced = info->general.num_groups;
7908 break;
7909 case TORTURE_SAMR_MANY_ALIASES:
7910 num_anounced = info->general.num_aliases;
7911 break;
7912 default:
7913 return false;
7917 /* create */
7919 for (i=0; i < num_total; i++) {
7921 const char *name = NULL;
7923 switch (ctx->choice) {
7924 case TORTURE_SAMR_MANY_ACCOUNTS:
7925 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7926 torture_assert(tctx,
7927 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7928 "failed to create user");
7929 break;
7930 case TORTURE_SAMR_MANY_GROUPS:
7931 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7932 torture_assert(tctx,
7933 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7934 "failed to create group");
7935 break;
7936 case TORTURE_SAMR_MANY_ALIASES:
7937 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7938 torture_assert(tctx,
7939 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7940 "failed to create alias");
7941 break;
7942 default:
7943 return false;
7945 if (!ndr_policy_handle_empty(&handles[i])) {
7946 num_created++;
7950 /* enum */
7952 switch (ctx->choice) {
7953 case TORTURE_SAMR_MANY_ACCOUNTS:
7954 torture_assert(tctx,
7955 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7956 "failed to enum users");
7957 break;
7958 case TORTURE_SAMR_MANY_GROUPS:
7959 torture_assert(tctx,
7960 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7961 "failed to enum groups");
7962 break;
7963 case TORTURE_SAMR_MANY_ALIASES:
7964 torture_assert(tctx,
7965 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7966 "failed to enum aliases");
7967 break;
7968 default:
7969 return false;
7972 /* dispinfo */
7974 switch (ctx->choice) {
7975 case TORTURE_SAMR_MANY_ACCOUNTS:
7976 torture_assert(tctx,
7977 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
7978 "failed to query display info");
7979 break;
7980 case TORTURE_SAMR_MANY_GROUPS:
7981 torture_assert(tctx,
7982 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
7983 "failed to query display info");
7984 break;
7985 case TORTURE_SAMR_MANY_ALIASES:
7986 /* no aliases in dispinfo */
7987 break;
7988 default:
7989 return false;
7992 /* close or delete */
7994 for (i=0; i < num_total; i++) {
7996 if (ndr_policy_handle_empty(&handles[i])) {
7997 continue;
8000 if (torture_setting_bool(tctx, "samba3", false)) {
8001 torture_assert(tctx,
8002 test_samr_handle_Close(b, tctx, &handles[i]),
8003 "failed to close handle");
8004 } else {
8005 switch (ctx->choice) {
8006 case TORTURE_SAMR_MANY_ACCOUNTS:
8007 torture_assert(tctx,
8008 test_DeleteUser(b, tctx, &handles[i]),
8009 "failed to delete user");
8010 break;
8011 case TORTURE_SAMR_MANY_GROUPS:
8012 torture_assert(tctx,
8013 test_DeleteDomainGroup(b, tctx, &handles[i]),
8014 "failed to delete group");
8015 break;
8016 case TORTURE_SAMR_MANY_ALIASES:
8017 torture_assert(tctx,
8018 test_DeleteAlias(b, tctx, &handles[i]),
8019 "failed to delete alias");
8020 break;
8021 default:
8022 return false;
8027 talloc_free(handles);
8029 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
8030 torture_comment(tctx,
8031 "unexpected number of results (%u) returned in enum call, expected %u\n",
8032 num_enum, num_anounced + num_created);
8034 torture_comment(tctx,
8035 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
8036 num_disp, num_anounced + num_created);
8039 return true;
8042 static bool test_Connect(struct dcerpc_binding_handle *b,
8043 struct torture_context *tctx,
8044 struct policy_handle *handle);
8046 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
8047 struct torture_samr_context *ctx, struct dom_sid *sid)
8049 struct samr_OpenDomain r;
8050 struct policy_handle domain_handle;
8051 struct policy_handle alias_handle;
8052 struct policy_handle user_handle;
8053 struct policy_handle group_handle;
8054 bool ret = true;
8055 struct dcerpc_binding_handle *b = p->binding_handle;
8057 ZERO_STRUCT(alias_handle);
8058 ZERO_STRUCT(user_handle);
8059 ZERO_STRUCT(group_handle);
8060 ZERO_STRUCT(domain_handle);
8062 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
8064 r.in.connect_handle = &ctx->handle;
8065 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8066 r.in.sid = sid;
8067 r.out.domain_handle = &domain_handle;
8069 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
8070 "OpenDomain failed");
8071 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
8073 /* run the domain tests with the main handle closed - this tests
8074 the servers reference counting */
8075 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
8077 switch (ctx->choice) {
8078 case TORTURE_SAMR_PASSWORDS:
8079 case TORTURE_SAMR_USER_PRIVILEGES:
8080 if (!torture_setting_bool(tctx, "samba3", false)) {
8081 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
8083 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8084 if (!ret) {
8085 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
8087 break;
8088 case TORTURE_SAMR_USER_ATTRIBUTES:
8089 if (!torture_setting_bool(tctx, "samba3", false)) {
8090 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
8092 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8093 /* This test needs 'complex' users to validate */
8094 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
8095 if (!ret) {
8096 torture_result(tctx, TORTURE_FAIL, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
8098 break;
8099 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
8100 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
8101 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
8102 if (!torture_setting_bool(tctx, "samba3", false)) {
8103 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
8105 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
8106 if (!ret) {
8107 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
8109 break;
8110 case TORTURE_SAMR_MANY_ACCOUNTS:
8111 case TORTURE_SAMR_MANY_GROUPS:
8112 case TORTURE_SAMR_MANY_ALIASES:
8113 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
8114 if (!ret) {
8115 torture_result(tctx, TORTURE_FAIL, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
8117 break;
8118 case TORTURE_SAMR_OTHER:
8119 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8120 if (!ret) {
8121 torture_result(tctx, TORTURE_FAIL, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
8123 if (!torture_setting_bool(tctx, "samba3", false)) {
8124 ret &= test_QuerySecurity(b, tctx, &domain_handle);
8126 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
8127 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
8128 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
8129 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
8130 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
8131 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
8132 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
8133 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
8134 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
8135 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
8136 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
8137 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
8138 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
8140 if (torture_setting_bool(tctx, "samba4", false)) {
8141 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
8142 } else {
8143 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
8144 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
8146 ret &= test_GroupList(b, tctx, sid, &domain_handle);
8147 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
8148 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
8149 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
8150 if (!ret) {
8151 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
8153 break;
8156 if (!ndr_policy_handle_empty(&user_handle) &&
8157 !test_DeleteUser(b, tctx, &user_handle)) {
8158 ret = false;
8161 if (!ndr_policy_handle_empty(&alias_handle) &&
8162 !test_DeleteAlias(b, tctx, &alias_handle)) {
8163 ret = false;
8166 if (!ndr_policy_handle_empty(&group_handle) &&
8167 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
8168 ret = false;
8171 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
8173 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
8174 /* reconnect the main handle */
8176 if (!ret) {
8177 torture_result(tctx, TORTURE_FAIL, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
8180 return ret;
8183 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
8184 struct torture_samr_context *ctx, const char *domain)
8186 struct samr_LookupDomain r;
8187 struct dom_sid2 *sid = NULL;
8188 struct lsa_String n1;
8189 struct lsa_String n2;
8190 bool ret = true;
8191 struct dcerpc_binding_handle *b = p->binding_handle;
8193 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
8195 /* check for correct error codes */
8196 r.in.connect_handle = &ctx->handle;
8197 r.in.domain_name = &n2;
8198 r.out.sid = &sid;
8199 n2.string = NULL;
8201 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8202 "LookupDomain failed");
8203 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
8205 init_lsa_String(&n2, "xxNODOMAINxx");
8207 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8208 "LookupDomain failed");
8209 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
8211 r.in.connect_handle = &ctx->handle;
8213 init_lsa_String(&n1, domain);
8214 r.in.domain_name = &n1;
8216 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8217 "LookupDomain failed");
8218 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
8220 if (!test_GetDomPwInfo(p, tctx, &n1)) {
8221 ret = false;
8224 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
8225 ret = false;
8228 return ret;
8232 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
8233 struct torture_samr_context *ctx)
8235 struct samr_EnumDomains r;
8236 uint32_t resume_handle = 0;
8237 uint32_t num_entries = 0;
8238 struct samr_SamArray *sam = NULL;
8239 int i;
8240 bool ret = true;
8241 struct dcerpc_binding_handle *b = p->binding_handle;
8243 r.in.connect_handle = &ctx->handle;
8244 r.in.resume_handle = &resume_handle;
8245 r.in.buf_size = (uint32_t)-1;
8246 r.out.resume_handle = &resume_handle;
8247 r.out.num_entries = &num_entries;
8248 r.out.sam = &sam;
8250 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
8251 "EnumDomains failed");
8252 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
8254 if (!*r.out.sam) {
8255 return false;
8258 for (i=0;i<sam->count;i++) {
8259 if (!test_LookupDomain(p, tctx, ctx,
8260 sam->entries[i].name.string)) {
8261 ret = false;
8265 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
8266 "EnumDomains failed");
8267 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
8269 return ret;
8273 static bool test_Connect(struct dcerpc_binding_handle *b,
8274 struct torture_context *tctx,
8275 struct policy_handle *handle)
8277 struct samr_Connect r;
8278 struct samr_Connect2 r2;
8279 struct samr_Connect3 r3;
8280 struct samr_Connect4 r4;
8281 struct samr_Connect5 r5;
8282 union samr_ConnectInfo info;
8283 struct policy_handle h;
8284 uint32_t level_out = 0;
8285 bool ret = true, got_handle = false;
8287 torture_comment(tctx, "Testing samr_Connect\n");
8289 r.in.system_name = NULL;
8290 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8291 r.out.connect_handle = &h;
8293 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
8294 "Connect failed");
8295 if (!NT_STATUS_IS_OK(r.out.result)) {
8296 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
8297 ret = false;
8298 } else {
8299 got_handle = true;
8300 *handle = h;
8303 torture_comment(tctx, "Testing samr_Connect2\n");
8305 r2.in.system_name = NULL;
8306 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8307 r2.out.connect_handle = &h;
8309 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
8310 "Connect2 failed");
8311 if (!NT_STATUS_IS_OK(r2.out.result)) {
8312 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
8313 ret = false;
8314 } else {
8315 if (got_handle) {
8316 test_samr_handle_Close(b, tctx, handle);
8318 got_handle = true;
8319 *handle = h;
8322 torture_comment(tctx, "Testing samr_Connect3\n");
8324 r3.in.system_name = NULL;
8325 r3.in.unknown = 0;
8326 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8327 r3.out.connect_handle = &h;
8329 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
8330 "Connect3 failed");
8331 if (!NT_STATUS_IS_OK(r3.out.result)) {
8332 torture_result(tctx, TORTURE_FAIL, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
8333 ret = false;
8334 } else {
8335 if (got_handle) {
8336 test_samr_handle_Close(b, tctx, handle);
8338 got_handle = true;
8339 *handle = h;
8342 torture_comment(tctx, "Testing samr_Connect4\n");
8344 r4.in.system_name = "";
8345 r4.in.client_version = 0;
8346 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8347 r4.out.connect_handle = &h;
8349 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8350 "Connect4 failed");
8351 if (!NT_STATUS_IS_OK(r4.out.result)) {
8352 torture_result(tctx, TORTURE_FAIL, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8353 ret = false;
8354 } else {
8355 if (got_handle) {
8356 test_samr_handle_Close(b, tctx, handle);
8358 got_handle = true;
8359 *handle = h;
8362 torture_comment(tctx, "Testing samr_Connect5\n");
8364 info.info1.client_version = 0;
8365 info.info1.unknown2 = 0;
8367 r5.in.system_name = "";
8368 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8369 r5.in.level_in = 1;
8370 r5.out.level_out = &level_out;
8371 r5.in.info_in = &info;
8372 r5.out.info_out = &info;
8373 r5.out.connect_handle = &h;
8375 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
8376 "Connect5 failed");
8377 if (!NT_STATUS_IS_OK(r5.out.result)) {
8378 torture_result(tctx, TORTURE_FAIL, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
8379 ret = false;
8380 } else {
8381 if (got_handle) {
8382 test_samr_handle_Close(b, tctx, handle);
8384 got_handle = true;
8385 *handle = h;
8388 return ret;
8392 static bool test_samr_ValidatePassword(struct torture_context *tctx,
8393 struct dcerpc_pipe *p)
8395 struct samr_ValidatePassword r;
8396 union samr_ValidatePasswordReq req;
8397 union samr_ValidatePasswordRep *repp = NULL;
8398 NTSTATUS status;
8399 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
8400 int i;
8401 struct dcerpc_binding_handle *b = p->binding_handle;
8403 torture_comment(tctx, "Testing samr_ValidatePassword\n");
8405 if (p->conn->transport.transport != NCACN_IP_TCP) {
8406 torture_comment(tctx, "samr_ValidatePassword only should succeed over NCACN_IP_TCP!\n");
8409 ZERO_STRUCT(r);
8410 r.in.level = NetValidatePasswordReset;
8411 r.in.req = &req;
8412 r.out.rep = &repp;
8414 ZERO_STRUCT(req);
8415 req.req3.account.string = "non-existent-account-aklsdji";
8417 for (i=0; passwords[i]; i++) {
8418 req.req3.password.string = passwords[i];
8420 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
8421 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
8422 torture_skip(tctx, "ValidatePassword not supported by server\n");
8424 torture_assert_ntstatus_ok(tctx, status,
8425 "samr_ValidatePassword failed");
8426 torture_assert_ntstatus_ok(tctx, r.out.result,
8427 "samr_ValidatePassword failed");
8428 torture_comment(tctx, "Server %s password '%s' with code %i\n",
8429 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
8430 req.req3.password.string, repp->ctr3.status);
8433 return true;
8436 bool torture_rpc_samr(struct torture_context *torture)
8438 NTSTATUS status;
8439 struct dcerpc_pipe *p;
8440 bool ret = true;
8441 struct torture_samr_context *ctx;
8442 struct dcerpc_binding_handle *b;
8444 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8445 if (!NT_STATUS_IS_OK(status)) {
8446 return false;
8448 b = p->binding_handle;
8450 ctx = talloc_zero(torture, struct torture_samr_context);
8452 ctx->choice = TORTURE_SAMR_OTHER;
8454 ret &= test_Connect(b, torture, &ctx->handle);
8456 if (!torture_setting_bool(torture, "samba3", false)) {
8457 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8460 ret &= test_EnumDomains(p, torture, ctx);
8462 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8464 ret &= test_Shutdown(b, torture, &ctx->handle);
8466 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8468 return ret;
8472 bool torture_rpc_samr_users(struct torture_context *torture)
8474 NTSTATUS status;
8475 struct dcerpc_pipe *p;
8476 bool ret = true;
8477 struct torture_samr_context *ctx;
8478 struct dcerpc_binding_handle *b;
8480 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8481 if (!NT_STATUS_IS_OK(status)) {
8482 return false;
8484 b = p->binding_handle;
8486 ctx = talloc_zero(torture, struct torture_samr_context);
8488 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8490 ret &= test_Connect(b, torture, &ctx->handle);
8492 if (!torture_setting_bool(torture, "samba3", false)) {
8493 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8496 ret &= test_EnumDomains(p, torture, ctx);
8498 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8500 ret &= test_Shutdown(b, torture, &ctx->handle);
8502 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8504 return ret;
8508 bool torture_rpc_samr_passwords(struct torture_context *torture)
8510 NTSTATUS status;
8511 struct dcerpc_pipe *p;
8512 bool ret = true;
8513 struct torture_samr_context *ctx;
8514 struct dcerpc_binding_handle *b;
8516 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8517 if (!NT_STATUS_IS_OK(status)) {
8518 return false;
8520 b = p->binding_handle;
8522 ctx = talloc_zero(torture, struct torture_samr_context);
8524 ctx->choice = TORTURE_SAMR_PASSWORDS;
8526 ret &= test_Connect(b, torture, &ctx->handle);
8528 ret &= test_EnumDomains(p, torture, ctx);
8530 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8532 return ret;
8535 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8536 struct dcerpc_pipe *p2,
8537 struct cli_credentials *machine_credentials)
8539 NTSTATUS status;
8540 struct dcerpc_pipe *p;
8541 bool ret = true;
8542 struct torture_samr_context *ctx;
8543 struct dcerpc_binding_handle *b;
8545 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8546 if (!NT_STATUS_IS_OK(status)) {
8547 return false;
8549 b = p->binding_handle;
8551 ctx = talloc_zero(torture, struct torture_samr_context);
8553 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8554 ctx->machine_credentials = machine_credentials;
8556 ret &= test_Connect(b, torture, &ctx->handle);
8558 ret &= test_EnumDomains(p, torture, ctx);
8560 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8562 return ret;
8565 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8567 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8568 struct torture_rpc_tcase *tcase;
8570 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8571 &ndr_table_samr,
8572 TEST_ACCOUNT_NAME_PWD);
8574 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8575 torture_rpc_samr_pwdlastset);
8577 return suite;
8580 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8581 struct dcerpc_pipe *p2,
8582 struct cli_credentials *machine_credentials)
8584 NTSTATUS status;
8585 struct dcerpc_pipe *p;
8586 bool ret = true;
8587 struct torture_samr_context *ctx;
8588 struct dcerpc_binding_handle *b;
8590 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8591 if (!NT_STATUS_IS_OK(status)) {
8592 return false;
8594 b = p->binding_handle;
8596 ctx = talloc_zero(torture, struct torture_samr_context);
8598 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8599 ctx->machine_credentials = machine_credentials;
8601 ret &= test_Connect(b, torture, &ctx->handle);
8603 ret &= test_EnumDomains(p, torture, ctx);
8605 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8607 return ret;
8610 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8612 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8613 struct torture_rpc_tcase *tcase;
8615 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8616 &ndr_table_samr,
8617 TEST_ACCOUNT_NAME_PWD);
8619 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8620 torture_rpc_samr_users_privileges_delete_user);
8622 return suite;
8625 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8626 struct dcerpc_pipe *p2,
8627 void *data)
8629 NTSTATUS status;
8630 struct dcerpc_pipe *p;
8631 bool ret = true;
8632 struct torture_samr_context *ctx =
8633 talloc_get_type_abort(data, struct torture_samr_context);
8634 struct dcerpc_binding_handle *b;
8636 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8637 if (!NT_STATUS_IS_OK(status)) {
8638 return false;
8640 b = p->binding_handle;
8642 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8643 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8644 ctx->num_objects_large_dc);
8646 ret &= test_Connect(b, torture, &ctx->handle);
8648 ret &= test_EnumDomains(p, torture, ctx);
8650 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8652 return ret;
8655 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8656 struct dcerpc_pipe *p2,
8657 void *data)
8659 NTSTATUS status;
8660 struct dcerpc_pipe *p;
8661 bool ret = true;
8662 struct torture_samr_context *ctx =
8663 talloc_get_type_abort(data, struct torture_samr_context);
8664 struct dcerpc_binding_handle *b;
8666 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8667 if (!NT_STATUS_IS_OK(status)) {
8668 return false;
8670 b = p->binding_handle;
8672 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8673 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8674 ctx->num_objects_large_dc);
8676 ret &= test_Connect(b, torture, &ctx->handle);
8678 ret &= test_EnumDomains(p, torture, ctx);
8680 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8682 return ret;
8685 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8686 struct dcerpc_pipe *p2,
8687 void *data)
8689 NTSTATUS status;
8690 struct dcerpc_pipe *p;
8691 bool ret = true;
8692 struct torture_samr_context *ctx =
8693 talloc_get_type_abort(data, struct torture_samr_context);
8694 struct dcerpc_binding_handle *b;
8696 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8697 if (!NT_STATUS_IS_OK(status)) {
8698 return false;
8700 b = p->binding_handle;
8702 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8703 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8704 ctx->num_objects_large_dc);
8706 ret &= test_Connect(b, torture, &ctx->handle);
8708 ret &= test_EnumDomains(p, torture, ctx);
8710 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8712 return ret;
8715 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8717 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8718 struct torture_rpc_tcase *tcase;
8719 struct torture_samr_context *ctx;
8721 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8723 ctx = talloc_zero(suite, struct torture_samr_context);
8724 ctx->num_objects_large_dc = 150;
8726 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8727 torture_rpc_samr_many_aliases, ctx);
8728 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8729 torture_rpc_samr_many_groups, ctx);
8730 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8731 torture_rpc_samr_many_accounts, ctx);
8733 return suite;
8736 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8737 struct dcerpc_pipe *p2,
8738 struct cli_credentials *machine_credentials)
8740 NTSTATUS status;
8741 struct dcerpc_pipe *p;
8742 bool ret = true;
8743 struct torture_samr_context *ctx;
8744 struct dcerpc_binding_handle *b;
8746 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8747 if (!NT_STATUS_IS_OK(status)) {
8748 return false;
8750 b = p->binding_handle;
8752 ctx = talloc_zero(torture, struct torture_samr_context);
8754 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8755 ctx->machine_credentials = machine_credentials;
8757 ret &= test_Connect(b, torture, &ctx->handle);
8759 ret &= test_EnumDomains(p, torture, ctx);
8761 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8763 return ret;
8766 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8768 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8769 struct torture_rpc_tcase *tcase;
8771 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8772 &ndr_table_samr,
8773 TEST_ACCOUNT_NAME_PWD);
8775 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8776 torture_rpc_samr_badpwdcount);
8778 return suite;
8781 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8782 struct dcerpc_pipe *p2,
8783 struct cli_credentials *machine_credentials)
8785 NTSTATUS status;
8786 struct dcerpc_pipe *p;
8787 bool ret = true;
8788 struct torture_samr_context *ctx;
8789 struct dcerpc_binding_handle *b;
8791 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8792 if (!NT_STATUS_IS_OK(status)) {
8793 return false;
8795 b = p->binding_handle;
8797 ctx = talloc_zero(torture, struct torture_samr_context);
8799 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8800 ctx->machine_credentials = machine_credentials;
8802 ret &= test_Connect(b, torture, &ctx->handle);
8804 ret &= test_EnumDomains(p, torture, ctx);
8806 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8808 return ret;
8811 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8813 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8814 struct torture_rpc_tcase *tcase;
8816 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8817 &ndr_table_samr,
8818 TEST_ACCOUNT_NAME_PWD);
8820 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8821 torture_rpc_samr_lockout);
8823 return suite;
8826 struct torture_suite *torture_rpc_samr_passwords_validate(TALLOC_CTX *mem_ctx)
8828 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.validate");
8829 struct torture_rpc_tcase *tcase;
8831 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
8832 &ndr_table_samr);
8833 torture_rpc_tcase_add_test(tcase, "validate",
8834 test_samr_ValidatePassword);
8836 return suite;