s4:torture/rpc: use generate_random_password()
[Samba/nascimento.git] / source4 / torture / rpc / samr.c
blob92a255e0fb8bd9220de2bbef072da5b9efda2bc4
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for samr rpc operations
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7 Copyright (C) Guenther Deschner 2008-2010
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include "system/time.h"
26 #include "librpc/gen_ndr/lsa.h"
27 #include "librpc/gen_ndr/ndr_netlogon.h"
28 #include "librpc/gen_ndr/ndr_netlogon_c.h"
29 #include "librpc/gen_ndr/ndr_samr_c.h"
30 #include "librpc/gen_ndr/ndr_lsa_c.h"
31 #include "../lib/crypto/crypto.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "libcli/security/security.h"
34 #include "torture/rpc/rpc.h"
35 #include "param/param.h"
36 #include "auth/gensec/gensec.h"
37 #include "auth/gensec/gensec_proto.h"
38 #include "../libcli/auth/schannel.h"
40 #include <unistd.h>
42 #define TEST_ACCOUNT_NAME "samrtorturetest"
43 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
44 #define TEST_ALIASNAME "samrtorturetestalias"
45 #define TEST_GROUPNAME "samrtorturetestgroup"
46 #define TEST_MACHINENAME "samrtestmach$"
47 #define TEST_DOMAINNAME "samrtestdom$"
49 enum torture_samr_choice {
50 TORTURE_SAMR_PASSWORDS,
51 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
52 TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
53 TORTURE_SAMR_PASSWORDS_LOCKOUT,
54 TORTURE_SAMR_USER_ATTRIBUTES,
55 TORTURE_SAMR_USER_PRIVILEGES,
56 TORTURE_SAMR_OTHER,
57 TORTURE_SAMR_MANY_ACCOUNTS,
58 TORTURE_SAMR_MANY_GROUPS,
59 TORTURE_SAMR_MANY_ALIASES
62 struct torture_samr_context {
63 struct policy_handle handle;
64 struct cli_credentials *machine_credentials;
65 enum torture_samr_choice choice;
66 uint32_t num_objects_large_dc;
69 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
70 struct torture_context *tctx,
71 struct policy_handle *handle);
73 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
74 struct torture_context *tctx,
75 struct policy_handle *handle);
77 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
78 struct torture_context *tctx,
79 struct policy_handle *handle);
81 static bool test_ChangePassword(struct dcerpc_pipe *p,
82 struct torture_context *tctx,
83 const char *acct_name,
84 struct policy_handle *domain_handle, char **password);
86 static void init_lsa_String(struct lsa_String *string, const char *s)
88 string->string = s;
91 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
93 string->string = s;
96 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
98 string->length = length;
99 string->size = length;
100 string->array = (uint16_t *)discard_const(s);
103 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
104 struct policy_handle *handle)
106 NTSTATUS status;
107 struct samr_Close r;
109 r.in.handle = handle;
110 r.out.handle = handle;
112 status = dcerpc_samr_Close(p, tctx, &r);
113 torture_assert_ntstatus_ok(tctx, status, "Close");
115 return true;
118 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
119 struct policy_handle *handle)
121 NTSTATUS status;
122 struct samr_Shutdown r;
124 if (!torture_setting_bool(tctx, "dangerous", false)) {
125 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
126 return true;
129 r.in.connect_handle = handle;
131 torture_comment(tctx, "testing samr_Shutdown\n");
133 status = dcerpc_samr_Shutdown(p, tctx, &r);
134 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
136 return true;
139 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
140 struct policy_handle *handle)
142 NTSTATUS status;
143 struct samr_SetDsrmPassword r;
144 struct lsa_String string;
145 struct samr_Password hash;
147 if (!torture_setting_bool(tctx, "dangerous", false)) {
148 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
151 E_md4hash("TeSTDSRM123", hash.hash);
153 init_lsa_String(&string, "Administrator");
155 r.in.name = &string;
156 r.in.unknown = 0;
157 r.in.hash = &hash;
159 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
161 status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
162 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
164 return true;
168 static bool test_QuerySecurity(struct dcerpc_pipe *p,
169 struct torture_context *tctx,
170 struct policy_handle *handle)
172 NTSTATUS status;
173 struct samr_QuerySecurity r;
174 struct samr_SetSecurity s;
175 struct sec_desc_buf *sdbuf = NULL;
177 r.in.handle = handle;
178 r.in.sec_info = 7;
179 r.out.sdbuf = &sdbuf;
181 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
182 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
184 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
186 s.in.handle = handle;
187 s.in.sec_info = 7;
188 s.in.sdbuf = sdbuf;
190 if (torture_setting_bool(tctx, "samba4", false)) {
191 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
194 status = dcerpc_samr_SetSecurity(p, tctx, &s);
195 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
197 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
198 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
200 return true;
204 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
205 struct policy_handle *handle, uint32_t base_acct_flags,
206 const char *base_account_name)
208 NTSTATUS status;
209 struct samr_SetUserInfo s;
210 struct samr_SetUserInfo2 s2;
211 struct samr_QueryUserInfo q;
212 struct samr_QueryUserInfo q0;
213 union samr_UserInfo u;
214 union samr_UserInfo *info;
215 bool ret = true;
216 const char *test_account_name;
218 uint32_t user_extra_flags = 0;
220 if (!torture_setting_bool(tctx, "samba3", false)) {
221 if (base_acct_flags == ACB_NORMAL) {
222 /* When created, accounts are expired by default */
223 user_extra_flags = ACB_PW_EXPIRED;
227 s.in.user_handle = handle;
228 s.in.info = &u;
230 s2.in.user_handle = handle;
231 s2.in.info = &u;
233 q.in.user_handle = handle;
234 q.out.info = &info;
235 q0 = q;
237 #define TESTCALL(call, r) \
238 status = dcerpc_samr_ ##call(p, tctx, &r); \
239 if (!NT_STATUS_IS_OK(status)) { \
240 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
241 r.in.level, nt_errstr(status), __location__); \
242 ret = false; \
243 break; \
246 #define STRING_EQUAL(s1, s2, field) \
247 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
248 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
249 #field, s2, __location__); \
250 ret = false; \
251 break; \
254 #define MEM_EQUAL(s1, s2, length, field) \
255 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
256 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
257 #field, (const char *)s2, __location__); \
258 ret = false; \
259 break; \
262 #define INT_EQUAL(i1, i2, field) \
263 if (i1 != i2) { \
264 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
265 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
266 ret = false; \
267 break; \
270 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
271 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
272 q.in.level = lvl1; \
273 TESTCALL(QueryUserInfo, q) \
274 s.in.level = lvl1; \
275 s2.in.level = lvl1; \
276 u = *info; \
277 if (lvl1 == 21) { \
278 ZERO_STRUCT(u.info21); \
279 u.info21.fields_present = fpval; \
281 init_lsa_String(&u.info ## lvl1.field1, value); \
282 TESTCALL(SetUserInfo, s) \
283 TESTCALL(SetUserInfo2, s2) \
284 init_lsa_String(&u.info ## lvl1.field1, ""); \
285 TESTCALL(QueryUserInfo, q); \
286 u = *info; \
287 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
288 q.in.level = lvl2; \
289 TESTCALL(QueryUserInfo, q) \
290 u = *info; \
291 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
292 } while (0)
294 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
295 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
296 q.in.level = lvl1; \
297 TESTCALL(QueryUserInfo, q) \
298 s.in.level = lvl1; \
299 s2.in.level = lvl1; \
300 u = *info; \
301 if (lvl1 == 21) { \
302 ZERO_STRUCT(u.info21); \
303 u.info21.fields_present = fpval; \
305 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
306 TESTCALL(SetUserInfo, s) \
307 TESTCALL(SetUserInfo2, s2) \
308 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
309 TESTCALL(QueryUserInfo, q); \
310 u = *info; \
311 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
312 q.in.level = lvl2; \
313 TESTCALL(QueryUserInfo, q) \
314 u = *info; \
315 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
316 } while (0)
318 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
319 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
320 q.in.level = lvl1; \
321 TESTCALL(QueryUserInfo, q) \
322 s.in.level = lvl1; \
323 s2.in.level = lvl1; \
324 u = *info; \
325 if (lvl1 == 21) { \
326 uint8_t *bits = u.info21.logon_hours.bits; \
327 ZERO_STRUCT(u.info21); \
328 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
329 u.info21.logon_hours.units_per_week = 168; \
330 u.info21.logon_hours.bits = bits; \
332 u.info21.fields_present = fpval; \
334 u.info ## lvl1.field1 = value; \
335 TESTCALL(SetUserInfo, s) \
336 TESTCALL(SetUserInfo2, s2) \
337 u.info ## lvl1.field1 = 0; \
338 TESTCALL(QueryUserInfo, q); \
339 u = *info; \
340 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
341 q.in.level = lvl2; \
342 TESTCALL(QueryUserInfo, q) \
343 u = *info; \
344 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
345 } while (0)
347 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
348 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
349 } while (0)
351 q0.in.level = 12;
352 do { TESTCALL(QueryUserInfo, q0) } while (0);
354 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
355 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
356 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
357 SAMR_FIELD_COMMENT);
359 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
360 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
361 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
362 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
363 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
364 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
365 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
366 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
367 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
368 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
369 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
370 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
371 test_account_name = base_account_name;
372 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
373 SAMR_FIELD_ACCOUNT_NAME);
375 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
376 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
377 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
378 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
379 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
380 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
381 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
382 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
383 SAMR_FIELD_FULL_NAME);
385 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
386 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
387 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
388 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
389 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
390 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
391 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
392 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
393 SAMR_FIELD_FULL_NAME);
395 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
396 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
397 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
398 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
399 SAMR_FIELD_LOGON_SCRIPT);
401 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
402 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
403 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
404 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
405 SAMR_FIELD_PROFILE_PATH);
407 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
408 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
409 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
410 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
411 SAMR_FIELD_HOME_DIRECTORY);
412 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
413 SAMR_FIELD_HOME_DIRECTORY);
415 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
416 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
417 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
418 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
419 SAMR_FIELD_HOME_DRIVE);
420 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
421 SAMR_FIELD_HOME_DRIVE);
423 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
424 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
425 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
426 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
427 SAMR_FIELD_DESCRIPTION);
429 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
430 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
431 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
432 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
433 SAMR_FIELD_WORKSTATIONS);
434 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
435 SAMR_FIELD_WORKSTATIONS);
436 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
437 SAMR_FIELD_WORKSTATIONS);
438 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
439 SAMR_FIELD_WORKSTATIONS);
441 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
442 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
443 SAMR_FIELD_PARAMETERS);
444 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
445 SAMR_FIELD_PARAMETERS);
446 /* also empty user parameters are allowed */
447 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
448 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
449 SAMR_FIELD_PARAMETERS);
450 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
451 SAMR_FIELD_PARAMETERS);
453 /* Samba 3 cannot store country_code and copy_page atm. - gd */
454 if (!torture_setting_bool(tctx, "samba3", false)) {
455 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
456 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
457 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
458 SAMR_FIELD_COUNTRY_CODE);
459 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
460 SAMR_FIELD_COUNTRY_CODE);
462 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
463 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
464 SAMR_FIELD_CODE_PAGE);
465 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
466 SAMR_FIELD_CODE_PAGE);
469 if (!torture_setting_bool(tctx, "samba3", false)) {
470 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
471 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
472 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
473 SAMR_FIELD_ACCT_EXPIRY);
474 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
475 SAMR_FIELD_ACCT_EXPIRY);
476 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
477 SAMR_FIELD_ACCT_EXPIRY);
478 } else {
479 /* Samba 3 can only store seconds / time_t in passdb - gd */
480 NTTIME nt;
481 unix_to_nt_time(&nt, time(NULL) + __LINE__);
482 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
483 unix_to_nt_time(&nt, time(NULL) + __LINE__);
484 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
485 unix_to_nt_time(&nt, time(NULL) + __LINE__);
486 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
487 unix_to_nt_time(&nt, time(NULL) + __LINE__);
488 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
489 unix_to_nt_time(&nt, time(NULL) + __LINE__);
490 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
493 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
494 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
495 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
496 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
497 SAMR_FIELD_LOGON_HOURS);
499 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
500 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
501 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
503 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
504 (base_acct_flags | ACB_DISABLED),
505 (base_acct_flags | ACB_DISABLED | user_extra_flags),
508 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
509 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
510 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
511 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
513 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
514 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
515 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
519 /* The 'autolock' flag doesn't stick - check this */
520 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
521 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
522 (base_acct_flags | ACB_DISABLED | user_extra_flags),
524 #if 0
525 /* Removing the 'disabled' flag doesn't stick - check this */
526 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
527 (base_acct_flags),
528 (base_acct_flags | ACB_DISABLED | user_extra_flags),
530 #endif
532 /* Samba3 cannot store these atm */
533 if (!torture_setting_bool(tctx, "samba3", false)) {
534 /* The 'store plaintext' flag does stick */
535 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
536 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
537 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
539 /* The 'use DES' flag does stick */
540 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
541 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
542 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
544 /* The 'don't require kerberos pre-authentication flag does stick */
545 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
546 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
547 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
549 /* The 'no kerberos PAC required' flag sticks */
550 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
551 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
552 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
555 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
556 (base_acct_flags | ACB_DISABLED),
557 (base_acct_flags | ACB_DISABLED | user_extra_flags),
558 SAMR_FIELD_ACCT_FLAGS);
560 #if 0
561 /* these fail with win2003 - it appears you can't set the primary gid?
562 the set succeeds, but the gid isn't changed. Very weird! */
563 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
564 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
565 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
566 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
567 #endif
569 return ret;
573 generate a random password for password change tests
575 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
577 size_t len = MAX(8, min_len);
578 char *s = generate_random_password(mem_ctx, len, len+6);
579 return s;
582 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
584 char *s = samr_rand_pass_silent(mem_ctx, min_len);
585 printf("Generated password '%s'\n", s);
586 return s;
591 generate a random password for password change tests
593 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
595 int i;
596 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
597 generate_random_buffer(password.data, password.length);
599 for (i=0; i < len; i++) {
600 if (((uint16_t *)password.data)[i] == 0) {
601 ((uint16_t *)password.data)[i] = 1;
605 return password;
609 generate a random password for password change tests (fixed length)
611 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
613 char *s = generate_random_password(mem_ctx, len, len);
614 printf("Generated password '%s'\n", s);
615 return s;
618 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
619 struct policy_handle *handle, char **password)
621 NTSTATUS status;
622 struct samr_SetUserInfo s;
623 union samr_UserInfo u;
624 bool ret = true;
625 DATA_BLOB session_key;
626 char *newpass;
627 struct samr_GetUserPwInfo pwp;
628 struct samr_PwInfo info;
629 int policy_min_pw_len = 0;
630 pwp.in.user_handle = handle;
631 pwp.out.info = &info;
633 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
634 if (NT_STATUS_IS_OK(status)) {
635 policy_min_pw_len = pwp.out.info->min_password_length;
637 newpass = samr_rand_pass(tctx, policy_min_pw_len);
639 s.in.user_handle = handle;
640 s.in.info = &u;
641 s.in.level = 24;
643 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
644 u.info24.password_expired = 0;
646 status = dcerpc_fetch_session_key(p, &session_key);
647 if (!NT_STATUS_IS_OK(status)) {
648 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
649 s.in.level, nt_errstr(status));
650 return false;
653 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
655 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
657 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
658 if (!NT_STATUS_IS_OK(status)) {
659 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
660 s.in.level, nt_errstr(status));
661 ret = false;
662 } else {
663 *password = newpass;
666 return ret;
670 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
671 struct policy_handle *handle, uint32_t fields_present,
672 char **password)
674 NTSTATUS status;
675 struct samr_SetUserInfo s;
676 union samr_UserInfo u;
677 bool ret = true;
678 DATA_BLOB session_key;
679 char *newpass;
680 struct samr_GetUserPwInfo pwp;
681 struct samr_PwInfo info;
682 int policy_min_pw_len = 0;
683 pwp.in.user_handle = handle;
684 pwp.out.info = &info;
686 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
687 if (NT_STATUS_IS_OK(status)) {
688 policy_min_pw_len = pwp.out.info->min_password_length;
690 newpass = samr_rand_pass(tctx, policy_min_pw_len);
692 s.in.user_handle = handle;
693 s.in.info = &u;
694 s.in.level = 23;
696 ZERO_STRUCT(u);
698 u.info23.info.fields_present = fields_present;
700 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
702 status = dcerpc_fetch_session_key(p, &session_key);
703 if (!NT_STATUS_IS_OK(status)) {
704 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
705 s.in.level, nt_errstr(status));
706 return false;
709 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
711 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
713 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
714 if (!NT_STATUS_IS_OK(status)) {
715 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
716 s.in.level, nt_errstr(status));
717 ret = false;
718 } else {
719 *password = newpass;
722 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
724 status = dcerpc_fetch_session_key(p, &session_key);
725 if (!NT_STATUS_IS_OK(status)) {
726 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
727 s.in.level, nt_errstr(status));
728 return false;
731 /* This should break the key nicely */
732 session_key.length--;
733 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
735 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
737 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
738 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
739 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
740 s.in.level, nt_errstr(status));
741 ret = false;
744 return ret;
748 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
749 struct policy_handle *handle, bool makeshort,
750 char **password)
752 NTSTATUS status;
753 struct samr_SetUserInfo s;
754 union samr_UserInfo u;
755 bool ret = true;
756 DATA_BLOB session_key;
757 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
758 uint8_t confounder[16];
759 char *newpass;
760 struct MD5Context ctx;
761 struct samr_GetUserPwInfo pwp;
762 struct samr_PwInfo info;
763 int policy_min_pw_len = 0;
764 pwp.in.user_handle = handle;
765 pwp.out.info = &info;
767 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
768 if (NT_STATUS_IS_OK(status)) {
769 policy_min_pw_len = pwp.out.info->min_password_length;
771 if (makeshort && policy_min_pw_len) {
772 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
773 } else {
774 newpass = samr_rand_pass(tctx, policy_min_pw_len);
777 s.in.user_handle = handle;
778 s.in.info = &u;
779 s.in.level = 26;
781 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
782 u.info26.password_expired = 0;
784 status = dcerpc_fetch_session_key(p, &session_key);
785 if (!NT_STATUS_IS_OK(status)) {
786 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
787 s.in.level, nt_errstr(status));
788 return false;
791 generate_random_buffer((uint8_t *)confounder, 16);
793 MD5Init(&ctx);
794 MD5Update(&ctx, confounder, 16);
795 MD5Update(&ctx, session_key.data, session_key.length);
796 MD5Final(confounded_session_key.data, &ctx);
798 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
799 memcpy(&u.info26.password.data[516], confounder, 16);
801 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
803 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
804 if (!NT_STATUS_IS_OK(status)) {
805 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
806 s.in.level, nt_errstr(status));
807 ret = false;
808 } else {
809 *password = newpass;
812 /* This should break the key nicely */
813 confounded_session_key.data[0]++;
815 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
816 memcpy(&u.info26.password.data[516], confounder, 16);
818 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
820 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
821 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
822 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
823 s.in.level, nt_errstr(status));
824 ret = false;
825 } else {
826 *password = newpass;
829 return ret;
832 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
833 struct policy_handle *handle, uint32_t fields_present,
834 char **password)
836 NTSTATUS status;
837 struct samr_SetUserInfo s;
838 union samr_UserInfo u;
839 bool ret = true;
840 DATA_BLOB session_key;
841 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
842 struct MD5Context ctx;
843 uint8_t confounder[16];
844 char *newpass;
845 struct samr_GetUserPwInfo pwp;
846 struct samr_PwInfo info;
847 int policy_min_pw_len = 0;
848 pwp.in.user_handle = handle;
849 pwp.out.info = &info;
851 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
852 if (NT_STATUS_IS_OK(status)) {
853 policy_min_pw_len = pwp.out.info->min_password_length;
855 newpass = samr_rand_pass(tctx, policy_min_pw_len);
857 s.in.user_handle = handle;
858 s.in.info = &u;
859 s.in.level = 25;
861 ZERO_STRUCT(u);
863 u.info25.info.fields_present = fields_present;
865 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
867 status = dcerpc_fetch_session_key(p, &session_key);
868 if (!NT_STATUS_IS_OK(status)) {
869 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
870 s.in.level, nt_errstr(status));
871 return false;
874 generate_random_buffer((uint8_t *)confounder, 16);
876 MD5Init(&ctx);
877 MD5Update(&ctx, confounder, 16);
878 MD5Update(&ctx, session_key.data, session_key.length);
879 MD5Final(confounded_session_key.data, &ctx);
881 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
882 memcpy(&u.info25.password.data[516], confounder, 16);
884 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
886 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
887 if (!NT_STATUS_IS_OK(status)) {
888 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
889 s.in.level, nt_errstr(status));
890 ret = false;
891 } else {
892 *password = newpass;
895 /* This should break the key nicely */
896 confounded_session_key.data[0]++;
898 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
899 memcpy(&u.info25.password.data[516], confounder, 16);
901 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
903 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
904 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
905 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
906 s.in.level, nt_errstr(status));
907 ret = false;
910 return ret;
913 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
914 struct policy_handle *handle, char **password)
916 NTSTATUS status;
917 struct samr_SetUserInfo s;
918 union samr_UserInfo u;
919 bool ret = true;
920 DATA_BLOB session_key;
921 char *newpass;
922 struct samr_GetUserPwInfo pwp;
923 struct samr_PwInfo info;
924 int policy_min_pw_len = 0;
925 uint8_t lm_hash[16], nt_hash[16];
927 pwp.in.user_handle = handle;
928 pwp.out.info = &info;
930 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
931 if (NT_STATUS_IS_OK(status)) {
932 policy_min_pw_len = pwp.out.info->min_password_length;
934 newpass = samr_rand_pass(tctx, policy_min_pw_len);
936 s.in.user_handle = handle;
937 s.in.info = &u;
938 s.in.level = 18;
940 ZERO_STRUCT(u);
942 u.info18.nt_pwd_active = true;
943 u.info18.lm_pwd_active = true;
945 E_md4hash(newpass, nt_hash);
946 E_deshash(newpass, lm_hash);
948 status = dcerpc_fetch_session_key(p, &session_key);
949 if (!NT_STATUS_IS_OK(status)) {
950 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
951 s.in.level, nt_errstr(status));
952 return false;
956 DATA_BLOB in,out;
957 in = data_blob_const(nt_hash, 16);
958 out = data_blob_talloc_zero(tctx, 16);
959 sess_crypt_blob(&out, &in, &session_key, true);
960 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
963 DATA_BLOB in,out;
964 in = data_blob_const(lm_hash, 16);
965 out = data_blob_talloc_zero(tctx, 16);
966 sess_crypt_blob(&out, &in, &session_key, true);
967 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
970 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
972 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
973 if (!NT_STATUS_IS_OK(status)) {
974 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
975 s.in.level, nt_errstr(status));
976 ret = false;
977 } else {
978 *password = newpass;
981 return ret;
984 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
985 struct policy_handle *handle, uint32_t fields_present,
986 char **password)
988 NTSTATUS status;
989 struct samr_SetUserInfo s;
990 union samr_UserInfo u;
991 bool ret = true;
992 DATA_BLOB session_key;
993 char *newpass;
994 struct samr_GetUserPwInfo pwp;
995 struct samr_PwInfo info;
996 int policy_min_pw_len = 0;
997 uint8_t lm_hash[16], nt_hash[16];
999 pwp.in.user_handle = handle;
1000 pwp.out.info = &info;
1002 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1003 if (NT_STATUS_IS_OK(status)) {
1004 policy_min_pw_len = pwp.out.info->min_password_length;
1006 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1008 s.in.user_handle = handle;
1009 s.in.info = &u;
1010 s.in.level = 21;
1012 E_md4hash(newpass, nt_hash);
1013 E_deshash(newpass, lm_hash);
1015 ZERO_STRUCT(u);
1017 u.info21.fields_present = fields_present;
1019 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1020 u.info21.lm_owf_password.length = 16;
1021 u.info21.lm_owf_password.size = 16;
1022 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1023 u.info21.lm_password_set = true;
1026 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1027 u.info21.nt_owf_password.length = 16;
1028 u.info21.nt_owf_password.size = 16;
1029 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1030 u.info21.nt_password_set = true;
1033 status = dcerpc_fetch_session_key(p, &session_key);
1034 if (!NT_STATUS_IS_OK(status)) {
1035 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1036 s.in.level, nt_errstr(status));
1037 return false;
1040 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1041 DATA_BLOB in,out;
1042 in = data_blob_const(u.info21.lm_owf_password.array,
1043 u.info21.lm_owf_password.length);
1044 out = data_blob_talloc_zero(tctx, 16);
1045 sess_crypt_blob(&out, &in, &session_key, true);
1046 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1049 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1050 DATA_BLOB in,out;
1051 in = data_blob_const(u.info21.nt_owf_password.array,
1052 u.info21.nt_owf_password.length);
1053 out = data_blob_talloc_zero(tctx, 16);
1054 sess_crypt_blob(&out, &in, &session_key, true);
1055 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1058 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1060 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1063 s.in.level, nt_errstr(status));
1064 ret = false;
1065 } else {
1066 *password = newpass;
1069 /* try invalid length */
1070 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1072 u.info21.nt_owf_password.length++;
1074 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1076 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1077 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1078 s.in.level, nt_errstr(status));
1079 ret = false;
1083 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1085 u.info21.lm_owf_password.length++;
1087 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1089 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1090 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1091 s.in.level, nt_errstr(status));
1092 ret = false;
1096 return ret;
1099 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1100 struct torture_context *tctx,
1101 struct policy_handle *handle,
1102 uint16_t level,
1103 uint32_t fields_present,
1104 char **password, uint8_t password_expired,
1105 bool use_setinfo2,
1106 bool *matched_expected_error)
1108 NTSTATUS status;
1109 NTSTATUS expected_error = NT_STATUS_OK;
1110 struct samr_SetUserInfo s;
1111 struct samr_SetUserInfo2 s2;
1112 union samr_UserInfo u;
1113 bool ret = true;
1114 DATA_BLOB session_key;
1115 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1116 struct MD5Context ctx;
1117 uint8_t confounder[16];
1118 char *newpass;
1119 struct samr_GetUserPwInfo pwp;
1120 struct samr_PwInfo info;
1121 int policy_min_pw_len = 0;
1122 const char *comment = NULL;
1123 uint8_t lm_hash[16], nt_hash[16];
1125 pwp.in.user_handle = handle;
1126 pwp.out.info = &info;
1128 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1129 if (NT_STATUS_IS_OK(status)) {
1130 policy_min_pw_len = pwp.out.info->min_password_length;
1132 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1134 if (use_setinfo2) {
1135 s2.in.user_handle = handle;
1136 s2.in.info = &u;
1137 s2.in.level = level;
1138 } else {
1139 s.in.user_handle = handle;
1140 s.in.info = &u;
1141 s.in.level = level;
1144 if (fields_present & SAMR_FIELD_COMMENT) {
1145 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1148 ZERO_STRUCT(u);
1150 switch (level) {
1151 case 18:
1152 E_md4hash(newpass, nt_hash);
1153 E_deshash(newpass, lm_hash);
1155 u.info18.nt_pwd_active = true;
1156 u.info18.lm_pwd_active = true;
1157 u.info18.password_expired = password_expired;
1159 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1160 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1162 break;
1163 case 21:
1164 E_md4hash(newpass, nt_hash);
1165 E_deshash(newpass, lm_hash);
1167 u.info21.fields_present = fields_present;
1168 u.info21.password_expired = password_expired;
1169 u.info21.comment.string = comment;
1171 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1172 u.info21.lm_owf_password.length = 16;
1173 u.info21.lm_owf_password.size = 16;
1174 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1175 u.info21.lm_password_set = true;
1178 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1179 u.info21.nt_owf_password.length = 16;
1180 u.info21.nt_owf_password.size = 16;
1181 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1182 u.info21.nt_password_set = true;
1185 break;
1186 case 23:
1187 u.info23.info.fields_present = fields_present;
1188 u.info23.info.password_expired = password_expired;
1189 u.info23.info.comment.string = comment;
1191 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1193 break;
1194 case 24:
1195 u.info24.password_expired = password_expired;
1197 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1199 break;
1200 case 25:
1201 u.info25.info.fields_present = fields_present;
1202 u.info25.info.password_expired = password_expired;
1203 u.info25.info.comment.string = comment;
1205 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1207 break;
1208 case 26:
1209 u.info26.password_expired = password_expired;
1211 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1213 break;
1216 status = dcerpc_fetch_session_key(p, &session_key);
1217 if (!NT_STATUS_IS_OK(status)) {
1218 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1219 s.in.level, nt_errstr(status));
1220 return false;
1223 generate_random_buffer((uint8_t *)confounder, 16);
1225 MD5Init(&ctx);
1226 MD5Update(&ctx, confounder, 16);
1227 MD5Update(&ctx, session_key.data, session_key.length);
1228 MD5Final(confounded_session_key.data, &ctx);
1230 switch (level) {
1231 case 18:
1233 DATA_BLOB in,out;
1234 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1235 out = data_blob_talloc_zero(tctx, 16);
1236 sess_crypt_blob(&out, &in, &session_key, true);
1237 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1240 DATA_BLOB in,out;
1241 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1242 out = data_blob_talloc_zero(tctx, 16);
1243 sess_crypt_blob(&out, &in, &session_key, true);
1244 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1247 break;
1248 case 21:
1249 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1250 DATA_BLOB in,out;
1251 in = data_blob_const(u.info21.lm_owf_password.array,
1252 u.info21.lm_owf_password.length);
1253 out = data_blob_talloc_zero(tctx, 16);
1254 sess_crypt_blob(&out, &in, &session_key, true);
1255 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1257 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1258 DATA_BLOB in,out;
1259 in = data_blob_const(u.info21.nt_owf_password.array,
1260 u.info21.nt_owf_password.length);
1261 out = data_blob_talloc_zero(tctx, 16);
1262 sess_crypt_blob(&out, &in, &session_key, true);
1263 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1265 break;
1266 case 23:
1267 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1268 break;
1269 case 24:
1270 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1271 break;
1272 case 25:
1273 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1274 memcpy(&u.info25.password.data[516], confounder, 16);
1275 break;
1276 case 26:
1277 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1278 memcpy(&u.info26.password.data[516], confounder, 16);
1279 break;
1282 if (use_setinfo2) {
1283 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1284 } else {
1285 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1288 if (!NT_STATUS_IS_OK(status)) {
1289 if (fields_present == 0) {
1290 expected_error = NT_STATUS_INVALID_PARAMETER;
1292 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1293 expected_error = NT_STATUS_ACCESS_DENIED;
1297 if (!NT_STATUS_IS_OK(expected_error)) {
1298 if (use_setinfo2) {
1299 torture_assert_ntstatus_equal(tctx,
1300 s2.out.result,
1301 expected_error, "SetUserInfo2 failed");
1302 } else {
1303 torture_assert_ntstatus_equal(tctx,
1304 s.out.result,
1305 expected_error, "SetUserInfo failed");
1307 *matched_expected_error = true;
1308 return true;
1311 if (!NT_STATUS_IS_OK(status)) {
1312 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1313 use_setinfo2 ? "2":"", level, nt_errstr(status));
1314 ret = false;
1315 } else {
1316 *password = newpass;
1319 return ret;
1322 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1323 struct policy_handle *handle)
1325 NTSTATUS status;
1326 struct samr_SetAliasInfo r;
1327 struct samr_QueryAliasInfo q;
1328 union samr_AliasInfo *info;
1329 uint16_t levels[] = {2, 3};
1330 int i;
1331 bool ret = true;
1333 /* Ignoring switch level 1, as that includes the number of members for the alias
1334 * and setting this to a wrong value might have negative consequences
1337 for (i=0;i<ARRAY_SIZE(levels);i++) {
1338 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1340 r.in.alias_handle = handle;
1341 r.in.level = levels[i];
1342 r.in.info = talloc(tctx, union samr_AliasInfo);
1343 switch (r.in.level) {
1344 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1345 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1346 "Test Description, should test I18N as well"); break;
1347 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1350 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1353 levels[i], nt_errstr(status));
1354 ret = false;
1357 q.in.alias_handle = handle;
1358 q.in.level = levels[i];
1359 q.out.info = &info;
1361 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1362 if (!NT_STATUS_IS_OK(status)) {
1363 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1364 levels[i], nt_errstr(status));
1365 ret = false;
1369 return ret;
1372 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1373 struct policy_handle *user_handle)
1375 struct samr_GetGroupsForUser r;
1376 struct samr_RidWithAttributeArray *rids = NULL;
1377 NTSTATUS status;
1379 torture_comment(tctx, "testing GetGroupsForUser\n");
1381 r.in.user_handle = user_handle;
1382 r.out.rids = &rids;
1384 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1385 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1387 return true;
1391 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1392 struct lsa_String *domain_name)
1394 NTSTATUS status;
1395 struct samr_GetDomPwInfo r;
1396 struct samr_PwInfo info;
1398 r.in.domain_name = domain_name;
1399 r.out.info = &info;
1401 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1403 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1404 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1406 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1407 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1409 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1410 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1412 r.in.domain_name->string = "\\\\__NONAME__";
1413 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1415 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1416 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1418 r.in.domain_name->string = "\\\\Builtin";
1419 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1421 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1422 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1424 return true;
1427 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1428 struct policy_handle *handle)
1430 NTSTATUS status;
1431 struct samr_GetUserPwInfo r;
1432 struct samr_PwInfo info;
1434 torture_comment(tctx, "Testing GetUserPwInfo\n");
1436 r.in.user_handle = handle;
1437 r.out.info = &info;
1439 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1440 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1442 return true;
1445 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1446 struct policy_handle *domain_handle, const char *name,
1447 uint32_t *rid)
1449 NTSTATUS status;
1450 struct samr_LookupNames n;
1451 struct lsa_String sname[2];
1452 struct samr_Ids rids, types;
1454 init_lsa_String(&sname[0], name);
1456 n.in.domain_handle = domain_handle;
1457 n.in.num_names = 1;
1458 n.in.names = sname;
1459 n.out.rids = &rids;
1460 n.out.types = &types;
1461 status = dcerpc_samr_LookupNames(p, tctx, &n);
1462 if (NT_STATUS_IS_OK(status)) {
1463 *rid = n.out.rids->ids[0];
1464 } else {
1465 return status;
1468 init_lsa_String(&sname[1], "xxNONAMExx");
1469 n.in.num_names = 2;
1470 status = dcerpc_samr_LookupNames(p, tctx, &n);
1471 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1472 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(status));
1473 if (NT_STATUS_IS_OK(status)) {
1474 return NT_STATUS_UNSUCCESSFUL;
1476 return status;
1479 n.in.num_names = 0;
1480 status = dcerpc_samr_LookupNames(p, tctx, &n);
1481 if (!NT_STATUS_IS_OK(status)) {
1482 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1483 return status;
1486 init_lsa_String(&sname[0], "xxNONAMExx");
1487 n.in.num_names = 1;
1488 status = dcerpc_samr_LookupNames(p, tctx, &n);
1489 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1490 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1491 if (NT_STATUS_IS_OK(status)) {
1492 return NT_STATUS_UNSUCCESSFUL;
1494 return status;
1497 init_lsa_String(&sname[0], "xxNONAMExx");
1498 init_lsa_String(&sname[1], "xxNONAME2xx");
1499 n.in.num_names = 2;
1500 status = dcerpc_samr_LookupNames(p, tctx, &n);
1501 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1502 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1503 if (NT_STATUS_IS_OK(status)) {
1504 return NT_STATUS_UNSUCCESSFUL;
1506 return status;
1509 return NT_STATUS_OK;
1512 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
1513 struct torture_context *tctx,
1514 struct policy_handle *domain_handle,
1515 const char *name, struct policy_handle *user_handle)
1517 NTSTATUS status;
1518 struct samr_OpenUser r;
1519 uint32_t rid;
1521 status = test_LookupName(p, tctx, domain_handle, name, &rid);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 return status;
1526 r.in.domain_handle = domain_handle;
1527 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1528 r.in.rid = rid;
1529 r.out.user_handle = user_handle;
1530 status = dcerpc_samr_OpenUser(p, tctx, &r);
1531 if (!NT_STATUS_IS_OK(status)) {
1532 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1535 return status;
1538 #if 0
1539 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1540 struct torture_context *tctx,
1541 struct policy_handle *handle)
1543 NTSTATUS status;
1544 struct samr_ChangePasswordUser r;
1545 bool ret = true;
1546 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1547 struct policy_handle user_handle;
1548 char *oldpass = "test";
1549 char *newpass = "test2";
1550 uint8_t old_nt_hash[16], new_nt_hash[16];
1551 uint8_t old_lm_hash[16], new_lm_hash[16];
1553 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1554 if (!NT_STATUS_IS_OK(status)) {
1555 return false;
1558 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1560 torture_comment(tctx, "old password: %s\n", oldpass);
1561 torture_comment(tctx, "new password: %s\n", newpass);
1563 E_md4hash(oldpass, old_nt_hash);
1564 E_md4hash(newpass, new_nt_hash);
1565 E_deshash(oldpass, old_lm_hash);
1566 E_deshash(newpass, new_lm_hash);
1568 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1569 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1570 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1571 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1572 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1573 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1575 r.in.handle = &user_handle;
1576 r.in.lm_present = 1;
1577 r.in.old_lm_crypted = &hash1;
1578 r.in.new_lm_crypted = &hash2;
1579 r.in.nt_present = 1;
1580 r.in.old_nt_crypted = &hash3;
1581 r.in.new_nt_crypted = &hash4;
1582 r.in.cross1_present = 1;
1583 r.in.nt_cross = &hash5;
1584 r.in.cross2_present = 1;
1585 r.in.lm_cross = &hash6;
1587 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1588 if (!NT_STATUS_IS_OK(status)) {
1589 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
1590 ret = false;
1593 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1594 ret = false;
1597 return ret;
1599 #endif
1601 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1602 const char *acct_name,
1603 struct policy_handle *handle, char **password)
1605 NTSTATUS status;
1606 struct samr_ChangePasswordUser r;
1607 bool ret = true;
1608 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1609 struct policy_handle user_handle;
1610 char *oldpass;
1611 uint8_t old_nt_hash[16], new_nt_hash[16];
1612 uint8_t old_lm_hash[16], new_lm_hash[16];
1613 bool changed = true;
1615 char *newpass;
1616 struct samr_GetUserPwInfo pwp;
1617 struct samr_PwInfo info;
1618 int policy_min_pw_len = 0;
1620 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1621 if (!NT_STATUS_IS_OK(status)) {
1622 return false;
1624 pwp.in.user_handle = &user_handle;
1625 pwp.out.info = &info;
1627 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1628 if (NT_STATUS_IS_OK(status)) {
1629 policy_min_pw_len = pwp.out.info->min_password_length;
1631 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1633 torture_comment(tctx, "Testing ChangePasswordUser\n");
1635 torture_assert(tctx, *password != NULL,
1636 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1638 oldpass = *password;
1640 E_md4hash(oldpass, old_nt_hash);
1641 E_md4hash(newpass, new_nt_hash);
1642 E_deshash(oldpass, old_lm_hash);
1643 E_deshash(newpass, new_lm_hash);
1645 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1646 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1647 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1648 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1649 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1650 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1652 r.in.user_handle = &user_handle;
1653 r.in.lm_present = 1;
1654 /* Break the LM hash */
1655 hash1.hash[0]++;
1656 r.in.old_lm_crypted = &hash1;
1657 r.in.new_lm_crypted = &hash2;
1658 r.in.nt_present = 1;
1659 r.in.old_nt_crypted = &hash3;
1660 r.in.new_nt_crypted = &hash4;
1661 r.in.cross1_present = 1;
1662 r.in.nt_cross = &hash5;
1663 r.in.cross2_present = 1;
1664 r.in.lm_cross = &hash6;
1666 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1667 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1668 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1670 /* Unbreak the LM hash */
1671 hash1.hash[0]--;
1673 r.in.user_handle = &user_handle;
1674 r.in.lm_present = 1;
1675 r.in.old_lm_crypted = &hash1;
1676 r.in.new_lm_crypted = &hash2;
1677 /* Break the NT hash */
1678 hash3.hash[0]--;
1679 r.in.nt_present = 1;
1680 r.in.old_nt_crypted = &hash3;
1681 r.in.new_nt_crypted = &hash4;
1682 r.in.cross1_present = 1;
1683 r.in.nt_cross = &hash5;
1684 r.in.cross2_present = 1;
1685 r.in.lm_cross = &hash6;
1687 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1688 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1689 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1691 /* Unbreak the NT hash */
1692 hash3.hash[0]--;
1694 r.in.user_handle = &user_handle;
1695 r.in.lm_present = 1;
1696 r.in.old_lm_crypted = &hash1;
1697 r.in.new_lm_crypted = &hash2;
1698 r.in.nt_present = 1;
1699 r.in.old_nt_crypted = &hash3;
1700 r.in.new_nt_crypted = &hash4;
1701 r.in.cross1_present = 1;
1702 r.in.nt_cross = &hash5;
1703 r.in.cross2_present = 1;
1704 /* Break the LM cross */
1705 hash6.hash[0]++;
1706 r.in.lm_cross = &hash6;
1708 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1709 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1710 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1711 ret = false;
1714 /* Unbreak the LM cross */
1715 hash6.hash[0]--;
1717 r.in.user_handle = &user_handle;
1718 r.in.lm_present = 1;
1719 r.in.old_lm_crypted = &hash1;
1720 r.in.new_lm_crypted = &hash2;
1721 r.in.nt_present = 1;
1722 r.in.old_nt_crypted = &hash3;
1723 r.in.new_nt_crypted = &hash4;
1724 r.in.cross1_present = 1;
1725 /* Break the NT cross */
1726 hash5.hash[0]++;
1727 r.in.nt_cross = &hash5;
1728 r.in.cross2_present = 1;
1729 r.in.lm_cross = &hash6;
1731 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1732 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1733 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1734 ret = false;
1737 /* Unbreak the NT cross */
1738 hash5.hash[0]--;
1741 /* Reset the hashes to not broken values */
1742 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1743 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1744 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1745 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1746 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1747 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1749 r.in.user_handle = &user_handle;
1750 r.in.lm_present = 1;
1751 r.in.old_lm_crypted = &hash1;
1752 r.in.new_lm_crypted = &hash2;
1753 r.in.nt_present = 1;
1754 r.in.old_nt_crypted = &hash3;
1755 r.in.new_nt_crypted = &hash4;
1756 r.in.cross1_present = 1;
1757 r.in.nt_cross = &hash5;
1758 r.in.cross2_present = 0;
1759 r.in.lm_cross = NULL;
1761 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1762 if (NT_STATUS_IS_OK(status)) {
1763 changed = true;
1764 *password = newpass;
1765 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1766 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1767 ret = false;
1770 oldpass = newpass;
1771 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1773 E_md4hash(oldpass, old_nt_hash);
1774 E_md4hash(newpass, new_nt_hash);
1775 E_deshash(oldpass, old_lm_hash);
1776 E_deshash(newpass, new_lm_hash);
1779 /* Reset the hashes to not broken values */
1780 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1781 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1782 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1783 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1784 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1785 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1787 r.in.user_handle = &user_handle;
1788 r.in.lm_present = 1;
1789 r.in.old_lm_crypted = &hash1;
1790 r.in.new_lm_crypted = &hash2;
1791 r.in.nt_present = 1;
1792 r.in.old_nt_crypted = &hash3;
1793 r.in.new_nt_crypted = &hash4;
1794 r.in.cross1_present = 0;
1795 r.in.nt_cross = NULL;
1796 r.in.cross2_present = 1;
1797 r.in.lm_cross = &hash6;
1799 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1800 if (NT_STATUS_IS_OK(status)) {
1801 changed = true;
1802 *password = newpass;
1803 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1804 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1805 ret = false;
1808 oldpass = newpass;
1809 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1811 E_md4hash(oldpass, old_nt_hash);
1812 E_md4hash(newpass, new_nt_hash);
1813 E_deshash(oldpass, old_lm_hash);
1814 E_deshash(newpass, new_lm_hash);
1817 /* Reset the hashes to not broken values */
1818 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1819 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1820 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1821 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1822 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1823 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1825 r.in.user_handle = &user_handle;
1826 r.in.lm_present = 1;
1827 r.in.old_lm_crypted = &hash1;
1828 r.in.new_lm_crypted = &hash2;
1829 r.in.nt_present = 1;
1830 r.in.old_nt_crypted = &hash3;
1831 r.in.new_nt_crypted = &hash4;
1832 r.in.cross1_present = 1;
1833 r.in.nt_cross = &hash5;
1834 r.in.cross2_present = 1;
1835 r.in.lm_cross = &hash6;
1837 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1838 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1839 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1840 } else if (!NT_STATUS_IS_OK(status)) {
1841 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
1842 ret = false;
1843 } else {
1844 changed = true;
1845 *password = newpass;
1848 r.in.user_handle = &user_handle;
1849 r.in.lm_present = 1;
1850 r.in.old_lm_crypted = &hash1;
1851 r.in.new_lm_crypted = &hash2;
1852 r.in.nt_present = 1;
1853 r.in.old_nt_crypted = &hash3;
1854 r.in.new_nt_crypted = &hash4;
1855 r.in.cross1_present = 1;
1856 r.in.nt_cross = &hash5;
1857 r.in.cross2_present = 1;
1858 r.in.lm_cross = &hash6;
1860 if (changed) {
1861 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1862 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1863 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1864 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1865 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1866 ret = false;
1871 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1872 ret = false;
1875 return ret;
1879 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1880 const char *acct_name,
1881 struct policy_handle *handle, char **password)
1883 NTSTATUS status;
1884 struct samr_OemChangePasswordUser2 r;
1885 bool ret = true;
1886 struct samr_Password lm_verifier;
1887 struct samr_CryptPassword lm_pass;
1888 struct lsa_AsciiString server, account, account_bad;
1889 char *oldpass;
1890 char *newpass;
1891 uint8_t old_lm_hash[16], new_lm_hash[16];
1893 struct samr_GetDomPwInfo dom_pw_info;
1894 struct samr_PwInfo info;
1895 int policy_min_pw_len = 0;
1897 struct lsa_String domain_name;
1899 domain_name.string = "";
1900 dom_pw_info.in.domain_name = &domain_name;
1901 dom_pw_info.out.info = &info;
1903 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1905 torture_assert(tctx, *password != NULL,
1906 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1908 oldpass = *password;
1910 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1911 if (NT_STATUS_IS_OK(status)) {
1912 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1915 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1917 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1918 account.string = acct_name;
1920 E_deshash(oldpass, old_lm_hash);
1921 E_deshash(newpass, new_lm_hash);
1923 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1924 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1925 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1927 r.in.server = &server;
1928 r.in.account = &account;
1929 r.in.password = &lm_pass;
1930 r.in.hash = &lm_verifier;
1932 /* Break the verification */
1933 lm_verifier.hash[0]++;
1935 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1937 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1938 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1939 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1940 nt_errstr(status));
1941 ret = false;
1944 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1945 /* Break the old password */
1946 old_lm_hash[0]++;
1947 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1948 /* unbreak it for the next operation */
1949 old_lm_hash[0]--;
1950 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1952 r.in.server = &server;
1953 r.in.account = &account;
1954 r.in.password = &lm_pass;
1955 r.in.hash = &lm_verifier;
1957 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1959 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1960 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1961 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1962 nt_errstr(status));
1963 ret = false;
1966 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1967 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1969 r.in.server = &server;
1970 r.in.account = &account;
1971 r.in.password = &lm_pass;
1972 r.in.hash = NULL;
1974 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1976 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1977 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1978 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1979 nt_errstr(status));
1980 ret = false;
1983 /* This shouldn't be a valid name */
1984 account_bad.string = TEST_ACCOUNT_NAME "XX";
1985 r.in.account = &account_bad;
1987 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1989 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1990 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1991 nt_errstr(status));
1992 ret = false;
1995 /* This shouldn't be a valid name */
1996 account_bad.string = TEST_ACCOUNT_NAME "XX";
1997 r.in.account = &account_bad;
1998 r.in.password = &lm_pass;
1999 r.in.hash = &lm_verifier;
2001 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2003 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2004 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2005 nt_errstr(status));
2006 ret = false;
2009 /* This shouldn't be a valid name */
2010 account_bad.string = TEST_ACCOUNT_NAME "XX";
2011 r.in.account = &account_bad;
2012 r.in.password = NULL;
2013 r.in.hash = &lm_verifier;
2015 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2017 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
2018 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2019 nt_errstr(status));
2020 ret = false;
2023 E_deshash(oldpass, old_lm_hash);
2024 E_deshash(newpass, new_lm_hash);
2026 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2027 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2028 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2030 r.in.server = &server;
2031 r.in.account = &account;
2032 r.in.password = &lm_pass;
2033 r.in.hash = &lm_verifier;
2035 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2036 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2037 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2038 } else if (!NT_STATUS_IS_OK(status)) {
2039 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
2040 ret = false;
2041 } else {
2042 *password = newpass;
2045 return ret;
2049 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2050 const char *acct_name,
2051 char **password,
2052 char *newpass, bool allow_password_restriction)
2054 NTSTATUS status;
2055 struct samr_ChangePasswordUser2 r;
2056 bool ret = true;
2057 struct lsa_String server, account;
2058 struct samr_CryptPassword nt_pass, lm_pass;
2059 struct samr_Password nt_verifier, lm_verifier;
2060 char *oldpass;
2061 uint8_t old_nt_hash[16], new_nt_hash[16];
2062 uint8_t old_lm_hash[16], new_lm_hash[16];
2064 struct samr_GetDomPwInfo dom_pw_info;
2065 struct samr_PwInfo info;
2067 struct lsa_String domain_name;
2069 domain_name.string = "";
2070 dom_pw_info.in.domain_name = &domain_name;
2071 dom_pw_info.out.info = &info;
2073 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2075 torture_assert(tctx, *password != NULL,
2076 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2077 oldpass = *password;
2079 if (!newpass) {
2080 int policy_min_pw_len = 0;
2081 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
2082 if (NT_STATUS_IS_OK(status)) {
2083 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2086 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2089 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2090 init_lsa_String(&account, acct_name);
2092 E_md4hash(oldpass, old_nt_hash);
2093 E_md4hash(newpass, new_nt_hash);
2095 E_deshash(oldpass, old_lm_hash);
2096 E_deshash(newpass, new_lm_hash);
2098 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2099 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2100 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2102 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2103 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2104 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2106 r.in.server = &server;
2107 r.in.account = &account;
2108 r.in.nt_password = &nt_pass;
2109 r.in.nt_verifier = &nt_verifier;
2110 r.in.lm_change = 1;
2111 r.in.lm_password = &lm_pass;
2112 r.in.lm_verifier = &lm_verifier;
2114 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
2115 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2116 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2117 } else if (!NT_STATUS_IS_OK(status)) {
2118 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2119 ret = false;
2120 } else {
2121 *password = newpass;
2124 return ret;
2128 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2129 const char *account_string,
2130 int policy_min_pw_len,
2131 char **password,
2132 const char *newpass,
2133 NTTIME last_password_change,
2134 bool handle_reject_reason)
2136 NTSTATUS status;
2137 struct samr_ChangePasswordUser3 r;
2138 bool ret = true;
2139 struct lsa_String server, account, account_bad;
2140 struct samr_CryptPassword nt_pass, lm_pass;
2141 struct samr_Password nt_verifier, lm_verifier;
2142 char *oldpass;
2143 uint8_t old_nt_hash[16], new_nt_hash[16];
2144 uint8_t old_lm_hash[16], new_lm_hash[16];
2145 NTTIME t;
2146 struct samr_DomInfo1 *dominfo = NULL;
2147 struct userPwdChangeFailureInformation *reject = NULL;
2149 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2151 if (newpass == NULL) {
2152 do {
2153 if (policy_min_pw_len == 0) {
2154 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2155 } else {
2156 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2158 } while (check_password_quality(newpass) == false);
2159 } else {
2160 torture_comment(tctx, "Using password '%s'\n", newpass);
2163 torture_assert(tctx, *password != NULL,
2164 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2166 oldpass = *password;
2167 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2168 init_lsa_String(&account, account_string);
2170 E_md4hash(oldpass, old_nt_hash);
2171 E_md4hash(newpass, new_nt_hash);
2173 E_deshash(oldpass, old_lm_hash);
2174 E_deshash(newpass, new_lm_hash);
2176 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2177 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2178 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2180 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2181 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2182 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2184 /* Break the verification */
2185 nt_verifier.hash[0]++;
2187 r.in.server = &server;
2188 r.in.account = &account;
2189 r.in.nt_password = &nt_pass;
2190 r.in.nt_verifier = &nt_verifier;
2191 r.in.lm_change = 1;
2192 r.in.lm_password = &lm_pass;
2193 r.in.lm_verifier = &lm_verifier;
2194 r.in.password3 = NULL;
2195 r.out.dominfo = &dominfo;
2196 r.out.reject = &reject;
2198 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2199 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2200 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2201 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2202 nt_errstr(status));
2203 ret = false;
2206 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2207 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2208 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2210 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2211 /* Break the NT hash */
2212 old_nt_hash[0]++;
2213 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2214 /* Unbreak it again */
2215 old_nt_hash[0]--;
2216 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2218 r.in.server = &server;
2219 r.in.account = &account;
2220 r.in.nt_password = &nt_pass;
2221 r.in.nt_verifier = &nt_verifier;
2222 r.in.lm_change = 1;
2223 r.in.lm_password = &lm_pass;
2224 r.in.lm_verifier = &lm_verifier;
2225 r.in.password3 = NULL;
2226 r.out.dominfo = &dominfo;
2227 r.out.reject = &reject;
2229 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2230 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2231 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2232 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2233 nt_errstr(status));
2234 ret = false;
2237 /* This shouldn't be a valid name */
2238 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2240 r.in.account = &account_bad;
2241 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2242 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2243 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2244 nt_errstr(status));
2245 ret = false;
2248 E_md4hash(oldpass, old_nt_hash);
2249 E_md4hash(newpass, new_nt_hash);
2251 E_deshash(oldpass, old_lm_hash);
2252 E_deshash(newpass, new_lm_hash);
2254 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2255 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2256 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2258 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2259 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2260 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2262 r.in.server = &server;
2263 r.in.account = &account;
2264 r.in.nt_password = &nt_pass;
2265 r.in.nt_verifier = &nt_verifier;
2266 r.in.lm_change = 1;
2267 r.in.lm_password = &lm_pass;
2268 r.in.lm_verifier = &lm_verifier;
2269 r.in.password3 = NULL;
2270 r.out.dominfo = &dominfo;
2271 r.out.reject = &reject;
2273 unix_to_nt_time(&t, time(NULL));
2275 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2277 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2278 && dominfo
2279 && reject
2280 && handle_reject_reason
2281 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2282 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2284 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2285 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2286 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2287 return false;
2291 /* We tested the order of precendence which is as follows:
2293 * pwd min_age
2294 * pwd length
2295 * pwd complexity
2296 * pwd history
2298 Guenther */
2300 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2301 (last_password_change + dominfo->min_password_age > t)) {
2303 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2304 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2305 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2306 return false;
2309 } else if ((dominfo->min_password_length > 0) &&
2310 (strlen(newpass) < dominfo->min_password_length)) {
2312 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2313 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2314 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2315 return false;
2318 } else if ((dominfo->password_history_length > 0) &&
2319 strequal(oldpass, newpass)) {
2321 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2322 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2323 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2324 return false;
2326 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2328 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2329 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2330 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2331 return false;
2336 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2337 /* retry with adjusted size */
2338 return test_ChangePasswordUser3(p, tctx, account_string,
2339 dominfo->min_password_length,
2340 password, NULL, 0, false);
2344 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2345 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2346 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2347 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2348 return false;
2350 /* Perhaps the server has a 'min password age' set? */
2352 } else {
2353 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2354 *password = talloc_strdup(tctx, newpass);
2357 return ret;
2360 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2361 const char *account_string,
2362 struct policy_handle *handle,
2363 char **password)
2365 NTSTATUS status;
2366 struct samr_ChangePasswordUser3 r;
2367 struct samr_SetUserInfo s;
2368 union samr_UserInfo u;
2369 DATA_BLOB session_key;
2370 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2371 uint8_t confounder[16];
2372 struct MD5Context ctx;
2374 bool ret = true;
2375 struct lsa_String server, account;
2376 struct samr_CryptPassword nt_pass;
2377 struct samr_Password nt_verifier;
2378 DATA_BLOB new_random_pass;
2379 char *newpass;
2380 char *oldpass;
2381 uint8_t old_nt_hash[16], new_nt_hash[16];
2382 NTTIME t;
2383 struct samr_DomInfo1 *dominfo = NULL;
2384 struct userPwdChangeFailureInformation *reject = NULL;
2386 new_random_pass = samr_very_rand_pass(tctx, 128);
2388 torture_assert(tctx, *password != NULL,
2389 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2391 oldpass = *password;
2392 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2393 init_lsa_String(&account, account_string);
2395 s.in.user_handle = handle;
2396 s.in.info = &u;
2397 s.in.level = 25;
2399 ZERO_STRUCT(u);
2401 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2403 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2405 status = dcerpc_fetch_session_key(p, &session_key);
2406 if (!NT_STATUS_IS_OK(status)) {
2407 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2408 s.in.level, nt_errstr(status));
2409 return false;
2412 generate_random_buffer((uint8_t *)confounder, 16);
2414 MD5Init(&ctx);
2415 MD5Update(&ctx, confounder, 16);
2416 MD5Update(&ctx, session_key.data, session_key.length);
2417 MD5Final(confounded_session_key.data, &ctx);
2419 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2420 memcpy(&u.info25.password.data[516], confounder, 16);
2422 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2424 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2425 if (!NT_STATUS_IS_OK(status)) {
2426 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2427 s.in.level, nt_errstr(status));
2428 ret = false;
2431 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2433 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2435 new_random_pass = samr_very_rand_pass(tctx, 128);
2437 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2439 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2440 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2441 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2443 r.in.server = &server;
2444 r.in.account = &account;
2445 r.in.nt_password = &nt_pass;
2446 r.in.nt_verifier = &nt_verifier;
2447 r.in.lm_change = 0;
2448 r.in.lm_password = NULL;
2449 r.in.lm_verifier = NULL;
2450 r.in.password3 = NULL;
2451 r.out.dominfo = &dominfo;
2452 r.out.reject = &reject;
2454 unix_to_nt_time(&t, time(NULL));
2456 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2458 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2459 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2460 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2461 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2462 return false;
2464 /* Perhaps the server has a 'min password age' set? */
2466 } else if (!NT_STATUS_IS_OK(status)) {
2467 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2468 ret = false;
2471 newpass = samr_rand_pass(tctx, 128);
2473 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2475 E_md4hash(newpass, new_nt_hash);
2477 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2478 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2479 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2481 r.in.server = &server;
2482 r.in.account = &account;
2483 r.in.nt_password = &nt_pass;
2484 r.in.nt_verifier = &nt_verifier;
2485 r.in.lm_change = 0;
2486 r.in.lm_password = NULL;
2487 r.in.lm_verifier = NULL;
2488 r.in.password3 = NULL;
2489 r.out.dominfo = &dominfo;
2490 r.out.reject = &reject;
2492 unix_to_nt_time(&t, time(NULL));
2494 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2496 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2497 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2498 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2499 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2500 return false;
2502 /* Perhaps the server has a 'min password age' set? */
2504 } else {
2505 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2506 *password = talloc_strdup(tctx, newpass);
2509 return ret;
2513 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2514 struct policy_handle *alias_handle)
2516 struct samr_GetMembersInAlias r;
2517 struct lsa_SidArray sids;
2518 NTSTATUS status;
2520 torture_comment(tctx, "Testing GetMembersInAlias\n");
2522 r.in.alias_handle = alias_handle;
2523 r.out.sids = &sids;
2525 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2526 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2528 return true;
2531 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2532 struct policy_handle *alias_handle,
2533 const struct dom_sid *domain_sid)
2535 struct samr_AddAliasMember r;
2536 struct samr_DeleteAliasMember d;
2537 NTSTATUS status;
2538 struct dom_sid *sid;
2540 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2542 torture_comment(tctx, "testing AddAliasMember\n");
2543 r.in.alias_handle = alias_handle;
2544 r.in.sid = sid;
2546 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2547 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2549 d.in.alias_handle = alias_handle;
2550 d.in.sid = sid;
2552 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2553 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2555 return true;
2558 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2559 struct policy_handle *alias_handle)
2561 struct samr_AddMultipleMembersToAlias a;
2562 struct samr_RemoveMultipleMembersFromAlias r;
2563 NTSTATUS status;
2564 struct lsa_SidArray sids;
2566 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2567 a.in.alias_handle = alias_handle;
2568 a.in.sids = &sids;
2570 sids.num_sids = 3;
2571 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2573 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2574 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2575 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2577 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2578 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2581 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2582 r.in.alias_handle = alias_handle;
2583 r.in.sids = &sids;
2585 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2586 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2588 /* strange! removing twice doesn't give any error */
2589 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2590 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2592 /* but removing an alias that isn't there does */
2593 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2595 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2596 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2598 return true;
2601 static bool test_GetAliasMembership(struct dcerpc_pipe *p,
2602 struct torture_context *tctx,
2603 struct policy_handle *domain_handle)
2605 struct samr_GetAliasMembership r;
2606 struct lsa_SidArray sids;
2607 struct samr_Ids rids;
2608 NTSTATUS status;
2610 torture_comment(tctx, "Testing GetAliasMembership\n");
2612 if (torture_setting_bool(tctx, "samba4", false)) {
2613 torture_skip(tctx, "skipping GetAliasMembership against s4");
2616 r.in.domain_handle = domain_handle;
2617 r.in.sids = &sids;
2618 r.out.rids = &rids;
2620 sids.num_sids = 0;
2621 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2623 status = dcerpc_samr_GetAliasMembership(p, tctx, &r);
2624 torture_assert_ntstatus_ok(tctx, status,
2625 "samr_GetAliasMembership failed");
2627 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2628 "protocol misbehaviour");
2630 sids.num_sids = 1;
2631 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2632 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2634 status = dcerpc_samr_GetAliasMembership(p, tctx, &r);
2635 torture_assert_ntstatus_ok(tctx, status,
2636 "samr_GetAliasMembership failed");
2638 #if 0
2639 /* only true for w2k8 it seems
2640 * win7, xp, w2k3 will return a 0 length array pointer */
2642 if (rids.ids && (rids.count == 0)) {
2643 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2645 #endif
2646 if (!rids.ids && rids.count) {
2647 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2650 return true;
2653 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2654 struct policy_handle *user_handle)
2656 struct samr_TestPrivateFunctionsUser r;
2657 NTSTATUS status;
2659 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2661 r.in.user_handle = user_handle;
2663 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2664 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2666 return true;
2669 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2670 struct torture_context *tctx,
2671 struct policy_handle *handle,
2672 bool use_info2,
2673 NTTIME *pwdlastset)
2675 NTSTATUS status;
2676 uint16_t levels[] = { /* 3, */ 5, 21 };
2677 int i;
2678 NTTIME pwdlastset3 = 0;
2679 NTTIME pwdlastset5 = 0;
2680 NTTIME pwdlastset21 = 0;
2682 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2683 use_info2 ? "2":"");
2685 for (i=0; i<ARRAY_SIZE(levels); i++) {
2687 struct samr_QueryUserInfo r;
2688 struct samr_QueryUserInfo2 r2;
2689 union samr_UserInfo *info;
2691 if (use_info2) {
2692 r2.in.user_handle = handle;
2693 r2.in.level = levels[i];
2694 r2.out.info = &info;
2695 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2697 } else {
2698 r.in.user_handle = handle;
2699 r.in.level = levels[i];
2700 r.out.info = &info;
2701 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2704 if (!NT_STATUS_IS_OK(status) &&
2705 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2706 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2707 use_info2 ? "2":"", levels[i], nt_errstr(status));
2708 return false;
2711 switch (levels[i]) {
2712 case 3:
2713 pwdlastset3 = info->info3.last_password_change;
2714 break;
2715 case 5:
2716 pwdlastset5 = info->info5.last_password_change;
2717 break;
2718 case 21:
2719 pwdlastset21 = info->info21.last_password_change;
2720 break;
2721 default:
2722 return false;
2725 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2726 "pwdlastset mixup"); */
2727 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2728 "pwdlastset mixup");
2730 *pwdlastset = pwdlastset21;
2732 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2734 return true;
2737 static bool test_SamLogon(struct torture_context *tctx,
2738 struct dcerpc_pipe *p,
2739 struct cli_credentials *test_credentials,
2740 NTSTATUS expected_result,
2741 bool interactive)
2743 NTSTATUS status;
2744 struct netr_LogonSamLogonEx r;
2745 union netr_LogonLevel logon;
2746 union netr_Validation validation;
2747 uint8_t authoritative;
2748 struct netr_IdentityInfo identity;
2749 struct netr_NetworkInfo ninfo;
2750 struct netr_PasswordInfo pinfo;
2751 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2752 int flags = CLI_CRED_NTLM_AUTH;
2753 uint32_t samlogon_flags = 0;
2754 struct netlogon_creds_CredentialState *creds;
2755 struct netr_Authenticator a;
2757 torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2759 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2760 flags |= CLI_CRED_LANMAN_AUTH;
2763 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2764 flags |= CLI_CRED_NTLMv2_AUTH;
2767 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2768 &identity.account_name.string,
2769 &identity.domain_name.string);
2771 identity.parameter_control =
2772 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2773 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2774 identity.logon_id_low = 0;
2775 identity.logon_id_high = 0;
2776 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2778 if (interactive) {
2779 netlogon_creds_client_authenticator(creds, &a);
2781 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
2782 ZERO_STRUCT(pinfo.lmpassword.hash);
2784 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
2786 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
2787 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
2788 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
2789 } else {
2790 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
2791 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
2794 pinfo.identity_info = identity;
2795 logon.password = &pinfo;
2797 r.in.logon_level = NetlogonInteractiveInformation;
2798 } else {
2799 generate_random_buffer(ninfo.challenge,
2800 sizeof(ninfo.challenge));
2801 chal = data_blob_const(ninfo.challenge,
2802 sizeof(ninfo.challenge));
2804 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2805 cli_credentials_get_domain(test_credentials));
2807 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2808 &flags,
2809 chal,
2810 names_blob,
2811 &lm_resp, &nt_resp,
2812 NULL, NULL);
2813 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2815 ninfo.lm.data = lm_resp.data;
2816 ninfo.lm.length = lm_resp.length;
2818 ninfo.nt.data = nt_resp.data;
2819 ninfo.nt.length = nt_resp.length;
2821 ninfo.identity_info = identity;
2822 logon.network = &ninfo;
2824 r.in.logon_level = NetlogonNetworkInformation;
2827 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2828 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2829 r.in.logon = &logon;
2830 r.in.flags = &samlogon_flags;
2831 r.out.flags = &samlogon_flags;
2832 r.out.validation = &validation;
2833 r.out.authoritative = &authoritative;
2835 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
2837 r.in.validation_level = 6;
2839 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2840 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2841 r.in.validation_level = 3;
2842 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2844 if (!NT_STATUS_IS_OK(status)) {
2845 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed");
2846 return true;
2847 } else {
2848 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogonEx failed");
2851 return true;
2854 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2855 struct dcerpc_pipe *p,
2856 struct cli_credentials *machine_creds,
2857 const char *acct_name,
2858 char *password,
2859 NTSTATUS expected_samlogon_result,
2860 bool interactive)
2862 bool ret = true;
2863 struct cli_credentials *test_credentials;
2865 test_credentials = cli_credentials_init(tctx);
2867 cli_credentials_set_workstation(test_credentials,
2868 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2869 cli_credentials_set_domain(test_credentials,
2870 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2871 cli_credentials_set_username(test_credentials,
2872 acct_name, CRED_SPECIFIED);
2873 cli_credentials_set_password(test_credentials,
2874 password, CRED_SPECIFIED);
2876 torture_comment(tctx, "testing samlogon (%s) as %s password: %s\n",
2877 interactive ? "interactive" : "network", acct_name, password);
2879 if (!test_SamLogon(tctx, p, test_credentials,
2880 expected_samlogon_result, interactive)) {
2881 torture_warning(tctx, "new password did not work\n");
2882 ret = false;
2885 return ret;
2888 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2889 struct dcerpc_pipe *np,
2890 struct torture_context *tctx,
2891 struct policy_handle *handle,
2892 uint16_t level,
2893 uint32_t fields_present,
2894 uint8_t password_expired,
2895 bool *matched_expected_error,
2896 bool use_setinfo2,
2897 const char *acct_name,
2898 char **password,
2899 struct cli_credentials *machine_creds,
2900 bool use_queryinfo2,
2901 NTTIME *pwdlastset,
2902 NTSTATUS expected_samlogon_result)
2904 const char *fields = NULL;
2905 bool ret = true;
2907 switch (level) {
2908 case 21:
2909 case 23:
2910 case 25:
2911 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2912 fields_present);
2913 break;
2914 default:
2915 break;
2918 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2919 "(password_expired: %d) %s\n",
2920 use_setinfo2 ? "2":"", level, password_expired,
2921 fields ? fields : "");
2923 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2924 fields_present,
2925 password,
2926 password_expired,
2927 use_setinfo2,
2928 matched_expected_error)) {
2929 ret = false;
2932 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2933 use_queryinfo2,
2934 pwdlastset)) {
2935 ret = false;
2938 if (*matched_expected_error == true) {
2939 return ret;
2942 if (!test_SamLogon_with_creds(tctx, np,
2943 machine_creds,
2944 acct_name,
2945 *password,
2946 expected_samlogon_result,
2947 false)) {
2948 ret = false;
2951 return ret;
2954 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
2955 struct cli_credentials *credentials,
2956 struct dcerpc_pipe **p)
2958 struct dcerpc_binding *b;
2960 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
2961 "failed to get rpc binding");
2963 /* We have to use schannel, otherwise the SamLogonEx fails
2964 * with INTERNAL_ERROR */
2966 b->flags &= ~DCERPC_AUTH_OPTIONS;
2967 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
2969 torture_assert_ntstatus_ok(tctx,
2970 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
2971 credentials, tctx->ev, tctx->lp_ctx),
2972 "failed to bind to netlogon");
2974 return true;
2977 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2978 struct torture_context *tctx,
2979 uint32_t acct_flags,
2980 const char *acct_name,
2981 struct policy_handle *handle,
2982 char **password,
2983 struct cli_credentials *machine_credentials)
2985 int s = 0, q = 0, f = 0, l = 0, z = 0;
2986 bool ret = true;
2987 int delay = 50000;
2988 bool set_levels[] = { false, true };
2989 bool query_levels[] = { false, true };
2990 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
2991 uint32_t nonzeros[] = { 1, 24 };
2992 uint32_t fields_present[] = {
2994 SAMR_FIELD_EXPIRED_FLAG,
2995 SAMR_FIELD_LAST_PWD_CHANGE,
2996 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2997 SAMR_FIELD_COMMENT,
2998 SAMR_FIELD_NT_PASSWORD_PRESENT,
2999 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3000 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3001 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3002 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3003 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3004 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3006 struct dcerpc_pipe *np = NULL;
3008 if (torture_setting_bool(tctx, "samba3", false)) {
3009 delay = 999999;
3010 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3011 delay);
3014 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3016 /* set to 1 to enable testing for all possible opcode
3017 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3018 combinations */
3019 #if 0
3020 #define TEST_ALL_LEVELS 1
3021 #define TEST_SET_LEVELS 1
3022 #define TEST_QUERY_LEVELS 1
3023 #endif
3024 #ifdef TEST_ALL_LEVELS
3025 for (l=0; l<ARRAY_SIZE(levels); l++) {
3026 #else
3027 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3028 #endif
3029 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3030 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3031 #ifdef TEST_SET_LEVELS
3032 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3033 #endif
3034 #ifdef TEST_QUERY_LEVELS
3035 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3036 #endif
3037 NTTIME pwdlastset_old = 0;
3038 NTTIME pwdlastset_new = 0;
3039 bool matched_expected_error = false;
3040 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3042 torture_comment(tctx, "------------------------------\n"
3043 "Testing pwdLastSet attribute for flags: 0x%08x "
3044 "(s: %d (l: %d), q: %d)\n",
3045 acct_flags, s, levels[l], q);
3047 switch (levels[l]) {
3048 case 21:
3049 case 23:
3050 case 25:
3051 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3052 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3053 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3055 break;
3059 /* set #1 */
3061 /* set a password and force password change (pwdlastset 0) by
3062 * setting the password expired flag to a non-0 value */
3064 if (!test_SetPassword_level(p, np, tctx, handle,
3065 levels[l],
3066 fields_present[f],
3067 nonzeros[z],
3068 &matched_expected_error,
3069 set_levels[s],
3070 acct_name,
3071 password,
3072 machine_credentials,
3073 query_levels[q],
3074 &pwdlastset_old,
3075 expected_samlogon_result)) {
3076 ret = false;
3079 if (matched_expected_error == true) {
3080 /* skipping on expected failure */
3081 continue;
3084 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3085 * set without the SAMR_FIELD_EXPIRED_FLAG */
3087 switch (levels[l]) {
3088 case 21:
3089 case 23:
3090 case 25:
3091 if ((pwdlastset_new != 0) &&
3092 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3093 torture_comment(tctx, "not considering a non-0 "
3094 "pwdLastSet as a an error as the "
3095 "SAMR_FIELD_EXPIRED_FLAG has not "
3096 "been set\n");
3097 break;
3099 default:
3100 if (pwdlastset_new != 0) {
3101 torture_warning(tctx, "pwdLastSet test failed: "
3102 "expected pwdLastSet 0 but got %lld\n",
3103 pwdlastset_old);
3104 ret = false;
3106 break;
3109 switch (levels[l]) {
3110 case 21:
3111 case 23:
3112 case 25:
3113 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3114 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3115 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3116 (pwdlastset_old >= pwdlastset_new)) {
3117 torture_warning(tctx, "pwdlastset not increasing\n");
3118 ret = false;
3120 break;
3121 default:
3122 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3123 (pwdlastset_old >= pwdlastset_new)) {
3124 torture_warning(tctx, "pwdlastset not increasing\n");
3125 ret = false;
3127 break;
3130 usleep(delay);
3132 /* set #2 */
3134 /* set a password, pwdlastset needs to get updated (increased
3135 * value), password_expired value used here is 0 */
3137 if (!test_SetPassword_level(p, np, tctx, handle,
3138 levels[l],
3139 fields_present[f],
3141 &matched_expected_error,
3142 set_levels[s],
3143 acct_name,
3144 password,
3145 machine_credentials,
3146 query_levels[q],
3147 &pwdlastset_new,
3148 expected_samlogon_result)) {
3149 ret = false;
3152 /* when a password has been changed, pwdlastset must not be 0 afterwards
3153 * and must be larger then the old value */
3155 switch (levels[l]) {
3156 case 21:
3157 case 23:
3158 case 25:
3160 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3161 * password has been changed, old and new pwdlastset
3162 * need to be the same value */
3164 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3165 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3166 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3168 torture_assert_int_equal(tctx, pwdlastset_old,
3169 pwdlastset_new, "pwdlastset must be equal");
3170 break;
3172 default:
3173 if (pwdlastset_old >= pwdlastset_new) {
3174 torture_warning(tctx, "pwdLastSet test failed: "
3175 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3176 pwdlastset_old, pwdlastset_new);
3177 ret = false;
3179 if (pwdlastset_new == 0) {
3180 torture_warning(tctx, "pwdLastSet test failed: "
3181 "expected non-0 pwdlastset, got: %lld\n",
3182 pwdlastset_new);
3183 ret = false;
3187 switch (levels[l]) {
3188 case 21:
3189 case 23:
3190 case 25:
3191 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3192 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3193 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3194 (pwdlastset_old >= pwdlastset_new)) {
3195 torture_warning(tctx, "pwdlastset not increasing\n");
3196 ret = false;
3198 break;
3199 default:
3200 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3201 (pwdlastset_old >= pwdlastset_new)) {
3202 torture_warning(tctx, "pwdlastset not increasing\n");
3203 ret = false;
3205 break;
3208 pwdlastset_old = pwdlastset_new;
3210 usleep(delay);
3212 /* set #2b */
3214 /* set a password, pwdlastset needs to get updated (increased
3215 * value), password_expired value used here is 0 */
3217 if (!test_SetPassword_level(p, np, tctx, handle,
3218 levels[l],
3219 fields_present[f],
3221 &matched_expected_error,
3222 set_levels[s],
3223 acct_name,
3224 password,
3225 machine_credentials,
3226 query_levels[q],
3227 &pwdlastset_new,
3228 expected_samlogon_result)) {
3229 ret = false;
3232 /* when a password has been changed, pwdlastset must not be 0 afterwards
3233 * and must be larger then the old value */
3235 switch (levels[l]) {
3236 case 21:
3237 case 23:
3238 case 25:
3240 /* if no password has been changed, old and new pwdlastset
3241 * need to be the same value */
3243 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3244 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3246 torture_assert_int_equal(tctx, pwdlastset_old,
3247 pwdlastset_new, "pwdlastset must be equal");
3248 break;
3250 default:
3251 if (pwdlastset_old >= pwdlastset_new) {
3252 torture_warning(tctx, "pwdLastSet test failed: "
3253 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3254 pwdlastset_old, pwdlastset_new);
3255 ret = false;
3257 if (pwdlastset_new == 0) {
3258 torture_warning(tctx, "pwdLastSet test failed: "
3259 "expected non-0 pwdlastset, got: %lld\n",
3260 pwdlastset_new);
3261 ret = false;
3265 /* set #3 */
3267 /* set a password and force password change (pwdlastset 0) by
3268 * setting the password expired flag to a non-0 value */
3270 if (!test_SetPassword_level(p, np, tctx, handle,
3271 levels[l],
3272 fields_present[f],
3273 nonzeros[z],
3274 &matched_expected_error,
3275 set_levels[s],
3276 acct_name,
3277 password,
3278 machine_credentials,
3279 query_levels[q],
3280 &pwdlastset_new,
3281 expected_samlogon_result)) {
3282 ret = false;
3285 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3286 * set without the SAMR_FIELD_EXPIRED_FLAG */
3288 switch (levels[l]) {
3289 case 21:
3290 case 23:
3291 case 25:
3292 if ((pwdlastset_new != 0) &&
3293 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3294 torture_comment(tctx, "not considering a non-0 "
3295 "pwdLastSet as a an error as the "
3296 "SAMR_FIELD_EXPIRED_FLAG has not "
3297 "been set\n");
3298 break;
3301 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3302 * password has been changed, old and new pwdlastset
3303 * need to be the same value */
3305 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3306 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3307 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3309 torture_assert_int_equal(tctx, pwdlastset_old,
3310 pwdlastset_new, "pwdlastset must be equal");
3311 break;
3313 default:
3315 if (pwdlastset_old == pwdlastset_new) {
3316 torture_warning(tctx, "pwdLastSet test failed: "
3317 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3318 pwdlastset_old, pwdlastset_new);
3319 ret = false;
3322 if (pwdlastset_new != 0) {
3323 torture_warning(tctx, "pwdLastSet test failed: "
3324 "expected pwdLastSet 0, got %lld\n",
3325 pwdlastset_old);
3326 ret = false;
3328 break;
3331 switch (levels[l]) {
3332 case 21:
3333 case 23:
3334 case 25:
3335 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3336 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3337 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3338 (pwdlastset_old >= pwdlastset_new)) {
3339 torture_warning(tctx, "pwdlastset not increasing\n");
3340 ret = false;
3342 break;
3343 default:
3344 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3345 (pwdlastset_old >= pwdlastset_new)) {
3346 torture_warning(tctx, "pwdlastset not increasing\n");
3347 ret = false;
3349 break;
3352 /* if the level we are testing does not have a fields_present
3353 * field, skip all fields present tests by setting f to to
3354 * arraysize */
3355 switch (levels[l]) {
3356 case 18:
3357 case 24:
3358 case 26:
3359 f = ARRAY_SIZE(fields_present);
3360 break;
3363 #ifdef TEST_QUERY_LEVELS
3365 #endif
3366 #ifdef TEST_SET_LEVELS
3368 #endif
3369 } /* fields present */
3370 } /* nonzeros */
3371 } /* levels */
3373 #undef TEST_SET_LEVELS
3374 #undef TEST_QUERY_LEVELS
3376 talloc_free(np);
3378 return ret;
3381 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_pipe *p,
3382 struct torture_context *tctx,
3383 struct policy_handle *handle,
3384 uint32_t *badpwdcount)
3386 union samr_UserInfo *info;
3387 struct samr_QueryUserInfo r;
3389 r.in.user_handle = handle;
3390 r.in.level = 3;
3391 r.out.info = &info;
3393 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3395 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo(p, tctx, &r),
3396 "failed to query userinfo");
3398 *badpwdcount = info->info3.bad_password_count;
3400 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3402 return true;
3405 static bool test_SetUserInfo_acct_flags(struct dcerpc_pipe *p,
3406 struct torture_context *tctx,
3407 struct policy_handle *user_handle,
3408 uint32_t acct_flags)
3410 struct samr_SetUserInfo r;
3411 union samr_UserInfo user_info;
3413 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3415 user_info.info16.acct_flags = acct_flags;
3417 r.in.user_handle = user_handle;
3418 r.in.level = 16;
3419 r.in.info = &user_info;
3421 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo(p, tctx, &r),
3422 "failed to set account flags");
3424 return true;
3427 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3428 struct torture_context *tctx,
3429 struct policy_handle *user_handle,
3430 uint32_t acct_flags,
3431 char **password)
3433 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3434 "failed to set password");
3436 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3438 torture_assert(tctx,
3439 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3440 acct_flags & ~ACB_DISABLED),
3441 "failed to enable user");
3443 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3444 "failed to set password");
3446 return true;
3449 static bool test_SetDomainInfo(struct dcerpc_pipe *p,
3450 struct torture_context *tctx,
3451 struct policy_handle *domain_handle,
3452 enum samr_DomainInfoClass level,
3453 union samr_DomainInfo *info)
3455 struct samr_SetDomainInfo r;
3457 r.in.domain_handle = domain_handle;
3458 r.in.level = level;
3459 r.in.info = info;
3461 torture_assert_ntstatus_ok(tctx,
3462 dcerpc_samr_SetDomainInfo(p, tctx, &r),
3463 "failed to set domain info");
3465 return true;
3468 static bool test_SetDomainInfo_ntstatus(struct dcerpc_pipe *p,
3469 struct torture_context *tctx,
3470 struct policy_handle *domain_handle,
3471 enum samr_DomainInfoClass level,
3472 union samr_DomainInfo *info,
3473 NTSTATUS expected)
3475 struct samr_SetDomainInfo r;
3477 r.in.domain_handle = domain_handle;
3478 r.in.level = level;
3479 r.in.info = info;
3481 torture_assert_ntstatus_equal(tctx,
3482 dcerpc_samr_SetDomainInfo(p, tctx, &r),
3483 expected,
3484 "");
3486 return true;
3489 static bool test_QueryDomainInfo2_level(struct dcerpc_pipe *p,
3490 struct torture_context *tctx,
3491 struct policy_handle *domain_handle,
3492 enum samr_DomainInfoClass level,
3493 union samr_DomainInfo **q_info)
3495 struct samr_QueryDomainInfo2 r;
3497 r.in.domain_handle = domain_handle;
3498 r.in.level = level;
3499 r.out.info = q_info;
3501 torture_assert_ntstatus_ok(tctx,
3502 dcerpc_samr_QueryDomainInfo2(p, tctx, &r),
3503 "failed to query domain info");
3505 return true;
3508 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3509 struct dcerpc_pipe *np,
3510 struct torture_context *tctx,
3511 uint32_t acct_flags,
3512 const char *acct_name,
3513 struct policy_handle *domain_handle,
3514 struct policy_handle *user_handle,
3515 char **password,
3516 struct cli_credentials *machine_credentials,
3517 const char *comment,
3518 bool disable,
3519 bool interactive,
3520 NTSTATUS expected_success_status,
3521 struct samr_DomInfo1 *info1,
3522 struct samr_DomInfo12 *info12)
3524 union samr_DomainInfo info;
3525 char **passwords;
3526 int i;
3527 uint32_t badpwdcount, tmp;
3528 uint32_t password_history_length = 12;
3529 uint32_t lockout_threshold = 15;
3531 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3533 torture_assert(tctx, password_history_length < lockout_threshold,
3534 "password history length needs to be smaller than account lockout threshold for this test");
3537 /* set policies */
3539 info.info1 = *info1;
3540 info.info1.password_history_length = password_history_length;
3542 torture_assert(tctx,
3543 test_SetDomainInfo(p, tctx, domain_handle,
3544 DomainPasswordInformation, &info),
3545 "failed to set password history length");
3547 info.info12 = *info12;
3548 info.info12.lockout_threshold = lockout_threshold;
3550 torture_assert(tctx,
3551 test_SetDomainInfo(p, tctx, domain_handle,
3552 DomainLockoutInformation, &info),
3553 "failed to set lockout threshold");
3555 /* reset bad pwd count */
3557 torture_assert(tctx,
3558 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3561 /* enable or disable account */
3562 if (disable) {
3563 torture_assert(tctx,
3564 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3565 acct_flags | ACB_DISABLED),
3566 "failed to disable user");
3567 } else {
3568 torture_assert(tctx,
3569 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3570 acct_flags & ~ACB_DISABLED),
3571 "failed to enable user");
3575 /* setup password history */
3577 passwords = talloc_array(tctx, char *, password_history_length);
3579 for (i=0; i < password_history_length; i++) {
3581 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3582 "failed to set password");
3583 passwords[i] = talloc_strdup(tctx, *password);
3585 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3586 acct_name, passwords[i],
3587 expected_success_status, interactive)) {
3588 torture_fail(tctx, "failed to auth with latest password");
3591 torture_assert(tctx,
3592 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3594 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3598 /* test with wrong password */
3600 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3601 acct_name, "random_crap",
3602 NT_STATUS_WRONG_PASSWORD, interactive)) {
3603 torture_fail(tctx, "succeeded to authenticate with wrong password");
3606 torture_assert(tctx,
3607 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3609 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3612 /* test with latest good password */
3614 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3615 passwords[password_history_length-1],
3616 expected_success_status, interactive)) {
3617 torture_fail(tctx, "succeeded to authenticate with wrong password");
3620 torture_assert(tctx,
3621 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3623 if (disable) {
3624 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3625 } else {
3626 /* only enabled accounts get the bad pwd count reset upon
3627 * successful logon */
3628 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3631 tmp = badpwdcount;
3634 /* test password history */
3636 for (i=0; i < password_history_length; i++) {
3638 torture_comment(tctx, "Testing bad password count behavior with "
3639 "password #%d of #%d\n", i, password_history_length);
3641 /* - network samlogon will succeed auth and not
3642 * increase badpwdcount for 2 last entries
3643 * - interactive samlogon only for the last one */
3645 if (i == password_history_length - 1 ||
3646 (i == password_history_length - 2 && !interactive)) {
3648 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3649 acct_name, passwords[i],
3650 expected_success_status, interactive)) {
3651 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3654 torture_assert(tctx,
3655 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3657 if (disable) {
3658 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3659 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3660 } else {
3661 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3662 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3665 tmp = badpwdcount;
3667 continue;
3670 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3671 acct_name, passwords[i],
3672 NT_STATUS_WRONG_PASSWORD, interactive)) {
3673 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3676 torture_assert(tctx,
3677 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3679 /* - network samlogon will fail auth but not increase
3680 * badpwdcount for 3rd last entry
3681 * - interactive samlogon for 3rd and 2nd last entry */
3683 if (i == password_history_length - 3 ||
3684 (i == password_history_length - 2 && interactive)) {
3685 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3686 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3687 } else {
3688 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3689 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3692 tmp = badpwdcount;
3695 return true;
3698 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3699 struct torture_context *tctx,
3700 uint32_t acct_flags,
3701 const char *acct_name,
3702 struct policy_handle *domain_handle,
3703 struct policy_handle *user_handle,
3704 char **password,
3705 struct cli_credentials *machine_credentials)
3707 union samr_DomainInfo *q_info, s_info;
3708 struct samr_DomInfo1 info1, _info1;
3709 struct samr_DomInfo12 info12, _info12;
3710 bool ret = true;
3711 struct dcerpc_pipe *np;
3712 int i;
3714 struct {
3715 const char *comment;
3716 bool disabled;
3717 bool interactive;
3718 NTSTATUS expected_success_status;
3719 } creds[] = {
3721 .comment = "network logon (disabled account)",
3722 .disabled = true,
3723 .interactive = false,
3724 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3727 .comment = "network logon (enabled account)",
3728 .disabled = false,
3729 .interactive = false,
3730 .expected_success_status= NT_STATUS_OK
3733 .comment = "interactive logon (disabled account)",
3734 .disabled = true,
3735 .interactive = true,
3736 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3739 .comment = "interactive logon (enabled account)",
3740 .disabled = false,
3741 .interactive = true,
3742 .expected_success_status= NT_STATUS_OK
3746 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3748 /* backup old policies */
3750 torture_assert(tctx,
3751 test_QueryDomainInfo2_level(p, tctx, domain_handle,
3752 DomainPasswordInformation, &q_info),
3753 "failed to query domain info level 1");
3755 info1 = q_info->info1;
3756 _info1 = info1;
3758 torture_assert(tctx,
3759 test_QueryDomainInfo2_level(p, tctx, domain_handle,
3760 DomainLockoutInformation, &q_info),
3761 "failed to query domain info level 12");
3763 info12 = q_info->info12;
3764 _info12 = info12;
3766 /* run tests */
3768 for (i=0; i < ARRAY_SIZE(creds); i++) {
3770 /* skip trust tests for now */
3771 if (acct_flags & ACB_WSTRUST ||
3772 acct_flags & ACB_SVRTRUST ||
3773 acct_flags & ACB_DOMTRUST) {
3774 continue;
3777 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
3778 domain_handle, user_handle, password,
3779 machine_credentials,
3780 creds[i].comment,
3781 creds[i].disabled,
3782 creds[i].interactive,
3783 creds[i].expected_success_status,
3784 &_info1, &_info12);
3785 if (!ret) {
3786 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
3787 } else {
3788 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
3792 /* restore policies */
3794 s_info.info1 = info1;
3796 torture_assert(tctx,
3797 test_SetDomainInfo(p, tctx, domain_handle,
3798 DomainPasswordInformation, &s_info),
3799 "failed to set password information");
3801 s_info.info12 = info12;
3803 torture_assert(tctx,
3804 test_SetDomainInfo(p, tctx, domain_handle,
3805 DomainLockoutInformation, &s_info),
3806 "failed to set lockout information");
3808 return ret;
3811 static bool test_QueryUserInfo_acct_flags(struct dcerpc_pipe *p,
3812 struct torture_context *tctx,
3813 struct policy_handle *handle,
3814 uint32_t *acct_flags)
3816 union samr_UserInfo *info;
3817 struct samr_QueryUserInfo r;
3819 r.in.user_handle = handle;
3820 r.in.level = 16;
3821 r.out.info = &info;
3823 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3825 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo(p, tctx, &r),
3826 "failed to query userinfo");
3828 *acct_flags = info->info16.acct_flags;
3830 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
3832 return true;
3835 static bool test_Password_lockout(struct dcerpc_pipe *p,
3836 struct dcerpc_pipe *np,
3837 struct torture_context *tctx,
3838 uint32_t acct_flags,
3839 const char *acct_name,
3840 struct policy_handle *domain_handle,
3841 struct policy_handle *user_handle,
3842 char **password,
3843 struct cli_credentials *machine_credentials,
3844 const char *comment,
3845 bool disable,
3846 bool interactive,
3847 NTSTATUS expected_success_status,
3848 struct samr_DomInfo1 *info1,
3849 struct samr_DomInfo12 *info12)
3851 union samr_DomainInfo info;
3852 uint32_t badpwdcount;
3853 uint32_t password_history_length = 1;
3854 uint64_t lockout_threshold = 1;
3855 uint32_t lockout_seconds = 5;
3856 uint64_t delta_time_factor = 10 * 1000 * 1000;
3858 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
3860 /* set policies */
3862 info.info1 = *info1;
3864 torture_comment(tctx, "setting password history lenght.\n");
3865 info.info1.password_history_length = password_history_length;
3867 torture_assert(tctx,
3868 test_SetDomainInfo(p, tctx, domain_handle,
3869 DomainPasswordInformation, &info),
3870 "failed to set password history length");
3872 info.info12 = *info12;
3873 info.info12.lockout_threshold = lockout_threshold;
3875 /* set lockout duration < lockout window: should fail */
3876 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3877 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
3879 torture_assert(tctx,
3880 test_SetDomainInfo_ntstatus(p, tctx, domain_handle,
3881 DomainLockoutInformation, &info,
3882 NT_STATUS_INVALID_PARAMETER),
3883 "setting lockout duration < lockout window gave unexpected result");
3885 info.info12.lockout_duration = 0;
3886 info.info12.lockout_window = 0;
3888 torture_assert(tctx,
3889 test_SetDomainInfo(p, tctx, domain_handle,
3890 DomainLockoutInformation, &info),
3891 "failed to set lockout window and duration to 0");
3894 /* set lockout duration of 5 seconds */
3895 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3896 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
3898 torture_assert(tctx,
3899 test_SetDomainInfo(p, tctx, domain_handle,
3900 DomainLockoutInformation, &info),
3901 "failed to set lockout window and duration to 5 seconds");
3903 /* reset bad pwd count */
3905 torture_assert(tctx,
3906 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3909 /* enable or disable account */
3911 if (disable) {
3912 torture_assert(tctx,
3913 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3914 acct_flags | ACB_DISABLED),
3915 "failed to disable user");
3916 } else {
3917 torture_assert(tctx,
3918 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3919 acct_flags & ~ACB_DISABLED),
3920 "failed to enable user");
3924 /* test logon with right password */
3926 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3927 acct_name, *password,
3928 expected_success_status, interactive)) {
3929 torture_fail(tctx, "failed to auth with latest password");
3932 torture_assert(tctx,
3933 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3934 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3937 /* test with wrong password ==> lockout */
3939 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3940 acct_name, "random_crap",
3941 NT_STATUS_WRONG_PASSWORD, interactive)) {
3942 torture_fail(tctx, "succeeded to authenticate with wrong password");
3945 torture_assert(tctx,
3946 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3947 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3949 torture_assert(tctx,
3950 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3951 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3952 "expected account to be locked");
3955 /* test with good password */
3957 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3958 *password,
3959 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
3961 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
3964 /* bad pwd count should not get updated */
3965 torture_assert(tctx,
3966 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3967 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3969 /* curiously, windows does _not_ set the autlock flag */
3970 torture_assert(tctx,
3971 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3972 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3973 "expected account to be locked");
3976 /* with bad password */
3978 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3979 acct_name, "random_crap2",
3980 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
3982 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
3985 /* bad pwd count should not get updated */
3986 torture_assert(tctx,
3987 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3988 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3990 /* curiously, windows does _not_ set the autlock flag */
3991 torture_assert(tctx,
3992 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3993 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3994 "expected account to be locked");
3997 /* let lockout duration expire ==> unlock */
3999 torture_comment(tctx, "let lockout duration expire...\n");
4000 sleep(lockout_seconds + 1);
4002 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4003 *password,
4004 expected_success_status, interactive))
4006 torture_fail(tctx, "failed to authenticate after lockout expired");
4009 torture_assert(tctx,
4010 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
4011 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4012 "expected account not to be locked");
4014 return true;
4017 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4018 struct torture_context *tctx,
4019 uint32_t acct_flags,
4020 const char *acct_name,
4021 struct policy_handle *domain_handle,
4022 struct policy_handle *user_handle,
4023 char **password,
4024 struct cli_credentials *machine_credentials)
4026 union samr_DomainInfo *q_info, s_info;
4027 struct samr_DomInfo1 info1, _info1;
4028 struct samr_DomInfo12 info12, _info12;
4029 bool ret = true;
4030 struct dcerpc_pipe *np;
4031 int i;
4033 struct {
4034 const char *comment;
4035 bool disabled;
4036 bool interactive;
4037 NTSTATUS expected_success_status;
4038 } creds[] = {
4040 .comment = "network logon (disabled account)",
4041 .disabled = true,
4042 .interactive = false,
4043 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4046 .comment = "network logon (enabled account)",
4047 .disabled = false,
4048 .interactive = false,
4049 .expected_success_status= NT_STATUS_OK
4052 .comment = "interactive logon (disabled account)",
4053 .disabled = true,
4054 .interactive = true,
4055 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4058 .comment = "interactive logon (enabled account)",
4059 .disabled = false,
4060 .interactive = true,
4061 .expected_success_status= NT_STATUS_OK
4065 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4067 /* backup old policies */
4069 torture_assert(tctx,
4070 test_QueryDomainInfo2_level(p, tctx, domain_handle,
4071 DomainPasswordInformation, &q_info),
4072 "failed to query domain info level 1");
4074 info1 = q_info->info1;
4075 _info1 = info1;
4077 torture_assert(tctx,
4078 test_QueryDomainInfo2_level(p, tctx, domain_handle,
4079 DomainLockoutInformation, &q_info),
4080 "failed to query domain info level 12");
4082 info12 = q_info->info12;
4083 _info12 = info12;
4085 /* run tests */
4087 for (i=0; i < ARRAY_SIZE(creds); i++) {
4089 /* skip trust tests for now */
4090 if (acct_flags & ACB_WSTRUST ||
4091 acct_flags & ACB_SVRTRUST ||
4092 acct_flags & ACB_DOMTRUST) {
4093 continue;
4096 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4097 domain_handle, user_handle, password,
4098 machine_credentials,
4099 creds[i].comment,
4100 creds[i].disabled,
4101 creds[i].interactive,
4102 creds[i].expected_success_status,
4103 &_info1, &_info12);
4104 if (!ret) {
4105 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4106 } else {
4107 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4111 /* restore policies */
4113 s_info.info1 = info1;
4115 torture_assert(tctx,
4116 test_SetDomainInfo(p, tctx, domain_handle,
4117 DomainPasswordInformation, &s_info),
4118 "failed to set password information");
4120 s_info.info12 = info12;
4122 torture_assert(tctx,
4123 test_SetDomainInfo(p, tctx, domain_handle,
4124 DomainLockoutInformation, &s_info),
4125 "failed to set lockout information");
4127 return ret;
4130 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4131 struct dcerpc_pipe *lp,
4132 struct torture_context *tctx,
4133 struct policy_handle *domain_handle,
4134 struct policy_handle *lsa_handle,
4135 struct policy_handle *user_handle,
4136 const struct dom_sid *domain_sid,
4137 uint32_t rid,
4138 struct cli_credentials *machine_credentials)
4140 NTSTATUS status;
4141 bool ret = true;
4143 struct policy_handle lsa_acct_handle;
4144 struct dom_sid *user_sid;
4146 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4149 struct lsa_EnumAccountRights r;
4150 struct lsa_RightSet rights;
4152 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4154 r.in.handle = lsa_handle;
4155 r.in.sid = user_sid;
4156 r.out.rights = &rights;
4158 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4159 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4160 "Expected enum rights for account to fail");
4164 struct lsa_RightSet rights;
4165 struct lsa_StringLarge names[2];
4166 struct lsa_AddAccountRights r;
4168 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4170 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4171 init_lsa_StringLarge(&names[1], NULL);
4173 rights.count = 1;
4174 rights.names = names;
4176 r.in.handle = lsa_handle;
4177 r.in.sid = user_sid;
4178 r.in.rights = &rights;
4180 status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
4181 torture_assert_ntstatus_ok(tctx, status,
4182 "Failed to add privileges");
4186 struct lsa_EnumAccounts r;
4187 uint32_t resume_handle = 0;
4188 struct lsa_SidArray lsa_sid_array;
4189 int i;
4190 bool found_sid = false;
4192 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4194 r.in.handle = lsa_handle;
4195 r.in.num_entries = 0x1000;
4196 r.in.resume_handle = &resume_handle;
4197 r.out.sids = &lsa_sid_array;
4198 r.out.resume_handle = &resume_handle;
4200 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4201 torture_assert_ntstatus_ok(tctx, status,
4202 "Failed to enum accounts");
4204 for (i=0; i < lsa_sid_array.num_sids; i++) {
4205 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4206 found_sid = true;
4210 torture_assert(tctx, found_sid,
4211 "failed to list privileged account");
4215 struct lsa_EnumAccountRights r;
4216 struct lsa_RightSet user_rights;
4218 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4220 r.in.handle = lsa_handle;
4221 r.in.sid = user_sid;
4222 r.out.rights = &user_rights;
4224 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4225 torture_assert_ntstatus_ok(tctx, status,
4226 "Failed to enum rights for account");
4228 if (user_rights.count < 1) {
4229 torture_warning(tctx, "failed to find newly added rights");
4230 return false;
4235 struct lsa_OpenAccount r;
4237 torture_comment(tctx, "Testing LSA OpenAccount\n");
4239 r.in.handle = lsa_handle;
4240 r.in.sid = user_sid;
4241 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4242 r.out.acct_handle = &lsa_acct_handle;
4244 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
4245 torture_assert_ntstatus_ok(tctx, status,
4246 "Failed to open lsa account");
4250 struct lsa_GetSystemAccessAccount r;
4251 uint32_t access_mask;
4253 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4255 r.in.handle = &lsa_acct_handle;
4256 r.out.access_mask = &access_mask;
4258 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
4259 torture_assert_ntstatus_ok(tctx, status,
4260 "Failed to get lsa system access account");
4264 struct lsa_Close r;
4266 torture_comment(tctx, "Testing LSA Close\n");
4268 r.in.handle = &lsa_acct_handle;
4269 r.out.handle = &lsa_acct_handle;
4271 status = dcerpc_lsa_Close(lp, tctx, &r);
4272 torture_assert_ntstatus_ok(tctx, status,
4273 "Failed to close lsa");
4277 struct samr_DeleteUser r;
4279 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4281 r.in.user_handle = user_handle;
4282 r.out.user_handle = user_handle;
4284 status = dcerpc_samr_DeleteUser(p, tctx, &r);
4285 torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
4289 struct lsa_EnumAccounts r;
4290 uint32_t resume_handle = 0;
4291 struct lsa_SidArray lsa_sid_array;
4292 int i;
4293 bool found_sid = false;
4295 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4297 r.in.handle = lsa_handle;
4298 r.in.num_entries = 0x1000;
4299 r.in.resume_handle = &resume_handle;
4300 r.out.sids = &lsa_sid_array;
4301 r.out.resume_handle = &resume_handle;
4303 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4304 torture_assert_ntstatus_ok(tctx, status,
4305 "Failed to enum accounts");
4307 for (i=0; i < lsa_sid_array.num_sids; i++) {
4308 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4309 found_sid = true;
4313 torture_assert(tctx, found_sid,
4314 "failed to list privileged account");
4318 struct lsa_EnumAccountRights r;
4319 struct lsa_RightSet user_rights;
4321 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4323 r.in.handle = lsa_handle;
4324 r.in.sid = user_sid;
4325 r.out.rights = &user_rights;
4327 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4328 torture_assert_ntstatus_ok(tctx, status,
4329 "Failed to enum rights for account");
4331 if (user_rights.count < 1) {
4332 torture_warning(tctx, "failed to find newly added rights");
4333 return false;
4338 struct lsa_OpenAccount r;
4340 torture_comment(tctx, "Testing LSA OpenAccount\n");
4342 r.in.handle = lsa_handle;
4343 r.in.sid = user_sid;
4344 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4345 r.out.acct_handle = &lsa_acct_handle;
4347 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
4348 torture_assert_ntstatus_ok(tctx, status,
4349 "Failed to open lsa account");
4353 struct lsa_GetSystemAccessAccount r;
4354 uint32_t access_mask;
4356 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4358 r.in.handle = &lsa_acct_handle;
4359 r.out.access_mask = &access_mask;
4361 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
4362 torture_assert_ntstatus_ok(tctx, status,
4363 "Failed to get lsa system access account");
4367 struct lsa_DeleteObject r;
4369 torture_comment(tctx, "Testing LSA DeleteObject\n");
4371 r.in.handle = &lsa_acct_handle;
4372 r.out.handle = &lsa_acct_handle;
4374 status = dcerpc_lsa_DeleteObject(lp, tctx, &r);
4375 torture_assert_ntstatus_ok(tctx, status,
4376 "Failed to delete object");
4380 struct lsa_EnumAccounts r;
4381 uint32_t resume_handle = 0;
4382 struct lsa_SidArray lsa_sid_array;
4383 int i;
4384 bool found_sid = false;
4386 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4388 r.in.handle = lsa_handle;
4389 r.in.num_entries = 0x1000;
4390 r.in.resume_handle = &resume_handle;
4391 r.out.sids = &lsa_sid_array;
4392 r.out.resume_handle = &resume_handle;
4394 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4395 torture_assert_ntstatus_ok(tctx, status,
4396 "Failed to enum accounts");
4398 for (i=0; i < lsa_sid_array.num_sids; i++) {
4399 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4400 found_sid = true;
4404 torture_assert(tctx, !found_sid,
4405 "should not have listed privileged account");
4409 struct lsa_EnumAccountRights r;
4410 struct lsa_RightSet user_rights;
4412 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4414 r.in.handle = lsa_handle;
4415 r.in.sid = user_sid;
4416 r.out.rights = &user_rights;
4418 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4419 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4420 "Failed to enum rights for account");
4423 return ret;
4426 static bool test_user_ops(struct dcerpc_pipe *p,
4427 struct torture_context *tctx,
4428 struct policy_handle *user_handle,
4429 struct policy_handle *domain_handle,
4430 const struct dom_sid *domain_sid,
4431 uint32_t base_acct_flags,
4432 const char *base_acct_name, enum torture_samr_choice which_ops,
4433 struct cli_credentials *machine_credentials)
4435 char *password = NULL;
4436 struct samr_QueryUserInfo q;
4437 union samr_UserInfo *info;
4438 NTSTATUS status;
4440 bool ret = true;
4441 int i;
4442 uint32_t rid;
4443 const uint32_t password_fields[] = {
4444 SAMR_FIELD_NT_PASSWORD_PRESENT,
4445 SAMR_FIELD_LM_PASSWORD_PRESENT,
4446 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4450 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
4451 if (!NT_STATUS_IS_OK(status)) {
4452 ret = false;
4455 switch (which_ops) {
4456 case TORTURE_SAMR_USER_ATTRIBUTES:
4457 if (!test_QuerySecurity(p, tctx, user_handle)) {
4458 ret = false;
4461 if (!test_QueryUserInfo(p, tctx, user_handle)) {
4462 ret = false;
4465 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
4466 ret = false;
4469 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
4470 base_acct_name)) {
4471 ret = false;
4474 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
4475 ret = false;
4478 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
4479 ret = false;
4482 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4483 ret = false;
4485 break;
4486 case TORTURE_SAMR_PASSWORDS:
4487 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4488 char simple_pass[9];
4489 char *v = generate_random_str(tctx, 1);
4491 ZERO_STRUCT(simple_pass);
4492 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4494 torture_comment(tctx, "Testing machine account password policy rules\n");
4496 /* Workstation trust accounts don't seem to need to honour password quality policy */
4497 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4498 ret = false;
4501 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4502 ret = false;
4505 /* reset again, to allow another 'user' password change */
4506 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4507 ret = false;
4510 /* Try a 'short' password */
4511 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4512 ret = false;
4515 /* Try a compleatly random password */
4516 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4517 ret = false;
4521 for (i = 0; password_fields[i]; i++) {
4522 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4523 ret = false;
4526 /* check it was set right */
4527 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4528 ret = false;
4532 for (i = 0; password_fields[i]; i++) {
4533 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4534 ret = false;
4537 /* check it was set right */
4538 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4539 ret = false;
4543 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4544 ret = false;
4547 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4548 ret = false;
4551 if (torture_setting_bool(tctx, "samba4", false)) {
4552 torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
4553 } else {
4555 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4556 ret = false;
4559 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4560 ret = false;
4563 for (i = 0; password_fields[i]; i++) {
4565 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4566 /* we need to skip as that would break
4567 * the ChangePasswordUser3 verify */
4568 continue;
4571 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4572 ret = false;
4575 /* check it was set right */
4576 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4577 ret = false;
4582 q.in.user_handle = user_handle;
4583 q.in.level = 5;
4584 q.out.info = &info;
4586 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4587 if (!NT_STATUS_IS_OK(status)) {
4588 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4589 q.in.level, nt_errstr(status));
4590 ret = false;
4591 } else {
4592 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4593 if ((info->info5.acct_flags) != expected_flags) {
4594 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4595 info->info5.acct_flags,
4596 expected_flags);
4597 /* FIXME: GD */
4598 if (!torture_setting_bool(tctx, "samba3", false)) {
4599 ret = false;
4602 if (info->info5.rid != rid) {
4603 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4604 info->info5.rid, rid);
4609 break;
4611 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4613 /* test last password change timestamp behaviour */
4614 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4615 base_acct_name,
4616 user_handle, &password,
4617 machine_credentials)) {
4618 ret = false;
4621 if (ret == true) {
4622 torture_comment(tctx, "pwdLastSet test succeeded\n");
4623 } else {
4624 torture_warning(tctx, "pwdLastSet test failed\n");
4627 break;
4629 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4631 /* test bad pwd count change behaviour */
4632 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4633 base_acct_name,
4634 domain_handle,
4635 user_handle, &password,
4636 machine_credentials)) {
4637 ret = false;
4640 if (ret == true) {
4641 torture_comment(tctx, "badPwdCount test succeeded\n");
4642 } else {
4643 torture_warning(tctx, "badPwdCount test failed\n");
4646 break;
4648 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4650 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4651 base_acct_name,
4652 domain_handle,
4653 user_handle, &password,
4654 machine_credentials))
4656 ret = false;
4659 if (ret == true) {
4660 torture_comment(tctx, "lockout test succeeded\n");
4661 } else {
4662 torture_warning(tctx, "lockout test failed\n");
4665 break;
4668 case TORTURE_SAMR_USER_PRIVILEGES: {
4670 struct dcerpc_pipe *lp;
4671 struct policy_handle *lsa_handle;
4673 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4674 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4676 if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
4677 ret = false;
4680 if (!test_DeleteUser_with_privs(p, lp, tctx,
4681 domain_handle, lsa_handle, user_handle,
4682 domain_sid, rid,
4683 machine_credentials)) {
4684 ret = false;
4687 if (!test_lsa_Close(lp, tctx, lsa_handle)) {
4688 ret = false;
4691 if (!ret) {
4692 torture_warning(tctx, "privileged user delete test failed\n");
4695 break;
4697 case TORTURE_SAMR_OTHER:
4698 /* We just need the account to exist */
4699 break;
4701 return ret;
4704 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
4705 struct policy_handle *alias_handle,
4706 const struct dom_sid *domain_sid)
4708 bool ret = true;
4710 if (!torture_setting_bool(tctx, "samba3", false)) {
4711 if (!test_QuerySecurity(p, tctx, alias_handle)) {
4712 ret = false;
4716 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
4717 ret = false;
4720 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
4721 ret = false;
4724 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
4725 ret = false;
4728 if (torture_setting_bool(tctx, "samba3", false) ||
4729 torture_setting_bool(tctx, "samba4", false)) {
4730 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4731 return ret;
4734 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
4735 ret = false;
4738 return ret;
4742 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
4743 struct policy_handle *user_handle)
4745 struct samr_DeleteUser d;
4746 NTSTATUS status;
4747 torture_comment(tctx, "Testing DeleteUser\n");
4749 d.in.user_handle = user_handle;
4750 d.out.user_handle = user_handle;
4752 status = dcerpc_samr_DeleteUser(p, tctx, &d);
4753 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
4755 return true;
4758 bool test_DeleteUser_byname(struct dcerpc_pipe *p,
4759 struct torture_context *tctx,
4760 struct policy_handle *handle, const char *name)
4762 NTSTATUS status;
4763 struct samr_DeleteUser d;
4764 struct policy_handle user_handle;
4765 uint32_t rid;
4767 status = test_LookupName(p, tctx, handle, name, &rid);
4768 if (!NT_STATUS_IS_OK(status)) {
4769 goto failed;
4772 status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
4773 if (!NT_STATUS_IS_OK(status)) {
4774 goto failed;
4777 d.in.user_handle = &user_handle;
4778 d.out.user_handle = &user_handle;
4779 status = dcerpc_samr_DeleteUser(p, tctx, &d);
4780 if (!NT_STATUS_IS_OK(status)) {
4781 goto failed;
4784 return true;
4786 failed:
4787 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
4788 return false;
4792 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
4793 struct torture_context *tctx,
4794 struct policy_handle *handle, const char *name)
4796 NTSTATUS status;
4797 struct samr_OpenGroup r;
4798 struct samr_DeleteDomainGroup d;
4799 struct policy_handle group_handle;
4800 uint32_t rid;
4802 status = test_LookupName(p, tctx, handle, name, &rid);
4803 if (!NT_STATUS_IS_OK(status)) {
4804 goto failed;
4807 r.in.domain_handle = handle;
4808 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4809 r.in.rid = rid;
4810 r.out.group_handle = &group_handle;
4811 status = dcerpc_samr_OpenGroup(p, tctx, &r);
4812 if (!NT_STATUS_IS_OK(status)) {
4813 goto failed;
4816 d.in.group_handle = &group_handle;
4817 d.out.group_handle = &group_handle;
4818 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
4819 if (!NT_STATUS_IS_OK(status)) {
4820 goto failed;
4823 return true;
4825 failed:
4826 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
4827 return false;
4831 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
4832 struct torture_context *tctx,
4833 struct policy_handle *domain_handle,
4834 const char *name)
4836 NTSTATUS status;
4837 struct samr_OpenAlias r;
4838 struct samr_DeleteDomAlias d;
4839 struct policy_handle alias_handle;
4840 uint32_t rid;
4842 torture_comment(tctx, "testing DeleteAlias_byname\n");
4844 status = test_LookupName(p, tctx, domain_handle, name, &rid);
4845 if (!NT_STATUS_IS_OK(status)) {
4846 goto failed;
4849 r.in.domain_handle = domain_handle;
4850 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4851 r.in.rid = rid;
4852 r.out.alias_handle = &alias_handle;
4853 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4854 if (!NT_STATUS_IS_OK(status)) {
4855 goto failed;
4858 d.in.alias_handle = &alias_handle;
4859 d.out.alias_handle = &alias_handle;
4860 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4861 if (!NT_STATUS_IS_OK(status)) {
4862 goto failed;
4865 return true;
4867 failed:
4868 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
4869 return false;
4872 static bool test_DeleteAlias(struct dcerpc_pipe *p,
4873 struct torture_context *tctx,
4874 struct policy_handle *alias_handle)
4876 struct samr_DeleteDomAlias d;
4877 NTSTATUS status;
4878 bool ret = true;
4880 torture_comment(tctx, "Testing DeleteAlias\n");
4882 d.in.alias_handle = alias_handle;
4883 d.out.alias_handle = alias_handle;
4885 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(status));
4888 ret = false;
4891 return ret;
4894 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4895 struct policy_handle *domain_handle,
4896 const char *alias_name,
4897 struct policy_handle *alias_handle,
4898 const struct dom_sid *domain_sid,
4899 bool test_alias)
4901 NTSTATUS status;
4902 struct samr_CreateDomAlias r;
4903 struct lsa_String name;
4904 uint32_t rid;
4905 bool ret = true;
4907 init_lsa_String(&name, alias_name);
4908 r.in.domain_handle = domain_handle;
4909 r.in.alias_name = &name;
4910 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4911 r.out.alias_handle = alias_handle;
4912 r.out.rid = &rid;
4914 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
4916 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4918 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4919 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4920 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
4921 return true;
4922 } else {
4923 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
4924 nt_errstr(status));
4925 return false;
4929 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
4930 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
4931 return false;
4933 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(status));
4938 return false;
4941 if (!test_alias) {
4942 return ret;
4945 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
4946 ret = false;
4949 return ret;
4952 static bool test_ChangePassword(struct dcerpc_pipe *p,
4953 struct torture_context *tctx,
4954 const char *acct_name,
4955 struct policy_handle *domain_handle, char **password)
4957 bool ret = true;
4959 if (!*password) {
4960 return false;
4963 if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
4964 ret = false;
4967 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
4968 ret = false;
4971 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
4972 ret = false;
4975 /* test what happens when setting the old password again */
4976 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
4977 ret = false;
4981 char simple_pass[9];
4982 char *v = generate_random_str(tctx, 1);
4984 ZERO_STRUCT(simple_pass);
4985 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4987 /* test what happens when picking a simple password */
4988 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
4989 ret = false;
4993 /* set samr_SetDomainInfo level 1 with min_length 5 */
4995 struct samr_QueryDomainInfo r;
4996 union samr_DomainInfo *info = NULL;
4997 struct samr_SetDomainInfo s;
4998 uint16_t len_old, len;
4999 uint32_t pwd_prop_old;
5000 int64_t min_pwd_age_old;
5001 NTSTATUS status;
5003 len = 5;
5005 r.in.domain_handle = domain_handle;
5006 r.in.level = 1;
5007 r.out.info = &info;
5009 torture_comment(tctx, "testing samr_QueryDomainInfo level 1\n");
5010 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5011 if (!NT_STATUS_IS_OK(status)) {
5012 return false;
5015 s.in.domain_handle = domain_handle;
5016 s.in.level = 1;
5017 s.in.info = info;
5019 /* remember the old min length, so we can reset it */
5020 len_old = s.in.info->info1.min_password_length;
5021 s.in.info->info1.min_password_length = len;
5022 pwd_prop_old = s.in.info->info1.password_properties;
5023 /* turn off password complexity checks for this test */
5024 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5026 min_pwd_age_old = s.in.info->info1.min_password_age;
5027 s.in.info->info1.min_password_age = 0;
5029 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
5030 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5031 if (!NT_STATUS_IS_OK(status)) {
5032 return false;
5035 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5037 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5038 ret = false;
5041 s.in.info->info1.min_password_length = len_old;
5042 s.in.info->info1.password_properties = pwd_prop_old;
5043 s.in.info->info1.min_password_age = min_pwd_age_old;
5045 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
5046 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5047 if (!NT_STATUS_IS_OK(status)) {
5048 return false;
5054 NTSTATUS status;
5055 struct samr_OpenUser r;
5056 struct samr_QueryUserInfo q;
5057 union samr_UserInfo *info;
5058 struct samr_LookupNames n;
5059 struct policy_handle user_handle;
5060 struct samr_Ids rids, types;
5062 n.in.domain_handle = domain_handle;
5063 n.in.num_names = 1;
5064 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5065 n.in.names[0].string = acct_name;
5066 n.out.rids = &rids;
5067 n.out.types = &types;
5069 status = dcerpc_samr_LookupNames(p, tctx, &n);
5070 if (!NT_STATUS_IS_OK(status)) {
5071 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5072 return false;
5075 r.in.domain_handle = domain_handle;
5076 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5077 r.in.rid = n.out.rids->ids[0];
5078 r.out.user_handle = &user_handle;
5080 status = dcerpc_samr_OpenUser(p, tctx, &r);
5081 if (!NT_STATUS_IS_OK(status)) {
5082 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
5083 return false;
5086 q.in.user_handle = &user_handle;
5087 q.in.level = 5;
5088 q.out.info = &info;
5090 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5091 if (!NT_STATUS_IS_OK(status)) {
5092 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(status));
5093 return false;
5096 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5098 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5099 info->info5.last_password_change, true)) {
5100 ret = false;
5104 /* we change passwords twice - this has the effect of verifying
5105 they were changed correctly for the final call */
5106 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5107 ret = false;
5110 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5111 ret = false;
5114 return ret;
5117 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5118 struct policy_handle *domain_handle,
5119 const char *user_name,
5120 struct policy_handle *user_handle_out,
5121 struct dom_sid *domain_sid,
5122 enum torture_samr_choice which_ops,
5123 struct cli_credentials *machine_credentials,
5124 bool test_user)
5127 TALLOC_CTX *user_ctx;
5129 NTSTATUS status;
5130 struct samr_CreateUser r;
5131 struct samr_QueryUserInfo q;
5132 union samr_UserInfo *info;
5133 struct samr_DeleteUser d;
5134 uint32_t rid;
5136 /* This call creates a 'normal' account - check that it really does */
5137 const uint32_t acct_flags = ACB_NORMAL;
5138 struct lsa_String name;
5139 bool ret = true;
5141 struct policy_handle user_handle;
5142 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5143 init_lsa_String(&name, user_name);
5145 r.in.domain_handle = domain_handle;
5146 r.in.account_name = &name;
5147 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5148 r.out.user_handle = &user_handle;
5149 r.out.rid = &rid;
5151 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5153 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
5155 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5156 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5157 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5158 return true;
5159 } else {
5160 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5161 nt_errstr(status));
5162 return false;
5166 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5167 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
5168 talloc_free(user_ctx);
5169 return false;
5171 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
5174 if (!NT_STATUS_IS_OK(status)) {
5175 talloc_free(user_ctx);
5176 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(status));
5177 return false;
5180 if (!test_user) {
5181 if (user_handle_out) {
5182 *user_handle_out = user_handle;
5184 return ret;
5188 q.in.user_handle = &user_handle;
5189 q.in.level = 16;
5190 q.out.info = &info;
5192 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
5193 if (!NT_STATUS_IS_OK(status)) {
5194 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5195 q.in.level, nt_errstr(status));
5196 ret = false;
5197 } else {
5198 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5199 torture_warning(tctx, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5200 info->info16.acct_flags,
5201 acct_flags);
5202 ret = false;
5206 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5207 domain_sid, acct_flags, name.string, which_ops,
5208 machine_credentials)) {
5209 ret = false;
5212 if (user_handle_out) {
5213 *user_handle_out = user_handle;
5214 } else {
5215 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5217 d.in.user_handle = &user_handle;
5218 d.out.user_handle = &user_handle;
5220 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
5221 if (!NT_STATUS_IS_OK(status)) {
5222 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
5223 ret = false;
5229 talloc_free(user_ctx);
5231 return ret;
5235 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5236 struct policy_handle *domain_handle,
5237 struct dom_sid *domain_sid,
5238 enum torture_samr_choice which_ops,
5239 struct cli_credentials *machine_credentials)
5241 NTSTATUS status;
5242 struct samr_CreateUser2 r;
5243 struct samr_QueryUserInfo q;
5244 union samr_UserInfo *info;
5245 struct samr_DeleteUser d;
5246 struct policy_handle user_handle;
5247 uint32_t rid;
5248 struct lsa_String name;
5249 bool ret = true;
5250 int i;
5252 struct {
5253 uint32_t acct_flags;
5254 const char *account_name;
5255 NTSTATUS nt_status;
5256 } account_types[] = {
5257 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5258 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5259 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5260 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5261 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5262 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5263 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5264 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5265 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5266 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5267 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5268 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5269 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5270 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5271 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5274 for (i = 0; account_types[i].account_name; i++) {
5275 TALLOC_CTX *user_ctx;
5276 uint32_t acct_flags = account_types[i].acct_flags;
5277 uint32_t access_granted;
5278 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5279 init_lsa_String(&name, account_types[i].account_name);
5281 r.in.domain_handle = domain_handle;
5282 r.in.account_name = &name;
5283 r.in.acct_flags = acct_flags;
5284 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5285 r.out.user_handle = &user_handle;
5286 r.out.access_granted = &access_granted;
5287 r.out.rid = &rid;
5289 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5291 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
5293 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5294 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5295 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5296 continue;
5297 } else {
5298 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5299 nt_errstr(status));
5300 ret = false;
5301 continue;
5305 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5306 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
5307 talloc_free(user_ctx);
5308 ret = false;
5309 continue;
5311 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
5314 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
5315 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5316 nt_errstr(status), nt_errstr(account_types[i].nt_status));
5317 ret = false;
5320 if (NT_STATUS_IS_OK(status)) {
5321 q.in.user_handle = &user_handle;
5322 q.in.level = 5;
5323 q.out.info = &info;
5325 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
5326 if (!NT_STATUS_IS_OK(status)) {
5327 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5328 q.in.level, nt_errstr(status));
5329 ret = false;
5330 } else {
5331 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5332 if (acct_flags == ACB_NORMAL) {
5333 expected_flags |= ACB_PW_EXPIRED;
5335 if ((info->info5.acct_flags) != expected_flags) {
5336 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5337 info->info5.acct_flags,
5338 expected_flags);
5339 ret = false;
5341 switch (acct_flags) {
5342 case ACB_SVRTRUST:
5343 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5344 torture_warning(tctx, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5345 DOMAIN_RID_DCS, info->info5.primary_gid);
5346 ret = false;
5348 break;
5349 case ACB_WSTRUST:
5350 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5351 torture_warning(tctx, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5352 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5353 ret = false;
5355 break;
5356 case ACB_NORMAL:
5357 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5358 torture_warning(tctx, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5359 DOMAIN_RID_USERS, info->info5.primary_gid);
5360 ret = false;
5362 break;
5366 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5367 domain_sid, acct_flags, name.string, which_ops,
5368 machine_credentials)) {
5369 ret = false;
5372 if (!policy_handle_empty(&user_handle)) {
5373 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5375 d.in.user_handle = &user_handle;
5376 d.out.user_handle = &user_handle;
5378 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
5381 ret = false;
5385 talloc_free(user_ctx);
5388 return ret;
5391 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
5392 struct torture_context *tctx,
5393 struct policy_handle *handle)
5395 NTSTATUS status;
5396 struct samr_QueryAliasInfo r;
5397 union samr_AliasInfo *info;
5398 uint16_t levels[] = {1, 2, 3};
5399 int i;
5400 bool ret = true;
5402 for (i=0;i<ARRAY_SIZE(levels);i++) {
5403 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5405 r.in.alias_handle = handle;
5406 r.in.level = levels[i];
5407 r.out.info = &info;
5409 status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
5410 if (!NT_STATUS_IS_OK(status)) {
5411 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5412 levels[i], nt_errstr(status));
5413 ret = false;
5417 return ret;
5420 static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
5421 struct torture_context *tctx,
5422 struct policy_handle *handle)
5424 NTSTATUS status;
5425 struct samr_QueryGroupInfo r;
5426 union samr_GroupInfo *info;
5427 uint16_t levels[] = {1, 2, 3, 4, 5};
5428 int i;
5429 bool ret = true;
5431 for (i=0;i<ARRAY_SIZE(levels);i++) {
5432 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5434 r.in.group_handle = handle;
5435 r.in.level = levels[i];
5436 r.out.info = &info;
5438 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
5439 if (!NT_STATUS_IS_OK(status)) {
5440 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5441 levels[i], nt_errstr(status));
5442 ret = false;
5446 return ret;
5449 static bool test_QueryGroupMember(struct dcerpc_pipe *p,
5450 struct torture_context *tctx,
5451 struct policy_handle *handle)
5453 NTSTATUS status;
5454 struct samr_QueryGroupMember r;
5455 struct samr_RidTypeArray *rids = NULL;
5456 bool ret = true;
5458 torture_comment(tctx, "Testing QueryGroupMember\n");
5460 r.in.group_handle = handle;
5461 r.out.rids = &rids;
5463 status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
5464 if (!NT_STATUS_IS_OK(status)) {
5465 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(status));
5466 ret = false;
5469 return ret;
5473 static bool test_SetGroupInfo(struct dcerpc_pipe *p,
5474 struct torture_context *tctx,
5475 struct policy_handle *handle)
5477 NTSTATUS status;
5478 struct samr_QueryGroupInfo r;
5479 union samr_GroupInfo *info;
5480 struct samr_SetGroupInfo s;
5481 uint16_t levels[] = {1, 2, 3, 4};
5482 uint16_t set_ok[] = {0, 1, 1, 1};
5483 int i;
5484 bool ret = true;
5486 for (i=0;i<ARRAY_SIZE(levels);i++) {
5487 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5489 r.in.group_handle = handle;
5490 r.in.level = levels[i];
5491 r.out.info = &info;
5493 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
5494 if (!NT_STATUS_IS_OK(status)) {
5495 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5496 levels[i], nt_errstr(status));
5497 ret = false;
5500 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5502 s.in.group_handle = handle;
5503 s.in.level = levels[i];
5504 s.in.info = *r.out.info;
5506 #if 0
5507 /* disabled this, as it changes the name only from the point of view of samr,
5508 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5509 the name is still reserved, so creating the old name fails, but deleting by the old name
5510 also fails */
5511 if (s.in.level == 2) {
5512 init_lsa_String(&s.in.info->string, "NewName");
5514 #endif
5516 if (s.in.level == 4) {
5517 init_lsa_String(&s.in.info->description, "test description");
5520 status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
5521 if (set_ok[i]) {
5522 if (!NT_STATUS_IS_OK(status)) {
5523 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5524 r.in.level, nt_errstr(status));
5525 ret = false;
5526 continue;
5528 } else {
5529 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5530 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5531 r.in.level, nt_errstr(status));
5532 ret = false;
5533 continue;
5538 return ret;
5541 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
5542 struct torture_context *tctx,
5543 struct policy_handle *handle)
5545 NTSTATUS status;
5546 struct samr_QueryUserInfo r;
5547 union samr_UserInfo *info;
5548 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5549 11, 12, 13, 14, 16, 17, 20, 21};
5550 int i;
5551 bool ret = true;
5553 for (i=0;i<ARRAY_SIZE(levels);i++) {
5554 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5556 r.in.user_handle = handle;
5557 r.in.level = levels[i];
5558 r.out.info = &info;
5560 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
5561 if (!NT_STATUS_IS_OK(status)) {
5562 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5563 levels[i], nt_errstr(status));
5564 ret = false;
5568 return ret;
5571 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
5572 struct torture_context *tctx,
5573 struct policy_handle *handle)
5575 NTSTATUS status;
5576 struct samr_QueryUserInfo2 r;
5577 union samr_UserInfo *info;
5578 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5579 11, 12, 13, 14, 16, 17, 20, 21};
5580 int i;
5581 bool ret = true;
5583 for (i=0;i<ARRAY_SIZE(levels);i++) {
5584 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5586 r.in.user_handle = handle;
5587 r.in.level = levels[i];
5588 r.out.info = &info;
5590 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
5591 if (!NT_STATUS_IS_OK(status)) {
5592 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5593 levels[i], nt_errstr(status));
5594 ret = false;
5598 return ret;
5601 static bool test_OpenUser(struct dcerpc_pipe *p,
5602 struct torture_context *tctx,
5603 struct policy_handle *handle, uint32_t rid)
5605 NTSTATUS status;
5606 struct samr_OpenUser r;
5607 struct policy_handle user_handle;
5608 bool ret = true;
5610 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5612 r.in.domain_handle = handle;
5613 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5614 r.in.rid = rid;
5615 r.out.user_handle = &user_handle;
5617 status = dcerpc_samr_OpenUser(p, tctx, &r);
5618 if (!NT_STATUS_IS_OK(status)) {
5619 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
5620 return false;
5623 if (!test_QuerySecurity(p, tctx, &user_handle)) {
5624 ret = false;
5627 if (!test_QueryUserInfo(p, tctx, &user_handle)) {
5628 ret = false;
5631 if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
5632 ret = false;
5635 if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
5636 ret = false;
5639 if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
5640 ret = false;
5643 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5644 ret = false;
5647 return ret;
5650 static bool test_OpenGroup(struct dcerpc_pipe *p,
5651 struct torture_context *tctx,
5652 struct policy_handle *handle, uint32_t rid)
5654 NTSTATUS status;
5655 struct samr_OpenGroup r;
5656 struct policy_handle group_handle;
5657 bool ret = true;
5659 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5661 r.in.domain_handle = handle;
5662 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5663 r.in.rid = rid;
5664 r.out.group_handle = &group_handle;
5666 status = dcerpc_samr_OpenGroup(p, tctx, &r);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
5669 return false;
5672 if (!torture_setting_bool(tctx, "samba3", false)) {
5673 if (!test_QuerySecurity(p, tctx, &group_handle)) {
5674 ret = false;
5678 if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
5679 ret = false;
5682 if (!test_QueryGroupMember(p, tctx, &group_handle)) {
5683 ret = false;
5686 if (!test_samr_handle_Close(p, tctx, &group_handle)) {
5687 ret = false;
5690 return ret;
5693 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
5694 struct policy_handle *handle, uint32_t rid)
5696 NTSTATUS status;
5697 struct samr_OpenAlias r;
5698 struct policy_handle alias_handle;
5699 bool ret = true;
5701 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5703 r.in.domain_handle = handle;
5704 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5705 r.in.rid = rid;
5706 r.out.alias_handle = &alias_handle;
5708 status = dcerpc_samr_OpenAlias(p, tctx, &r);
5709 if (!NT_STATUS_IS_OK(status)) {
5710 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
5711 return false;
5714 if (!torture_setting_bool(tctx, "samba3", false)) {
5715 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
5716 ret = false;
5720 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
5721 ret = false;
5724 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
5725 ret = false;
5728 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
5729 ret = false;
5732 return ret;
5735 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
5736 struct policy_handle *handle, uint32_t rid,
5737 uint32_t acct_flag_mask)
5739 NTSTATUS status;
5740 struct samr_OpenUser r;
5741 struct samr_QueryUserInfo q;
5742 union samr_UserInfo *info;
5743 struct policy_handle user_handle;
5744 bool ret = true;
5746 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5748 r.in.domain_handle = handle;
5749 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5750 r.in.rid = rid;
5751 r.out.user_handle = &user_handle;
5753 status = dcerpc_samr_OpenUser(p, tctx, &r);
5754 if (!NT_STATUS_IS_OK(status)) {
5755 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
5756 return false;
5759 q.in.user_handle = &user_handle;
5760 q.in.level = 16;
5761 q.out.info = &info;
5763 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5764 if (!NT_STATUS_IS_OK(status)) {
5765 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
5766 nt_errstr(status));
5767 ret = false;
5768 } else {
5769 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
5770 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
5771 acct_flag_mask, info->info16.acct_flags, rid);
5772 ret = false;
5776 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5777 ret = false;
5780 return ret;
5783 static bool test_EnumDomainUsers_all(struct dcerpc_pipe *p,
5784 struct torture_context *tctx,
5785 struct policy_handle *handle)
5787 NTSTATUS status = STATUS_MORE_ENTRIES;
5788 struct samr_EnumDomainUsers r;
5789 uint32_t mask, resume_handle=0;
5790 int i, mask_idx;
5791 bool ret = true;
5792 struct samr_LookupNames n;
5793 struct samr_LookupRids lr ;
5794 struct lsa_Strings names;
5795 struct samr_Ids rids, types;
5796 struct samr_SamArray *sam = NULL;
5797 uint32_t num_entries = 0;
5799 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
5800 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
5801 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
5802 ACB_PWNOEXP, 0};
5804 torture_comment(tctx, "Testing EnumDomainUsers\n");
5806 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
5807 r.in.domain_handle = handle;
5808 r.in.resume_handle = &resume_handle;
5809 r.in.acct_flags = mask = masks[mask_idx];
5810 r.in.max_size = (uint32_t)-1;
5811 r.out.resume_handle = &resume_handle;
5812 r.out.num_entries = &num_entries;
5813 r.out.sam = &sam;
5815 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
5816 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5817 !NT_STATUS_IS_OK(status)) {
5818 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(status));
5819 return false;
5822 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
5824 if (sam->count == 0) {
5825 continue;
5828 for (i=0;i<sam->count;i++) {
5829 if (mask) {
5830 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
5831 ret = false;
5833 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
5834 ret = false;
5839 torture_comment(tctx, "Testing LookupNames\n");
5840 n.in.domain_handle = handle;
5841 n.in.num_names = sam->count;
5842 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
5843 n.out.rids = &rids;
5844 n.out.types = &types;
5845 for (i=0;i<sam->count;i++) {
5846 n.in.names[i].string = sam->entries[i].name.string;
5848 status = dcerpc_samr_LookupNames(p, tctx, &n);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5851 ret = false;
5855 torture_comment(tctx, "Testing LookupRids\n");
5856 lr.in.domain_handle = handle;
5857 lr.in.num_rids = sam->count;
5858 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
5859 lr.out.names = &names;
5860 lr.out.types = &types;
5861 for (i=0;i<sam->count;i++) {
5862 lr.in.rids[i] = sam->entries[i].idx;
5864 status = dcerpc_samr_LookupRids(p, tctx, &lr);
5865 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
5867 return ret;
5871 try blasting the server with a bunch of sync requests
5873 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
5874 struct policy_handle *handle)
5876 NTSTATUS status;
5877 struct samr_EnumDomainUsers r;
5878 uint32_t resume_handle=0;
5879 int i;
5880 #define ASYNC_COUNT 100
5881 struct rpc_request *req[ASYNC_COUNT];
5883 if (!torture_setting_bool(tctx, "dangerous", false)) {
5884 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
5887 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
5889 r.in.domain_handle = handle;
5890 r.in.resume_handle = &resume_handle;
5891 r.in.acct_flags = 0;
5892 r.in.max_size = (uint32_t)-1;
5893 r.out.resume_handle = &resume_handle;
5895 for (i=0;i<ASYNC_COUNT;i++) {
5896 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
5899 for (i=0;i<ASYNC_COUNT;i++) {
5900 status = dcerpc_ndr_request_recv(req[i]);
5901 if (!NT_STATUS_IS_OK(status)) {
5902 torture_warning(tctx, "EnumDomainUsers[%d] failed - %s\n",
5903 i, nt_errstr(status));
5904 return false;
5908 torture_comment(tctx, "%d async requests OK\n", i);
5910 return true;
5913 static bool test_EnumDomainGroups_all(struct dcerpc_pipe *p,
5914 struct torture_context *tctx,
5915 struct policy_handle *handle)
5917 NTSTATUS status;
5918 struct samr_EnumDomainGroups r;
5919 uint32_t resume_handle=0;
5920 struct samr_SamArray *sam = NULL;
5921 uint32_t num_entries = 0;
5922 int i;
5923 bool ret = true;
5925 torture_comment(tctx, "Testing EnumDomainGroups\n");
5927 r.in.domain_handle = handle;
5928 r.in.resume_handle = &resume_handle;
5929 r.in.max_size = (uint32_t)-1;
5930 r.out.resume_handle = &resume_handle;
5931 r.out.num_entries = &num_entries;
5932 r.out.sam = &sam;
5934 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
5935 if (!NT_STATUS_IS_OK(status)) {
5936 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(status));
5937 return false;
5940 if (!sam) {
5941 return false;
5944 for (i=0;i<sam->count;i++) {
5945 if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
5946 ret = false;
5950 return ret;
5953 static bool test_EnumDomainAliases_all(struct dcerpc_pipe *p,
5954 struct torture_context *tctx,
5955 struct policy_handle *handle)
5957 NTSTATUS status;
5958 struct samr_EnumDomainAliases r;
5959 uint32_t resume_handle=0;
5960 struct samr_SamArray *sam = NULL;
5961 uint32_t num_entries = 0;
5962 int i;
5963 bool ret = true;
5965 torture_comment(tctx, "Testing EnumDomainAliases\n");
5967 r.in.domain_handle = handle;
5968 r.in.resume_handle = &resume_handle;
5969 r.in.max_size = (uint32_t)-1;
5970 r.out.sam = &sam;
5971 r.out.num_entries = &num_entries;
5972 r.out.resume_handle = &resume_handle;
5974 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(status));
5977 return false;
5980 if (!sam) {
5981 return false;
5984 for (i=0;i<sam->count;i++) {
5985 if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
5986 ret = false;
5990 return ret;
5993 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
5994 struct torture_context *tctx,
5995 struct policy_handle *handle)
5997 NTSTATUS status;
5998 struct samr_GetDisplayEnumerationIndex r;
5999 bool ret = true;
6000 uint16_t levels[] = {1, 2, 3, 4, 5};
6001 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6002 struct lsa_String name;
6003 uint32_t idx = 0;
6004 int i;
6006 for (i=0;i<ARRAY_SIZE(levels);i++) {
6007 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6009 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6011 r.in.domain_handle = handle;
6012 r.in.level = levels[i];
6013 r.in.name = &name;
6014 r.out.idx = &idx;
6016 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
6018 if (ok_lvl[i] &&
6019 !NT_STATUS_IS_OK(status) &&
6020 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6021 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6022 levels[i], nt_errstr(status));
6023 ret = false;
6026 init_lsa_String(&name, "zzzzzzzz");
6028 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
6030 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6031 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6032 levels[i], nt_errstr(status));
6033 ret = false;
6037 return ret;
6040 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
6041 struct torture_context *tctx,
6042 struct policy_handle *handle)
6044 NTSTATUS status;
6045 struct samr_GetDisplayEnumerationIndex2 r;
6046 bool ret = true;
6047 uint16_t levels[] = {1, 2, 3, 4, 5};
6048 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6049 struct lsa_String name;
6050 uint32_t idx = 0;
6051 int i;
6053 for (i=0;i<ARRAY_SIZE(levels);i++) {
6054 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6056 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6058 r.in.domain_handle = handle;
6059 r.in.level = levels[i];
6060 r.in.name = &name;
6061 r.out.idx = &idx;
6063 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
6064 if (ok_lvl[i] &&
6065 !NT_STATUS_IS_OK(status) &&
6066 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6067 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6068 levels[i], nt_errstr(status));
6069 ret = false;
6072 init_lsa_String(&name, "zzzzzzzz");
6074 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
6075 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6076 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6077 levels[i], nt_errstr(status));
6078 ret = false;
6082 return ret;
6085 #define STRING_EQUAL_QUERY(s1, s2, user) \
6086 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6087 /* odd, but valid */ \
6088 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6089 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6090 #s1, user.string, s1.string, s2.string, __location__); \
6091 ret = false; \
6093 #define INT_EQUAL_QUERY(s1, s2, user) \
6094 if (s1 != s2) { \
6095 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6096 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6097 ret = false; \
6100 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
6101 struct torture_context *tctx,
6102 struct samr_QueryDisplayInfo *querydisplayinfo,
6103 bool *seen_testuser)
6105 struct samr_OpenUser r;
6106 struct samr_QueryUserInfo q;
6107 union samr_UserInfo *info;
6108 struct policy_handle user_handle;
6109 int i, ret = true;
6110 NTSTATUS status;
6111 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6112 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6113 for (i = 0; ; i++) {
6114 switch (querydisplayinfo->in.level) {
6115 case 1:
6116 if (i >= querydisplayinfo->out.info->info1.count) {
6117 return ret;
6119 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6120 break;
6121 case 2:
6122 if (i >= querydisplayinfo->out.info->info2.count) {
6123 return ret;
6125 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6126 break;
6127 case 3:
6128 /* Groups */
6129 case 4:
6130 case 5:
6131 /* Not interested in validating just the account name */
6132 return true;
6135 r.out.user_handle = &user_handle;
6137 switch (querydisplayinfo->in.level) {
6138 case 1:
6139 case 2:
6140 status = dcerpc_samr_OpenUser(p, tctx, &r);
6141 if (!NT_STATUS_IS_OK(status)) {
6142 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
6143 return false;
6147 q.in.user_handle = &user_handle;
6148 q.in.level = 21;
6149 q.out.info = &info;
6150 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
6151 if (!NT_STATUS_IS_OK(status)) {
6152 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
6153 return false;
6156 switch (querydisplayinfo->in.level) {
6157 case 1:
6158 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6159 *seen_testuser = true;
6161 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6162 info->info21.full_name, info->info21.account_name);
6163 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6164 info->info21.account_name, info->info21.account_name);
6165 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6166 info->info21.description, info->info21.account_name);
6167 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6168 info->info21.rid, info->info21.account_name);
6169 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6170 info->info21.acct_flags, info->info21.account_name);
6172 break;
6173 case 2:
6174 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6175 info->info21.account_name, info->info21.account_name);
6176 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6177 info->info21.description, info->info21.account_name);
6178 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6179 info->info21.rid, info->info21.account_name);
6180 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6181 info->info21.acct_flags, info->info21.account_name);
6183 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6184 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6185 info->info21.account_name.string);
6188 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6189 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6190 info->info21.account_name.string,
6191 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6192 info->info21.acct_flags);
6193 return false;
6196 break;
6199 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
6200 return false;
6203 return ret;
6206 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
6207 struct torture_context *tctx,
6208 struct policy_handle *handle)
6210 NTSTATUS status;
6211 struct samr_QueryDisplayInfo r;
6212 struct samr_QueryDomainInfo dom_info;
6213 union samr_DomainInfo *info = NULL;
6214 bool ret = true;
6215 uint16_t levels[] = {1, 2, 3, 4, 5};
6216 int i;
6217 bool seen_testuser = false;
6218 uint32_t total_size;
6219 uint32_t returned_size;
6220 union samr_DispInfo disp_info;
6223 for (i=0;i<ARRAY_SIZE(levels);i++) {
6224 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6226 r.in.start_idx = 0;
6227 status = STATUS_MORE_ENTRIES;
6228 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6229 r.in.domain_handle = handle;
6230 r.in.level = levels[i];
6231 r.in.max_entries = 2;
6232 r.in.buf_size = (uint32_t)-1;
6233 r.out.total_size = &total_size;
6234 r.out.returned_size = &returned_size;
6235 r.out.info = &disp_info;
6237 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6238 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
6239 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6240 levels[i], nt_errstr(status));
6241 ret = false;
6243 switch (r.in.level) {
6244 case 1:
6245 if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
6246 ret = false;
6248 r.in.start_idx += r.out.info->info1.count;
6249 break;
6250 case 2:
6251 if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
6252 ret = false;
6254 r.in.start_idx += r.out.info->info2.count;
6255 break;
6256 case 3:
6257 r.in.start_idx += r.out.info->info3.count;
6258 break;
6259 case 4:
6260 r.in.start_idx += r.out.info->info4.count;
6261 break;
6262 case 5:
6263 r.in.start_idx += r.out.info->info5.count;
6264 break;
6267 dom_info.in.domain_handle = handle;
6268 dom_info.in.level = 2;
6269 dom_info.out.info = &info;
6271 /* Check number of users returned is correct */
6272 status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
6273 if (!NT_STATUS_IS_OK(status)) {
6274 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6275 r.in.level, nt_errstr(status));
6276 ret = false;
6277 break;
6279 switch (r.in.level) {
6280 case 1:
6281 case 4:
6282 if (info->general.num_users < r.in.start_idx) {
6283 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6284 r.in.start_idx, info->general.num_groups,
6285 info->general.domain_name.string);
6286 ret = false;
6288 if (!seen_testuser) {
6289 struct policy_handle user_handle;
6290 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6291 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6292 info->general.domain_name.string);
6293 ret = false;
6294 test_samr_handle_Close(p, tctx, &user_handle);
6297 break;
6298 case 3:
6299 case 5:
6300 if (info->general.num_groups != r.in.start_idx) {
6301 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6302 r.in.start_idx, info->general.num_groups,
6303 info->general.domain_name.string);
6304 ret = false;
6307 break;
6312 return ret;
6315 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
6316 struct torture_context *tctx,
6317 struct policy_handle *handle)
6319 NTSTATUS status;
6320 struct samr_QueryDisplayInfo2 r;
6321 bool ret = true;
6322 uint16_t levels[] = {1, 2, 3, 4, 5};
6323 int i;
6324 uint32_t total_size;
6325 uint32_t returned_size;
6326 union samr_DispInfo info;
6328 for (i=0;i<ARRAY_SIZE(levels);i++) {
6329 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6331 r.in.domain_handle = handle;
6332 r.in.level = levels[i];
6333 r.in.start_idx = 0;
6334 r.in.max_entries = 1000;
6335 r.in.buf_size = (uint32_t)-1;
6336 r.out.total_size = &total_size;
6337 r.out.returned_size = &returned_size;
6338 r.out.info = &info;
6340 status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
6341 if (!NT_STATUS_IS_OK(status)) {
6342 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6343 levels[i], nt_errstr(status));
6344 ret = false;
6348 return ret;
6351 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
6352 struct policy_handle *handle)
6354 NTSTATUS status;
6355 struct samr_QueryDisplayInfo3 r;
6356 bool ret = true;
6357 uint16_t levels[] = {1, 2, 3, 4, 5};
6358 int i;
6359 uint32_t total_size;
6360 uint32_t returned_size;
6361 union samr_DispInfo info;
6363 for (i=0;i<ARRAY_SIZE(levels);i++) {
6364 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6366 r.in.domain_handle = handle;
6367 r.in.level = levels[i];
6368 r.in.start_idx = 0;
6369 r.in.max_entries = 1000;
6370 r.in.buf_size = (uint32_t)-1;
6371 r.out.total_size = &total_size;
6372 r.out.returned_size = &returned_size;
6373 r.out.info = &info;
6375 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
6376 if (!NT_STATUS_IS_OK(status)) {
6377 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6378 levels[i], nt_errstr(status));
6379 ret = false;
6383 return ret;
6387 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
6388 struct torture_context *tctx,
6389 struct policy_handle *handle)
6391 NTSTATUS status;
6392 struct samr_QueryDisplayInfo r;
6393 bool ret = true;
6394 uint32_t total_size;
6395 uint32_t returned_size;
6396 union samr_DispInfo info;
6398 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6400 r.in.domain_handle = handle;
6401 r.in.level = 1;
6402 r.in.start_idx = 0;
6403 r.in.max_entries = 1;
6404 r.in.buf_size = (uint32_t)-1;
6405 r.out.total_size = &total_size;
6406 r.out.returned_size = &returned_size;
6407 r.out.info = &info;
6409 do {
6410 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6411 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
6412 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6413 torture_warning(tctx, "expected idx %d but got %d\n",
6414 r.in.start_idx + 1,
6415 r.out.info->info1.entries[0].idx);
6416 break;
6419 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
6420 !NT_STATUS_IS_OK(status)) {
6421 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6422 r.in.level, nt_errstr(status));
6423 ret = false;
6424 break;
6426 r.in.start_idx++;
6427 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
6428 NT_STATUS_IS_OK(status)) &&
6429 *r.out.returned_size != 0);
6431 return ret;
6434 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
6435 struct policy_handle *handle)
6437 NTSTATUS status;
6438 struct samr_QueryDomainInfo r;
6439 union samr_DomainInfo *info = NULL;
6440 struct samr_SetDomainInfo s;
6441 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6442 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6443 int i;
6444 bool ret = true;
6445 const char *domain_comment = talloc_asprintf(tctx,
6446 "Tortured by Samba4 RPC-SAMR: %s",
6447 timestring(tctx, time(NULL)));
6449 s.in.domain_handle = handle;
6450 s.in.level = 4;
6451 s.in.info = talloc(tctx, union samr_DomainInfo);
6453 s.in.info->oem.oem_information.string = domain_comment;
6454 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6457 s.in.level, nt_errstr(status));
6458 return false;
6461 for (i=0;i<ARRAY_SIZE(levels);i++) {
6462 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6464 r.in.domain_handle = handle;
6465 r.in.level = levels[i];
6466 r.out.info = &info;
6468 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
6469 if (!NT_STATUS_IS_OK(status)) {
6470 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6471 r.in.level, nt_errstr(status));
6472 ret = false;
6473 continue;
6476 switch (levels[i]) {
6477 case 2:
6478 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6479 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6480 levels[i], info->general.oem_information.string, domain_comment);
6481 if (!torture_setting_bool(tctx, "samba3", false)) {
6482 ret = false;
6485 if (!info->general.primary.string) {
6486 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6487 levels[i]);
6488 ret = false;
6489 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6490 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6491 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6492 levels[i], info->general.primary.string, dcerpc_server_name(p));
6495 break;
6496 case 4:
6497 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6498 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6499 levels[i], info->oem.oem_information.string, domain_comment);
6500 if (!torture_setting_bool(tctx, "samba3", false)) {
6501 ret = false;
6504 break;
6505 case 6:
6506 if (!info->info6.primary.string) {
6507 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6508 levels[i]);
6509 ret = false;
6511 break;
6512 case 11:
6513 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6514 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6515 levels[i], info->general2.general.oem_information.string, domain_comment);
6516 if (!torture_setting_bool(tctx, "samba3", false)) {
6517 ret = false;
6520 break;
6523 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6525 s.in.domain_handle = handle;
6526 s.in.level = levels[i];
6527 s.in.info = info;
6529 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
6530 if (set_ok[i]) {
6531 if (!NT_STATUS_IS_OK(status)) {
6532 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6533 r.in.level, nt_errstr(status));
6534 ret = false;
6535 continue;
6537 } else {
6538 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
6539 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6540 r.in.level, nt_errstr(status));
6541 ret = false;
6542 continue;
6546 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
6547 if (!NT_STATUS_IS_OK(status)) {
6548 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6549 r.in.level, nt_errstr(status));
6550 ret = false;
6551 continue;
6555 return ret;
6559 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
6560 struct policy_handle *handle)
6562 NTSTATUS status;
6563 struct samr_QueryDomainInfo2 r;
6564 union samr_DomainInfo *info = NULL;
6565 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6566 int i;
6567 bool ret = true;
6569 for (i=0;i<ARRAY_SIZE(levels);i++) {
6570 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6572 r.in.domain_handle = handle;
6573 r.in.level = levels[i];
6574 r.out.info = &info;
6576 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
6577 if (!NT_STATUS_IS_OK(status)) {
6578 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6579 r.in.level, nt_errstr(status));
6580 ret = false;
6581 continue;
6585 return true;
6588 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6589 set of group names. */
6590 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
6591 struct policy_handle *handle)
6593 struct samr_EnumDomainGroups q1;
6594 struct samr_QueryDisplayInfo q2;
6595 NTSTATUS status;
6596 uint32_t resume_handle=0;
6597 struct samr_SamArray *sam = NULL;
6598 uint32_t num_entries = 0;
6599 int i;
6600 bool ret = true;
6601 uint32_t total_size;
6602 uint32_t returned_size;
6603 union samr_DispInfo info;
6605 int num_names = 0;
6606 const char **names = NULL;
6608 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6610 q1.in.domain_handle = handle;
6611 q1.in.resume_handle = &resume_handle;
6612 q1.in.max_size = 5;
6613 q1.out.resume_handle = &resume_handle;
6614 q1.out.num_entries = &num_entries;
6615 q1.out.sam = &sam;
6617 status = STATUS_MORE_ENTRIES;
6618 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6619 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
6621 if (!NT_STATUS_IS_OK(status) &&
6622 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6623 break;
6625 for (i=0; i<*q1.out.num_entries; i++) {
6626 add_string_to_array(tctx,
6627 sam->entries[i].name.string,
6628 &names, &num_names);
6632 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6634 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6636 q2.in.domain_handle = handle;
6637 q2.in.level = 5;
6638 q2.in.start_idx = 0;
6639 q2.in.max_entries = 5;
6640 q2.in.buf_size = (uint32_t)-1;
6641 q2.out.total_size = &total_size;
6642 q2.out.returned_size = &returned_size;
6643 q2.out.info = &info;
6645 status = STATUS_MORE_ENTRIES;
6646 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6647 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
6649 if (!NT_STATUS_IS_OK(status) &&
6650 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6651 break;
6653 for (i=0; i<q2.out.info->info5.count; i++) {
6654 int j;
6655 const char *name = q2.out.info->info5.entries[i].account_name.string;
6656 bool found = false;
6657 for (j=0; j<num_names; j++) {
6658 if (names[j] == NULL)
6659 continue;
6660 if (strequal(names[j], name)) {
6661 names[j] = NULL;
6662 found = true;
6663 break;
6667 if (!found) {
6668 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
6669 name);
6670 ret = false;
6673 q2.in.start_idx += q2.out.info->info5.count;
6676 if (!NT_STATUS_IS_OK(status)) {
6677 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
6678 nt_errstr(status));
6679 ret = false;
6682 for (i=0; i<num_names; i++) {
6683 if (names[i] != NULL) {
6684 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
6685 names[i]);
6686 ret = false;
6690 return ret;
6693 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
6694 struct policy_handle *group_handle)
6696 struct samr_DeleteDomainGroup d;
6697 NTSTATUS status;
6699 torture_comment(tctx, "Testing DeleteDomainGroup\n");
6701 d.in.group_handle = group_handle;
6702 d.out.group_handle = group_handle;
6704 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
6705 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
6707 return true;
6710 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6711 struct policy_handle *domain_handle)
6713 struct samr_TestPrivateFunctionsDomain r;
6714 NTSTATUS status;
6715 bool ret = true;
6717 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
6719 r.in.domain_handle = domain_handle;
6721 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
6722 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
6724 return ret;
6727 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
6728 struct dom_sid *domain_sid,
6729 struct policy_handle *domain_handle)
6731 struct samr_RidToSid r;
6732 NTSTATUS status;
6733 bool ret = true;
6734 struct dom_sid *calc_sid, *out_sid;
6735 int rids[] = { 0, 42, 512, 10200 };
6736 int i;
6738 for (i=0;i<ARRAY_SIZE(rids);i++) {
6739 torture_comment(tctx, "Testing RidToSid\n");
6741 calc_sid = dom_sid_dup(tctx, domain_sid);
6742 r.in.domain_handle = domain_handle;
6743 r.in.rid = rids[i];
6744 r.out.sid = &out_sid;
6746 status = dcerpc_samr_RidToSid(p, tctx, &r);
6747 if (!NT_STATUS_IS_OK(status)) {
6748 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
6749 ret = false;
6750 } else {
6751 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
6753 if (!dom_sid_equal(calc_sid, out_sid)) {
6754 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
6755 dom_sid_string(tctx, out_sid),
6756 dom_sid_string(tctx, calc_sid));
6757 ret = false;
6762 return ret;
6765 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
6766 struct policy_handle *domain_handle)
6768 struct samr_GetBootKeyInformation r;
6769 NTSTATUS status;
6770 bool ret = true;
6771 uint32_t unknown = 0;
6773 torture_comment(tctx, "Testing GetBootKeyInformation\n");
6775 r.in.domain_handle = domain_handle;
6776 r.out.unknown = &unknown;
6778 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
6779 if (!NT_STATUS_IS_OK(status)) {
6780 /* w2k3 seems to fail this sometimes and pass it sometimes */
6781 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
6784 return ret;
6787 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
6788 struct policy_handle *domain_handle,
6789 struct policy_handle *group_handle)
6791 NTSTATUS status;
6792 struct samr_AddGroupMember r;
6793 struct samr_DeleteGroupMember d;
6794 struct samr_QueryGroupMember q;
6795 struct samr_RidTypeArray *rids = NULL;
6796 struct samr_SetMemberAttributesOfGroup s;
6797 uint32_t rid;
6798 bool found_member = false;
6799 int i;
6801 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
6802 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
6804 r.in.group_handle = group_handle;
6805 r.in.rid = rid;
6806 r.in.flags = 0; /* ??? */
6808 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
6810 d.in.group_handle = group_handle;
6811 d.in.rid = rid;
6813 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
6814 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
6816 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6817 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6819 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6820 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
6822 if (torture_setting_bool(tctx, "samba4", false) ||
6823 torture_setting_bool(tctx, "samba3", false)) {
6824 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
6825 } else {
6826 /* this one is quite strange. I am using random inputs in the
6827 hope of triggering an error that might give us a clue */
6829 s.in.group_handle = group_handle;
6830 s.in.unknown1 = random();
6831 s.in.unknown2 = random();
6833 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
6834 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
6837 q.in.group_handle = group_handle;
6838 q.out.rids = &rids;
6840 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
6841 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6842 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6844 for (i=0; i < rids->count; i++) {
6845 if (rids->rids[i] == rid) {
6846 found_member = true;
6850 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
6852 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
6853 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
6855 rids = NULL;
6856 found_member = false;
6858 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
6859 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6860 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6862 for (i=0; i < rids->count; i++) {
6863 if (rids->rids[i] == rid) {
6864 found_member = true;
6868 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
6870 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6871 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6873 return true;
6877 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
6878 struct torture_context *tctx,
6879 struct policy_handle *domain_handle,
6880 const char *group_name,
6881 struct policy_handle *group_handle,
6882 struct dom_sid *domain_sid,
6883 bool test_group)
6885 NTSTATUS status;
6886 struct samr_CreateDomainGroup r;
6887 uint32_t rid;
6888 struct lsa_String name;
6889 bool ret = true;
6891 init_lsa_String(&name, group_name);
6893 r.in.domain_handle = domain_handle;
6894 r.in.name = &name;
6895 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6896 r.out.group_handle = group_handle;
6897 r.out.rid = &rid;
6899 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
6901 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6903 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6904 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6905 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
6906 return true;
6907 } else {
6908 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
6909 nt_errstr(status));
6910 return false;
6914 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
6915 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
6916 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
6917 nt_errstr(status));
6918 return false;
6920 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6922 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
6923 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
6925 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
6926 nt_errstr(status));
6927 return false;
6929 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6931 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
6933 if (!test_group) {
6934 return ret;
6937 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
6938 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(status));
6939 ret = false;
6942 if (!test_SetGroupInfo(p, tctx, group_handle)) {
6943 ret = false;
6946 return ret;
6951 its not totally clear what this does. It seems to accept any sid you like.
6953 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
6954 struct torture_context *tctx,
6955 struct policy_handle *domain_handle)
6957 NTSTATUS status;
6958 struct samr_RemoveMemberFromForeignDomain r;
6960 r.in.domain_handle = domain_handle;
6961 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
6963 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
6964 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
6966 return true;
6969 static bool test_EnumDomainUsers(struct dcerpc_pipe *p,
6970 struct torture_context *tctx,
6971 struct policy_handle *domain_handle,
6972 uint32_t *total_num_entries_p)
6974 NTSTATUS status;
6975 struct samr_EnumDomainUsers r;
6976 uint32_t resume_handle = 0;
6977 uint32_t num_entries = 0;
6978 uint32_t total_num_entries = 0;
6979 struct samr_SamArray *sam;
6981 r.in.domain_handle = domain_handle;
6982 r.in.acct_flags = 0;
6983 r.in.max_size = (uint32_t)-1;
6984 r.in.resume_handle = &resume_handle;
6986 r.out.sam = &sam;
6987 r.out.num_entries = &num_entries;
6988 r.out.resume_handle = &resume_handle;
6990 torture_comment(tctx, "Testing EnumDomainUsers\n");
6992 do {
6993 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
6994 if (NT_STATUS_IS_ERR(status)) {
6995 torture_assert_ntstatus_ok(tctx, status,
6996 "failed to enumerate users");
6999 total_num_entries += num_entries;
7000 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7002 if (total_num_entries_p) {
7003 *total_num_entries_p = total_num_entries;
7006 return true;
7009 static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
7010 struct torture_context *tctx,
7011 struct policy_handle *domain_handle,
7012 uint32_t *total_num_entries_p)
7014 NTSTATUS status;
7015 struct samr_EnumDomainGroups r;
7016 uint32_t resume_handle = 0;
7017 uint32_t num_entries = 0;
7018 uint32_t total_num_entries = 0;
7019 struct samr_SamArray *sam;
7021 r.in.domain_handle = domain_handle;
7022 r.in.max_size = (uint32_t)-1;
7023 r.in.resume_handle = &resume_handle;
7025 r.out.sam = &sam;
7026 r.out.num_entries = &num_entries;
7027 r.out.resume_handle = &resume_handle;
7029 torture_comment(tctx, "Testing EnumDomainGroups\n");
7031 do {
7032 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
7033 if (NT_STATUS_IS_ERR(status)) {
7034 torture_assert_ntstatus_ok(tctx, status,
7035 "failed to enumerate groups");
7038 total_num_entries += num_entries;
7039 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7041 if (total_num_entries_p) {
7042 *total_num_entries_p = total_num_entries;
7045 return true;
7048 static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
7049 struct torture_context *tctx,
7050 struct policy_handle *domain_handle,
7051 uint32_t *total_num_entries_p)
7053 NTSTATUS status;
7054 struct samr_EnumDomainAliases r;
7055 uint32_t resume_handle = 0;
7056 uint32_t num_entries = 0;
7057 uint32_t total_num_entries = 0;
7058 struct samr_SamArray *sam;
7060 r.in.domain_handle = domain_handle;
7061 r.in.max_size = (uint32_t)-1;
7062 r.in.resume_handle = &resume_handle;
7064 r.out.sam = &sam;
7065 r.out.num_entries = &num_entries;
7066 r.out.resume_handle = &resume_handle;
7068 torture_comment(tctx, "Testing EnumDomainAliases\n");
7070 do {
7071 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
7072 if (NT_STATUS_IS_ERR(status)) {
7073 torture_assert_ntstatus_ok(tctx, status,
7074 "failed to enumerate aliases");
7077 total_num_entries += num_entries;
7078 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7080 if (total_num_entries_p) {
7081 *total_num_entries_p = total_num_entries;
7084 return true;
7087 static bool test_QueryDisplayInfo_level(struct dcerpc_pipe *p,
7088 struct torture_context *tctx,
7089 struct policy_handle *handle,
7090 uint16_t level,
7091 uint32_t *total_num_entries_p)
7093 NTSTATUS status;
7094 struct samr_QueryDisplayInfo r;
7095 uint32_t total_num_entries = 0;
7097 r.in.domain_handle = handle;
7098 r.in.level = level;
7099 r.in.start_idx = 0;
7100 r.in.max_entries = (uint32_t)-1;
7101 r.in.buf_size = (uint32_t)-1;
7103 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7105 do {
7106 uint32_t total_size;
7107 uint32_t returned_size;
7108 union samr_DispInfo info;
7110 r.out.total_size = &total_size;
7111 r.out.returned_size = &returned_size;
7112 r.out.info = &info;
7114 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
7115 if (NT_STATUS_IS_ERR(status)) {
7116 torture_assert_ntstatus_ok(tctx, status,
7117 "failed to query displayinfo");
7120 if (*r.out.returned_size == 0) {
7121 break;
7124 switch (r.in.level) {
7125 case 1:
7126 total_num_entries += info.info1.count;
7127 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7128 break;
7129 case 2:
7130 total_num_entries += info.info2.count;
7131 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7132 break;
7133 case 3:
7134 total_num_entries += info.info3.count;
7135 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7136 break;
7137 case 4:
7138 total_num_entries += info.info4.count;
7139 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7140 break;
7141 case 5:
7142 total_num_entries += info.info5.count;
7143 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7144 break;
7145 default:
7146 return false;
7149 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7151 if (total_num_entries_p) {
7152 *total_num_entries_p = total_num_entries;
7155 return true;
7158 static bool test_ManyObjects(struct dcerpc_pipe *p,
7159 struct torture_context *tctx,
7160 struct policy_handle *domain_handle,
7161 struct dom_sid *domain_sid,
7162 struct torture_samr_context *ctx)
7164 uint32_t num_total = ctx->num_objects_large_dc;
7165 uint32_t num_enum = 0;
7166 uint32_t num_disp = 0;
7167 uint32_t num_created = 0;
7168 uint32_t num_anounced = 0;
7169 bool ret = true;
7170 NTSTATUS status;
7171 uint32_t i;
7173 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7175 /* query */
7178 struct samr_QueryDomainInfo2 r;
7179 union samr_DomainInfo *info;
7180 r.in.domain_handle = domain_handle;
7181 r.in.level = 2;
7182 r.out.info = &info;
7184 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
7185 torture_assert_ntstatus_ok(tctx, status,
7186 "failed to query domain info");
7188 switch (ctx->choice) {
7189 case TORTURE_SAMR_MANY_ACCOUNTS:
7190 num_anounced = info->general.num_users;
7191 break;
7192 case TORTURE_SAMR_MANY_GROUPS:
7193 num_anounced = info->general.num_groups;
7194 break;
7195 case TORTURE_SAMR_MANY_ALIASES:
7196 num_anounced = info->general.num_aliases;
7197 break;
7198 default:
7199 return false;
7203 /* create */
7205 for (i=0; i < num_total; i++) {
7207 const char *name = NULL;
7209 switch (ctx->choice) {
7210 case TORTURE_SAMR_MANY_ACCOUNTS:
7211 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7212 ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
7213 break;
7214 case TORTURE_SAMR_MANY_GROUPS:
7215 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7216 ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
7217 break;
7218 case TORTURE_SAMR_MANY_ALIASES:
7219 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7220 ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
7221 break;
7222 default:
7223 return false;
7225 if (!policy_handle_empty(&handles[i])) {
7226 num_created++;
7230 /* enum */
7232 switch (ctx->choice) {
7233 case TORTURE_SAMR_MANY_ACCOUNTS:
7234 ret &= test_EnumDomainUsers(p, tctx, domain_handle, &num_enum);
7235 break;
7236 case TORTURE_SAMR_MANY_GROUPS:
7237 ret &= test_EnumDomainGroups(p, tctx, domain_handle, &num_enum);
7238 break;
7239 case TORTURE_SAMR_MANY_ALIASES:
7240 ret &= test_EnumDomainAliases(p, tctx, domain_handle, &num_enum);
7241 break;
7242 default:
7243 return false;
7246 /* dispinfo */
7248 switch (ctx->choice) {
7249 case TORTURE_SAMR_MANY_ACCOUNTS:
7250 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 1, &num_disp);
7251 break;
7252 case TORTURE_SAMR_MANY_GROUPS:
7253 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 3, &num_disp);
7254 break;
7255 case TORTURE_SAMR_MANY_ALIASES:
7256 /* no aliases in dispinfo */
7257 break;
7258 default:
7259 return false;
7262 /* close or delete */
7264 for (i=0; i < num_total; i++) {
7266 if (policy_handle_empty(&handles[i])) {
7267 continue;
7270 if (torture_setting_bool(tctx, "samba3", false)) {
7271 ret &= test_samr_handle_Close(p, tctx, &handles[i]);
7272 } else {
7273 switch (ctx->choice) {
7274 case TORTURE_SAMR_MANY_ACCOUNTS:
7275 ret &= test_DeleteUser(p, tctx, &handles[i]);
7276 break;
7277 case TORTURE_SAMR_MANY_GROUPS:
7278 ret &= test_DeleteDomainGroup(p, tctx, &handles[i]);
7279 break;
7280 case TORTURE_SAMR_MANY_ALIASES:
7281 ret &= test_DeleteAlias(p, tctx, &handles[i]);
7282 break;
7283 default:
7284 return false;
7289 talloc_free(handles);
7291 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7292 torture_comment(tctx,
7293 "unexpected number of results (%u) returned in enum call, expected %u\n",
7294 num_enum, num_anounced + num_created);
7296 torture_comment(tctx,
7297 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7298 num_disp, num_anounced + num_created);
7300 return ret;
7303 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
7304 struct policy_handle *handle);
7306 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7307 struct torture_samr_context *ctx, struct dom_sid *sid)
7309 NTSTATUS status;
7310 struct samr_OpenDomain r;
7311 struct policy_handle domain_handle;
7312 struct policy_handle alias_handle;
7313 struct policy_handle user_handle;
7314 struct policy_handle group_handle;
7315 bool ret = true;
7317 ZERO_STRUCT(alias_handle);
7318 ZERO_STRUCT(user_handle);
7319 ZERO_STRUCT(group_handle);
7320 ZERO_STRUCT(domain_handle);
7322 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7324 r.in.connect_handle = &ctx->handle;
7325 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7326 r.in.sid = sid;
7327 r.out.domain_handle = &domain_handle;
7329 status = dcerpc_samr_OpenDomain(p, tctx, &r);
7330 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
7332 /* run the domain tests with the main handle closed - this tests
7333 the servers reference counting */
7334 torture_assert(tctx, test_samr_handle_Close(p, tctx, &ctx->handle), "Failed to close SAMR handle");
7336 switch (ctx->choice) {
7337 case TORTURE_SAMR_PASSWORDS:
7338 case TORTURE_SAMR_USER_PRIVILEGES:
7339 if (!torture_setting_bool(tctx, "samba3", false)) {
7340 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7342 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7343 if (!ret) {
7344 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7346 break;
7347 case TORTURE_SAMR_USER_ATTRIBUTES:
7348 if (!torture_setting_bool(tctx, "samba3", false)) {
7349 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7351 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7352 /* This test needs 'complex' users to validate */
7353 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
7354 if (!ret) {
7355 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7357 break;
7358 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7359 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7360 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7361 if (!torture_setting_bool(tctx, "samba3", false)) {
7362 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7364 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7365 if (!ret) {
7366 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7368 break;
7369 case TORTURE_SAMR_MANY_ACCOUNTS:
7370 case TORTURE_SAMR_MANY_GROUPS:
7371 case TORTURE_SAMR_MANY_ALIASES:
7372 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7373 if (!ret) {
7374 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7376 break;
7377 case TORTURE_SAMR_OTHER:
7378 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7379 if (!ret) {
7380 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7382 if (!torture_setting_bool(tctx, "samba3", false)) {
7383 ret &= test_QuerySecurity(p, tctx, &domain_handle);
7385 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
7386 ret &= test_CreateAlias(p, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7387 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7388 ret &= test_GetAliasMembership(p, tctx, &domain_handle);
7389 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7390 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
7391 ret &= test_EnumDomainUsers_all(p, tctx, &domain_handle);
7392 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7393 ret &= test_EnumDomainGroups_all(p, tctx, &domain_handle);
7394 ret &= test_EnumDomainAliases_all(p, tctx, &domain_handle);
7395 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
7396 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
7397 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
7399 if (torture_setting_bool(tctx, "samba4", false)) {
7400 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7401 } else {
7402 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
7403 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
7405 ret &= test_GroupList(p, tctx, &domain_handle);
7406 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
7407 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
7408 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
7409 if (!ret) {
7410 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7412 break;
7415 if (!policy_handle_empty(&user_handle) &&
7416 !test_DeleteUser(p, tctx, &user_handle)) {
7417 ret = false;
7420 if (!policy_handle_empty(&alias_handle) &&
7421 !test_DeleteAlias(p, tctx, &alias_handle)) {
7422 ret = false;
7425 if (!policy_handle_empty(&group_handle) &&
7426 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
7427 ret = false;
7430 torture_assert(tctx, test_samr_handle_Close(p, tctx, &domain_handle), "Failed to close SAMR domain handle");
7432 torture_assert(tctx, test_Connect(p, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7433 /* reconnect the main handle */
7435 if (!ret) {
7436 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7439 return ret;
7442 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7443 struct torture_samr_context *ctx, const char *domain)
7445 NTSTATUS status;
7446 struct samr_LookupDomain r;
7447 struct dom_sid2 *sid = NULL;
7448 struct lsa_String n1;
7449 struct lsa_String n2;
7450 bool ret = true;
7452 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7454 /* check for correct error codes */
7455 r.in.connect_handle = &ctx->handle;
7456 r.in.domain_name = &n2;
7457 r.out.sid = &sid;
7458 n2.string = NULL;
7460 status = dcerpc_samr_LookupDomain(p, tctx, &r);
7461 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7463 init_lsa_String(&n2, "xxNODOMAINxx");
7465 status = dcerpc_samr_LookupDomain(p, tctx, &r);
7466 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7468 r.in.connect_handle = &ctx->handle;
7470 init_lsa_String(&n1, domain);
7471 r.in.domain_name = &n1;
7473 status = dcerpc_samr_LookupDomain(p, tctx, &r);
7474 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
7476 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7477 ret = false;
7480 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7481 ret = false;
7484 return ret;
7488 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7489 struct torture_samr_context *ctx)
7491 NTSTATUS status;
7492 struct samr_EnumDomains r;
7493 uint32_t resume_handle = 0;
7494 uint32_t num_entries = 0;
7495 struct samr_SamArray *sam = NULL;
7496 int i;
7497 bool ret = true;
7499 r.in.connect_handle = &ctx->handle;
7500 r.in.resume_handle = &resume_handle;
7501 r.in.buf_size = (uint32_t)-1;
7502 r.out.resume_handle = &resume_handle;
7503 r.out.num_entries = &num_entries;
7504 r.out.sam = &sam;
7506 status = dcerpc_samr_EnumDomains(p, tctx, &r);
7507 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
7509 if (!*r.out.sam) {
7510 return false;
7513 for (i=0;i<sam->count;i++) {
7514 if (!test_LookupDomain(p, tctx, ctx,
7515 sam->entries[i].name.string)) {
7516 ret = false;
7520 status = dcerpc_samr_EnumDomains(p, tctx, &r);
7521 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
7523 return ret;
7527 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
7528 struct policy_handle *handle)
7530 NTSTATUS status;
7531 struct samr_Connect r;
7532 struct samr_Connect2 r2;
7533 struct samr_Connect3 r3;
7534 struct samr_Connect4 r4;
7535 struct samr_Connect5 r5;
7536 union samr_ConnectInfo info;
7537 struct policy_handle h;
7538 uint32_t level_out = 0;
7539 bool ret = true, got_handle = false;
7541 torture_comment(tctx, "testing samr_Connect\n");
7543 r.in.system_name = 0;
7544 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7545 r.out.connect_handle = &h;
7547 status = dcerpc_samr_Connect(p, tctx, &r);
7548 if (!NT_STATUS_IS_OK(status)) {
7549 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
7550 ret = false;
7551 } else {
7552 got_handle = true;
7553 *handle = h;
7556 torture_comment(tctx, "testing samr_Connect2\n");
7558 r2.in.system_name = NULL;
7559 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7560 r2.out.connect_handle = &h;
7562 status = dcerpc_samr_Connect2(p, tctx, &r2);
7563 if (!NT_STATUS_IS_OK(status)) {
7564 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
7565 ret = false;
7566 } else {
7567 if (got_handle) {
7568 test_samr_handle_Close(p, tctx, handle);
7570 got_handle = true;
7571 *handle = h;
7574 torture_comment(tctx, "testing samr_Connect3\n");
7576 r3.in.system_name = NULL;
7577 r3.in.unknown = 0;
7578 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7579 r3.out.connect_handle = &h;
7581 status = dcerpc_samr_Connect3(p, tctx, &r3);
7582 if (!NT_STATUS_IS_OK(status)) {
7583 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(status));
7584 ret = false;
7585 } else {
7586 if (got_handle) {
7587 test_samr_handle_Close(p, tctx, handle);
7589 got_handle = true;
7590 *handle = h;
7593 torture_comment(tctx, "testing samr_Connect4\n");
7595 r4.in.system_name = "";
7596 r4.in.client_version = 0;
7597 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7598 r4.out.connect_handle = &h;
7600 status = dcerpc_samr_Connect4(p, tctx, &r4);
7601 if (!NT_STATUS_IS_OK(status)) {
7602 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(status));
7603 ret = false;
7604 } else {
7605 if (got_handle) {
7606 test_samr_handle_Close(p, tctx, handle);
7608 got_handle = true;
7609 *handle = h;
7612 torture_comment(tctx, "testing samr_Connect5\n");
7614 info.info1.client_version = 0;
7615 info.info1.unknown2 = 0;
7617 r5.in.system_name = "";
7618 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7619 r5.in.level_in = 1;
7620 r5.out.level_out = &level_out;
7621 r5.in.info_in = &info;
7622 r5.out.info_out = &info;
7623 r5.out.connect_handle = &h;
7625 status = dcerpc_samr_Connect5(p, tctx, &r5);
7626 if (!NT_STATUS_IS_OK(status)) {
7627 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(status));
7628 ret = false;
7629 } else {
7630 if (got_handle) {
7631 test_samr_handle_Close(p, tctx, handle);
7633 got_handle = true;
7634 *handle = h;
7637 return ret;
7641 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p, struct torture_context *tctx)
7643 struct samr_ValidatePassword r;
7644 union samr_ValidatePasswordReq req;
7645 union samr_ValidatePasswordRep *repp = NULL;
7646 NTSTATUS status;
7647 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
7648 int i;
7650 torture_comment(tctx, "testing samr_ValidatePassword\n");
7652 ZERO_STRUCT(r);
7653 r.in.level = NetValidatePasswordReset;
7654 r.in.req = &req;
7655 r.out.rep = &repp;
7657 ZERO_STRUCT(req);
7658 req.req3.account.string = "non-existant-account-aklsdji";
7660 for (i=0; passwords[i]; i++) {
7661 req.req3.password.string = passwords[i];
7662 status = dcerpc_samr_ValidatePassword(p, tctx, &r);
7663 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT) &&
7664 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
7665 torture_skip(tctx, "ValidatePassword not supported by server\n");
7667 torture_assert_ntstatus_ok(tctx, status, "samr_ValidatePassword");
7668 torture_comment(tctx, "Server %s password '%s' with code %i\n",
7669 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
7670 req.req3.password.string, repp->ctr3.status);
7673 return true;
7676 bool torture_rpc_samr(struct torture_context *torture)
7678 NTSTATUS status;
7679 struct dcerpc_pipe *p;
7680 bool ret = true;
7681 struct torture_samr_context *ctx;
7683 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7684 if (!NT_STATUS_IS_OK(status)) {
7685 return false;
7688 ctx = talloc_zero(torture, struct torture_samr_context);
7690 ctx->choice = TORTURE_SAMR_OTHER;
7692 ret &= test_Connect(p, torture, &ctx->handle);
7694 if (!torture_setting_bool(torture, "samba3", false)) {
7695 ret &= test_QuerySecurity(p, torture, &ctx->handle);
7698 ret &= test_EnumDomains(p, torture, ctx);
7700 ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
7702 ret &= test_Shutdown(p, torture, &ctx->handle);
7704 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7706 return ret;
7710 bool torture_rpc_samr_users(struct torture_context *torture)
7712 NTSTATUS status;
7713 struct dcerpc_pipe *p;
7714 bool ret = true;
7715 struct torture_samr_context *ctx;
7717 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7718 if (!NT_STATUS_IS_OK(status)) {
7719 return false;
7722 ctx = talloc_zero(torture, struct torture_samr_context);
7724 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
7726 ret &= test_Connect(p, torture, &ctx->handle);
7728 if (!torture_setting_bool(torture, "samba3", false)) {
7729 ret &= test_QuerySecurity(p, torture, &ctx->handle);
7732 ret &= test_EnumDomains(p, torture, ctx);
7734 ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
7736 ret &= test_Shutdown(p, torture, &ctx->handle);
7738 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7740 return ret;
7744 bool torture_rpc_samr_passwords(struct torture_context *torture)
7746 NTSTATUS status;
7747 struct dcerpc_pipe *p;
7748 bool ret = true;
7749 struct torture_samr_context *ctx;
7751 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7752 if (!NT_STATUS_IS_OK(status)) {
7753 return false;
7756 ctx = talloc_zero(torture, struct torture_samr_context);
7758 ctx->choice = TORTURE_SAMR_PASSWORDS;
7760 ret &= test_Connect(p, torture, &ctx->handle);
7762 ret &= test_EnumDomains(p, torture, ctx);
7764 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7766 ret &= test_samr_ValidatePassword(p, torture);
7768 return ret;
7771 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
7772 struct dcerpc_pipe *p2,
7773 struct cli_credentials *machine_credentials)
7775 NTSTATUS status;
7776 struct dcerpc_pipe *p;
7777 bool ret = true;
7778 struct torture_samr_context *ctx;
7780 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7781 if (!NT_STATUS_IS_OK(status)) {
7782 return false;
7785 ctx = talloc_zero(torture, struct torture_samr_context);
7787 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
7788 ctx->machine_credentials = machine_credentials;
7790 ret &= test_Connect(p, torture, &ctx->handle);
7792 ret &= test_EnumDomains(p, torture, ctx);
7794 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7796 return ret;
7799 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
7801 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
7802 struct torture_rpc_tcase *tcase;
7804 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7805 &ndr_table_samr,
7806 TEST_ACCOUNT_NAME_PWD);
7808 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
7809 torture_rpc_samr_pwdlastset);
7811 return suite;
7814 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
7815 struct dcerpc_pipe *p2,
7816 struct cli_credentials *machine_credentials)
7818 NTSTATUS status;
7819 struct dcerpc_pipe *p;
7820 bool ret = true;
7821 struct torture_samr_context *ctx;
7823 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7824 if (!NT_STATUS_IS_OK(status)) {
7825 return false;
7828 ctx = talloc_zero(torture, struct torture_samr_context);
7830 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
7831 ctx->machine_credentials = machine_credentials;
7833 ret &= test_Connect(p, torture, &ctx->handle);
7835 ret &= test_EnumDomains(p, torture, ctx);
7837 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7839 return ret;
7842 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
7844 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
7845 struct torture_rpc_tcase *tcase;
7847 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7848 &ndr_table_samr,
7849 TEST_ACCOUNT_NAME_PWD);
7851 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
7852 torture_rpc_samr_users_privileges_delete_user);
7854 return suite;
7857 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
7858 struct dcerpc_pipe *p2,
7859 void *data)
7861 NTSTATUS status;
7862 struct dcerpc_pipe *p;
7863 bool ret = true;
7864 struct torture_samr_context *ctx =
7865 talloc_get_type_abort(data, struct torture_samr_context);
7867 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7868 if (!NT_STATUS_IS_OK(status)) {
7869 return false;
7872 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
7873 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7874 ctx->num_objects_large_dc);
7876 ret &= test_Connect(p, torture, &ctx->handle);
7878 ret &= test_EnumDomains(p, torture, ctx);
7880 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7882 return ret;
7885 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
7886 struct dcerpc_pipe *p2,
7887 void *data)
7889 NTSTATUS status;
7890 struct dcerpc_pipe *p;
7891 bool ret = true;
7892 struct torture_samr_context *ctx =
7893 talloc_get_type_abort(data, struct torture_samr_context);
7895 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7896 if (!NT_STATUS_IS_OK(status)) {
7897 return false;
7900 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
7901 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7902 ctx->num_objects_large_dc);
7904 ret &= test_Connect(p, torture, &ctx->handle);
7906 ret &= test_EnumDomains(p, torture, ctx);
7908 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7910 return ret;
7913 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
7914 struct dcerpc_pipe *p2,
7915 void *data)
7917 NTSTATUS status;
7918 struct dcerpc_pipe *p;
7919 bool ret = true;
7920 struct torture_samr_context *ctx =
7921 talloc_get_type_abort(data, struct torture_samr_context);
7923 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7924 if (!NT_STATUS_IS_OK(status)) {
7925 return false;
7928 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
7929 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7930 ctx->num_objects_large_dc);
7932 ret &= test_Connect(p, torture, &ctx->handle);
7934 ret &= test_EnumDomains(p, torture, ctx);
7936 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7938 return ret;
7941 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
7943 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
7944 struct torture_rpc_tcase *tcase;
7945 struct torture_samr_context *ctx;
7947 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
7949 ctx = talloc_zero(suite, struct torture_samr_context);
7950 ctx->num_objects_large_dc = 150;
7952 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
7953 torture_rpc_samr_many_aliases, ctx);
7954 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
7955 torture_rpc_samr_many_groups, ctx);
7956 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
7957 torture_rpc_samr_many_accounts, ctx);
7959 return suite;
7962 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
7963 struct dcerpc_pipe *p2,
7964 struct cli_credentials *machine_credentials)
7966 NTSTATUS status;
7967 struct dcerpc_pipe *p;
7968 bool ret = true;
7969 struct torture_samr_context *ctx;
7971 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7972 if (!NT_STATUS_IS_OK(status)) {
7973 return false;
7976 ctx = talloc_zero(torture, struct torture_samr_context);
7978 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
7979 ctx->machine_credentials = machine_credentials;
7981 ret &= test_Connect(p, torture, &ctx->handle);
7983 ret &= test_EnumDomains(p, torture, ctx);
7985 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7987 return ret;
7990 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
7992 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-BADPWDCOUNT");
7993 struct torture_rpc_tcase *tcase;
7995 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7996 &ndr_table_samr,
7997 TEST_ACCOUNT_NAME_PWD);
7999 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8000 torture_rpc_samr_badpwdcount);
8002 return suite;
8005 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8006 struct dcerpc_pipe *p2,
8007 struct cli_credentials *machine_credentials)
8009 NTSTATUS status;
8010 struct dcerpc_pipe *p;
8011 bool ret = true;
8012 struct torture_samr_context *ctx;
8014 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8015 if (!NT_STATUS_IS_OK(status)) {
8016 return false;
8019 ctx = talloc_zero(torture, struct torture_samr_context);
8021 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8022 ctx->machine_credentials = machine_credentials;
8024 ret &= test_Connect(p, torture, &ctx->handle);
8026 ret &= test_EnumDomains(p, torture, ctx);
8028 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
8030 return ret;
8033 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8035 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-LOCKOUT");
8036 struct torture_rpc_tcase *tcase;
8038 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8039 &ndr_table_samr,
8040 TEST_ACCOUNT_NAME_PWD);
8042 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8043 torture_rpc_samr_lockout);
8045 return suite;