s4:torture: refactor querying of domain info out into test_QueryDomainInfo2_level()
[Samba/gebeck_regimport.git] / source4 / torture / rpc / samr.c
blob4ab4a2cdc7e6e5211d32042aefcc964008284f22
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"
39 #include "auth/gensec/schannel_state.h"
41 #include <unistd.h>
43 #define TEST_ACCOUNT_NAME "samrtorturetest"
44 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
45 #define TEST_ALIASNAME "samrtorturetestalias"
46 #define TEST_GROUPNAME "samrtorturetestgroup"
47 #define TEST_MACHINENAME "samrtestmach$"
48 #define TEST_DOMAINNAME "samrtestdom$"
50 enum torture_samr_choice {
51 TORTURE_SAMR_PASSWORDS,
52 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
53 TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
54 TORTURE_SAMR_PASSWORDS_LOCKOUT,
55 TORTURE_SAMR_USER_ATTRIBUTES,
56 TORTURE_SAMR_USER_PRIVILEGES,
57 TORTURE_SAMR_OTHER,
58 TORTURE_SAMR_MANY_ACCOUNTS,
59 TORTURE_SAMR_MANY_GROUPS,
60 TORTURE_SAMR_MANY_ALIASES
63 struct torture_samr_context {
64 struct policy_handle handle;
65 struct cli_credentials *machine_credentials;
66 enum torture_samr_choice choice;
67 uint32_t num_objects_large_dc;
70 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
71 struct torture_context *tctx,
72 struct policy_handle *handle);
74 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
75 struct torture_context *tctx,
76 struct policy_handle *handle);
78 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
79 struct torture_context *tctx,
80 struct policy_handle *handle);
82 static bool test_ChangePassword(struct dcerpc_pipe *p,
83 struct torture_context *tctx,
84 const char *acct_name,
85 struct policy_handle *domain_handle, char **password);
87 static void init_lsa_String(struct lsa_String *string, const char *s)
89 string->string = s;
92 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
94 string->string = s;
97 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
99 string->length = length;
100 string->size = length;
101 string->array = (uint16_t *)discard_const(s);
104 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
105 struct policy_handle *handle)
107 NTSTATUS status;
108 struct samr_Close r;
110 r.in.handle = handle;
111 r.out.handle = handle;
113 status = dcerpc_samr_Close(p, tctx, &r);
114 torture_assert_ntstatus_ok(tctx, status, "Close");
116 return true;
119 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
120 struct policy_handle *handle)
122 NTSTATUS status;
123 struct samr_Shutdown r;
125 if (!torture_setting_bool(tctx, "dangerous", false)) {
126 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
127 return true;
130 r.in.connect_handle = handle;
132 torture_comment(tctx, "testing samr_Shutdown\n");
134 status = dcerpc_samr_Shutdown(p, tctx, &r);
135 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
137 return true;
140 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
141 struct policy_handle *handle)
143 NTSTATUS status;
144 struct samr_SetDsrmPassword r;
145 struct lsa_String string;
146 struct samr_Password hash;
148 if (!torture_setting_bool(tctx, "dangerous", false)) {
149 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
152 E_md4hash("TeSTDSRM123", hash.hash);
154 init_lsa_String(&string, "Administrator");
156 r.in.name = &string;
157 r.in.unknown = 0;
158 r.in.hash = &hash;
160 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
162 status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
163 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
165 return true;
169 static bool test_QuerySecurity(struct dcerpc_pipe *p,
170 struct torture_context *tctx,
171 struct policy_handle *handle)
173 NTSTATUS status;
174 struct samr_QuerySecurity r;
175 struct samr_SetSecurity s;
176 struct sec_desc_buf *sdbuf = NULL;
178 r.in.handle = handle;
179 r.in.sec_info = 7;
180 r.out.sdbuf = &sdbuf;
182 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
183 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
185 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
187 s.in.handle = handle;
188 s.in.sec_info = 7;
189 s.in.sdbuf = sdbuf;
191 if (torture_setting_bool(tctx, "samba4", false)) {
192 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
195 status = dcerpc_samr_SetSecurity(p, tctx, &s);
196 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
198 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
199 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
201 return true;
205 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
206 struct policy_handle *handle, uint32_t base_acct_flags,
207 const char *base_account_name)
209 NTSTATUS status;
210 struct samr_SetUserInfo s;
211 struct samr_SetUserInfo2 s2;
212 struct samr_QueryUserInfo q;
213 struct samr_QueryUserInfo q0;
214 union samr_UserInfo u;
215 union samr_UserInfo *info;
216 bool ret = true;
217 const char *test_account_name;
219 uint32_t user_extra_flags = 0;
221 if (!torture_setting_bool(tctx, "samba3", false)) {
222 if (base_acct_flags == ACB_NORMAL) {
223 /* When created, accounts are expired by default */
224 user_extra_flags = ACB_PW_EXPIRED;
228 s.in.user_handle = handle;
229 s.in.info = &u;
231 s2.in.user_handle = handle;
232 s2.in.info = &u;
234 q.in.user_handle = handle;
235 q.out.info = &info;
236 q0 = q;
238 #define TESTCALL(call, r) \
239 status = dcerpc_samr_ ##call(p, tctx, &r); \
240 if (!NT_STATUS_IS_OK(status)) { \
241 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
242 r.in.level, nt_errstr(status), __location__); \
243 ret = false; \
244 break; \
247 #define STRING_EQUAL(s1, s2, field) \
248 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
249 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
250 #field, s2, __location__); \
251 ret = false; \
252 break; \
255 #define MEM_EQUAL(s1, s2, length, field) \
256 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
257 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
258 #field, (const char *)s2, __location__); \
259 ret = false; \
260 break; \
263 #define INT_EQUAL(i1, i2, field) \
264 if (i1 != i2) { \
265 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
266 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
267 ret = false; \
268 break; \
271 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
272 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
273 q.in.level = lvl1; \
274 TESTCALL(QueryUserInfo, q) \
275 s.in.level = lvl1; \
276 s2.in.level = lvl1; \
277 u = *info; \
278 if (lvl1 == 21) { \
279 ZERO_STRUCT(u.info21); \
280 u.info21.fields_present = fpval; \
282 init_lsa_String(&u.info ## lvl1.field1, value); \
283 TESTCALL(SetUserInfo, s) \
284 TESTCALL(SetUserInfo2, s2) \
285 init_lsa_String(&u.info ## lvl1.field1, ""); \
286 TESTCALL(QueryUserInfo, q); \
287 u = *info; \
288 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
289 q.in.level = lvl2; \
290 TESTCALL(QueryUserInfo, q) \
291 u = *info; \
292 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
293 } while (0)
295 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
296 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
297 q.in.level = lvl1; \
298 TESTCALL(QueryUserInfo, q) \
299 s.in.level = lvl1; \
300 s2.in.level = lvl1; \
301 u = *info; \
302 if (lvl1 == 21) { \
303 ZERO_STRUCT(u.info21); \
304 u.info21.fields_present = fpval; \
306 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
307 TESTCALL(SetUserInfo, s) \
308 TESTCALL(SetUserInfo2, s2) \
309 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
310 TESTCALL(QueryUserInfo, q); \
311 u = *info; \
312 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
313 q.in.level = lvl2; \
314 TESTCALL(QueryUserInfo, q) \
315 u = *info; \
316 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
317 } while (0)
319 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
320 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
321 q.in.level = lvl1; \
322 TESTCALL(QueryUserInfo, q) \
323 s.in.level = lvl1; \
324 s2.in.level = lvl1; \
325 u = *info; \
326 if (lvl1 == 21) { \
327 uint8_t *bits = u.info21.logon_hours.bits; \
328 ZERO_STRUCT(u.info21); \
329 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
330 u.info21.logon_hours.units_per_week = 168; \
331 u.info21.logon_hours.bits = bits; \
333 u.info21.fields_present = fpval; \
335 u.info ## lvl1.field1 = value; \
336 TESTCALL(SetUserInfo, s) \
337 TESTCALL(SetUserInfo2, s2) \
338 u.info ## lvl1.field1 = 0; \
339 TESTCALL(QueryUserInfo, q); \
340 u = *info; \
341 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
342 q.in.level = lvl2; \
343 TESTCALL(QueryUserInfo, q) \
344 u = *info; \
345 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
346 } while (0)
348 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
349 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
350 } while (0)
352 q0.in.level = 12;
353 do { TESTCALL(QueryUserInfo, q0) } while (0);
355 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
356 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
357 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
358 SAMR_FIELD_COMMENT);
360 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
361 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
362 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
363 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
364 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
365 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
366 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
367 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
368 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
369 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
370 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
371 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
372 test_account_name = base_account_name;
373 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
374 SAMR_FIELD_ACCOUNT_NAME);
376 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
377 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
378 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
379 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
380 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
381 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
382 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
383 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
384 SAMR_FIELD_FULL_NAME);
386 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
387 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
388 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
389 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
390 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
391 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
392 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
393 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
394 SAMR_FIELD_FULL_NAME);
396 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
397 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
398 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
399 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
400 SAMR_FIELD_LOGON_SCRIPT);
402 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
403 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
404 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
405 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
406 SAMR_FIELD_PROFILE_PATH);
408 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
409 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
410 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
411 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
412 SAMR_FIELD_HOME_DIRECTORY);
413 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
414 SAMR_FIELD_HOME_DIRECTORY);
416 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
417 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
418 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
419 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
420 SAMR_FIELD_HOME_DRIVE);
421 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
422 SAMR_FIELD_HOME_DRIVE);
424 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
425 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
426 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
427 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
428 SAMR_FIELD_DESCRIPTION);
430 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
431 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
432 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
433 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
434 SAMR_FIELD_WORKSTATIONS);
435 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
436 SAMR_FIELD_WORKSTATIONS);
437 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
438 SAMR_FIELD_WORKSTATIONS);
439 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
440 SAMR_FIELD_WORKSTATIONS);
442 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
443 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
444 SAMR_FIELD_PARAMETERS);
445 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
446 SAMR_FIELD_PARAMETERS);
447 /* also empty user parameters are allowed */
448 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
449 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
450 SAMR_FIELD_PARAMETERS);
451 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
452 SAMR_FIELD_PARAMETERS);
454 /* Samba 3 cannot store country_code and copy_page atm. - gd */
455 if (!torture_setting_bool(tctx, "samba3", false)) {
456 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
457 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
458 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
459 SAMR_FIELD_COUNTRY_CODE);
460 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
461 SAMR_FIELD_COUNTRY_CODE);
463 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
464 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
465 SAMR_FIELD_CODE_PAGE);
466 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
467 SAMR_FIELD_CODE_PAGE);
470 if (!torture_setting_bool(tctx, "samba3", false)) {
471 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
472 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
473 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
474 SAMR_FIELD_ACCT_EXPIRY);
475 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
476 SAMR_FIELD_ACCT_EXPIRY);
477 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
478 SAMR_FIELD_ACCT_EXPIRY);
479 } else {
480 /* Samba 3 can only store seconds / time_t in passdb - gd */
481 NTTIME nt;
482 unix_to_nt_time(&nt, time(NULL) + __LINE__);
483 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
484 unix_to_nt_time(&nt, time(NULL) + __LINE__);
485 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
486 unix_to_nt_time(&nt, time(NULL) + __LINE__);
487 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
488 unix_to_nt_time(&nt, time(NULL) + __LINE__);
489 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
490 unix_to_nt_time(&nt, time(NULL) + __LINE__);
491 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
494 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
495 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
496 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
497 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
498 SAMR_FIELD_LOGON_HOURS);
500 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
501 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
502 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
504 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
505 (base_acct_flags | ACB_DISABLED),
506 (base_acct_flags | ACB_DISABLED | user_extra_flags),
509 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
510 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
511 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
512 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
514 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
515 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
516 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
520 /* The 'autolock' flag doesn't stick - check this */
521 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
522 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
523 (base_acct_flags | ACB_DISABLED | user_extra_flags),
525 #if 0
526 /* Removing the 'disabled' flag doesn't stick - check this */
527 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
528 (base_acct_flags),
529 (base_acct_flags | ACB_DISABLED | user_extra_flags),
531 #endif
533 /* Samba3 cannot store these atm */
534 if (!torture_setting_bool(tctx, "samba3", false)) {
535 /* The 'store plaintext' flag does stick */
536 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
537 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
538 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
540 /* The 'use DES' flag does stick */
541 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
542 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
543 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
545 /* The 'don't require kerberos pre-authentication flag does stick */
546 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
547 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
548 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
550 /* The 'no kerberos PAC required' flag sticks */
551 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
552 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
553 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
556 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
557 (base_acct_flags | ACB_DISABLED),
558 (base_acct_flags | ACB_DISABLED | user_extra_flags),
559 SAMR_FIELD_ACCT_FLAGS);
561 #if 0
562 /* these fail with win2003 - it appears you can't set the primary gid?
563 the set succeeds, but the gid isn't changed. Very weird! */
564 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
565 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
566 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
567 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
568 #endif
570 return ret;
574 generate a random password for password change tests
576 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
578 size_t len = MAX(8, min_len) + (random() % 6);
579 char *s = generate_random_str(mem_ctx, len);
580 return s;
583 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
585 char *s = samr_rand_pass_silent(mem_ctx, min_len);
586 printf("Generated password '%s'\n", s);
587 return s;
592 generate a random password for password change tests
594 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
596 int i;
597 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
598 generate_random_buffer(password.data, password.length);
600 for (i=0; i < len; i++) {
601 if (((uint16_t *)password.data)[i] == 0) {
602 ((uint16_t *)password.data)[i] = 1;
606 return password;
610 generate a random password for password change tests (fixed length)
612 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
614 char *s = generate_random_str(mem_ctx, len);
615 printf("Generated password '%s'\n", s);
616 return s;
619 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
620 struct policy_handle *handle, char **password)
622 NTSTATUS status;
623 struct samr_SetUserInfo s;
624 union samr_UserInfo u;
625 bool ret = true;
626 DATA_BLOB session_key;
627 char *newpass;
628 struct samr_GetUserPwInfo pwp;
629 struct samr_PwInfo info;
630 int policy_min_pw_len = 0;
631 pwp.in.user_handle = handle;
632 pwp.out.info = &info;
634 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
635 if (NT_STATUS_IS_OK(status)) {
636 policy_min_pw_len = pwp.out.info->min_password_length;
638 newpass = samr_rand_pass(tctx, policy_min_pw_len);
640 s.in.user_handle = handle;
641 s.in.info = &u;
642 s.in.level = 24;
644 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
645 u.info24.password_expired = 0;
647 status = dcerpc_fetch_session_key(p, &session_key);
648 if (!NT_STATUS_IS_OK(status)) {
649 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
650 s.in.level, nt_errstr(status));
651 return false;
654 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
656 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
658 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
659 if (!NT_STATUS_IS_OK(status)) {
660 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
661 s.in.level, nt_errstr(status));
662 ret = false;
663 } else {
664 *password = newpass;
667 return ret;
671 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
672 struct policy_handle *handle, uint32_t fields_present,
673 char **password)
675 NTSTATUS status;
676 struct samr_SetUserInfo s;
677 union samr_UserInfo u;
678 bool ret = true;
679 DATA_BLOB session_key;
680 char *newpass;
681 struct samr_GetUserPwInfo pwp;
682 struct samr_PwInfo info;
683 int policy_min_pw_len = 0;
684 pwp.in.user_handle = handle;
685 pwp.out.info = &info;
687 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
688 if (NT_STATUS_IS_OK(status)) {
689 policy_min_pw_len = pwp.out.info->min_password_length;
691 newpass = samr_rand_pass(tctx, policy_min_pw_len);
693 s.in.user_handle = handle;
694 s.in.info = &u;
695 s.in.level = 23;
697 ZERO_STRUCT(u);
699 u.info23.info.fields_present = fields_present;
701 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
703 status = dcerpc_fetch_session_key(p, &session_key);
704 if (!NT_STATUS_IS_OK(status)) {
705 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
706 s.in.level, nt_errstr(status));
707 return false;
710 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
712 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
714 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
715 if (!NT_STATUS_IS_OK(status)) {
716 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
717 s.in.level, nt_errstr(status));
718 ret = false;
719 } else {
720 *password = newpass;
723 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
725 status = dcerpc_fetch_session_key(p, &session_key);
726 if (!NT_STATUS_IS_OK(status)) {
727 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
728 s.in.level, nt_errstr(status));
729 return false;
732 /* This should break the key nicely */
733 session_key.length--;
734 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
736 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
738 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
739 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
740 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
741 s.in.level, nt_errstr(status));
742 ret = false;
745 return ret;
749 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
750 struct policy_handle *handle, bool makeshort,
751 char **password)
753 NTSTATUS status;
754 struct samr_SetUserInfo s;
755 union samr_UserInfo u;
756 bool ret = true;
757 DATA_BLOB session_key;
758 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
759 uint8_t confounder[16];
760 char *newpass;
761 struct MD5Context ctx;
762 struct samr_GetUserPwInfo pwp;
763 struct samr_PwInfo info;
764 int policy_min_pw_len = 0;
765 pwp.in.user_handle = handle;
766 pwp.out.info = &info;
768 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
769 if (NT_STATUS_IS_OK(status)) {
770 policy_min_pw_len = pwp.out.info->min_password_length;
772 if (makeshort && policy_min_pw_len) {
773 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
774 } else {
775 newpass = samr_rand_pass(tctx, policy_min_pw_len);
778 s.in.user_handle = handle;
779 s.in.info = &u;
780 s.in.level = 26;
782 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
783 u.info26.password_expired = 0;
785 status = dcerpc_fetch_session_key(p, &session_key);
786 if (!NT_STATUS_IS_OK(status)) {
787 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
788 s.in.level, nt_errstr(status));
789 return false;
792 generate_random_buffer((uint8_t *)confounder, 16);
794 MD5Init(&ctx);
795 MD5Update(&ctx, confounder, 16);
796 MD5Update(&ctx, session_key.data, session_key.length);
797 MD5Final(confounded_session_key.data, &ctx);
799 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
800 memcpy(&u.info26.password.data[516], confounder, 16);
802 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
804 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
805 if (!NT_STATUS_IS_OK(status)) {
806 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
807 s.in.level, nt_errstr(status));
808 ret = false;
809 } else {
810 *password = newpass;
813 /* This should break the key nicely */
814 confounded_session_key.data[0]++;
816 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
817 memcpy(&u.info26.password.data[516], confounder, 16);
819 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
821 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
822 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
823 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
824 s.in.level, nt_errstr(status));
825 ret = false;
826 } else {
827 *password = newpass;
830 return ret;
833 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
834 struct policy_handle *handle, uint32_t fields_present,
835 char **password)
837 NTSTATUS status;
838 struct samr_SetUserInfo s;
839 union samr_UserInfo u;
840 bool ret = true;
841 DATA_BLOB session_key;
842 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
843 struct MD5Context ctx;
844 uint8_t confounder[16];
845 char *newpass;
846 struct samr_GetUserPwInfo pwp;
847 struct samr_PwInfo info;
848 int policy_min_pw_len = 0;
849 pwp.in.user_handle = handle;
850 pwp.out.info = &info;
852 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
853 if (NT_STATUS_IS_OK(status)) {
854 policy_min_pw_len = pwp.out.info->min_password_length;
856 newpass = samr_rand_pass(tctx, policy_min_pw_len);
858 s.in.user_handle = handle;
859 s.in.info = &u;
860 s.in.level = 25;
862 ZERO_STRUCT(u);
864 u.info25.info.fields_present = fields_present;
866 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
868 status = dcerpc_fetch_session_key(p, &session_key);
869 if (!NT_STATUS_IS_OK(status)) {
870 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
871 s.in.level, nt_errstr(status));
872 return false;
875 generate_random_buffer((uint8_t *)confounder, 16);
877 MD5Init(&ctx);
878 MD5Update(&ctx, confounder, 16);
879 MD5Update(&ctx, session_key.data, session_key.length);
880 MD5Final(confounded_session_key.data, &ctx);
882 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
883 memcpy(&u.info25.password.data[516], confounder, 16);
885 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
887 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
888 if (!NT_STATUS_IS_OK(status)) {
889 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
890 s.in.level, nt_errstr(status));
891 ret = false;
892 } else {
893 *password = newpass;
896 /* This should break the key nicely */
897 confounded_session_key.data[0]++;
899 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
900 memcpy(&u.info25.password.data[516], confounder, 16);
902 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
904 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
905 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
906 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
907 s.in.level, nt_errstr(status));
908 ret = false;
911 return ret;
914 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
915 struct policy_handle *handle, char **password)
917 NTSTATUS status;
918 struct samr_SetUserInfo s;
919 union samr_UserInfo u;
920 bool ret = true;
921 DATA_BLOB session_key;
922 char *newpass;
923 struct samr_GetUserPwInfo pwp;
924 struct samr_PwInfo info;
925 int policy_min_pw_len = 0;
926 uint8_t lm_hash[16], nt_hash[16];
928 pwp.in.user_handle = handle;
929 pwp.out.info = &info;
931 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
932 if (NT_STATUS_IS_OK(status)) {
933 policy_min_pw_len = pwp.out.info->min_password_length;
935 newpass = samr_rand_pass(tctx, policy_min_pw_len);
937 s.in.user_handle = handle;
938 s.in.info = &u;
939 s.in.level = 18;
941 ZERO_STRUCT(u);
943 u.info18.nt_pwd_active = true;
944 u.info18.lm_pwd_active = true;
946 E_md4hash(newpass, nt_hash);
947 E_deshash(newpass, lm_hash);
949 status = dcerpc_fetch_session_key(p, &session_key);
950 if (!NT_STATUS_IS_OK(status)) {
951 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
952 s.in.level, nt_errstr(status));
953 return false;
957 DATA_BLOB in,out;
958 in = data_blob_const(nt_hash, 16);
959 out = data_blob_talloc_zero(tctx, 16);
960 sess_crypt_blob(&out, &in, &session_key, true);
961 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
964 DATA_BLOB in,out;
965 in = data_blob_const(lm_hash, 16);
966 out = data_blob_talloc_zero(tctx, 16);
967 sess_crypt_blob(&out, &in, &session_key, true);
968 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
971 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
973 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
974 if (!NT_STATUS_IS_OK(status)) {
975 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
976 s.in.level, nt_errstr(status));
977 ret = false;
978 } else {
979 *password = newpass;
982 return ret;
985 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
986 struct policy_handle *handle, uint32_t fields_present,
987 char **password)
989 NTSTATUS status;
990 struct samr_SetUserInfo s;
991 union samr_UserInfo u;
992 bool ret = true;
993 DATA_BLOB session_key;
994 char *newpass;
995 struct samr_GetUserPwInfo pwp;
996 struct samr_PwInfo info;
997 int policy_min_pw_len = 0;
998 uint8_t lm_hash[16], nt_hash[16];
1000 pwp.in.user_handle = handle;
1001 pwp.out.info = &info;
1003 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1004 if (NT_STATUS_IS_OK(status)) {
1005 policy_min_pw_len = pwp.out.info->min_password_length;
1007 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1009 s.in.user_handle = handle;
1010 s.in.info = &u;
1011 s.in.level = 21;
1013 E_md4hash(newpass, nt_hash);
1014 E_deshash(newpass, lm_hash);
1016 ZERO_STRUCT(u);
1018 u.info21.fields_present = fields_present;
1020 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1021 u.info21.lm_owf_password.length = 16;
1022 u.info21.lm_owf_password.size = 16;
1023 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1024 u.info21.lm_password_set = true;
1027 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1028 u.info21.nt_owf_password.length = 16;
1029 u.info21.nt_owf_password.size = 16;
1030 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1031 u.info21.nt_password_set = true;
1034 status = dcerpc_fetch_session_key(p, &session_key);
1035 if (!NT_STATUS_IS_OK(status)) {
1036 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1037 s.in.level, nt_errstr(status));
1038 return false;
1041 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1042 DATA_BLOB in,out;
1043 in = data_blob_const(u.info21.lm_owf_password.array,
1044 u.info21.lm_owf_password.length);
1045 out = data_blob_talloc_zero(tctx, 16);
1046 sess_crypt_blob(&out, &in, &session_key, true);
1047 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1050 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1051 DATA_BLOB in,out;
1052 in = data_blob_const(u.info21.nt_owf_password.array,
1053 u.info21.nt_owf_password.length);
1054 out = data_blob_talloc_zero(tctx, 16);
1055 sess_crypt_blob(&out, &in, &session_key, true);
1056 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1059 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1061 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1062 if (!NT_STATUS_IS_OK(status)) {
1063 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1064 s.in.level, nt_errstr(status));
1065 ret = false;
1066 } else {
1067 *password = newpass;
1070 /* try invalid length */
1071 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1073 u.info21.nt_owf_password.length++;
1075 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1077 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1078 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1079 s.in.level, nt_errstr(status));
1080 ret = false;
1084 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1086 u.info21.lm_owf_password.length++;
1088 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1090 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1091 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1092 s.in.level, nt_errstr(status));
1093 ret = false;
1097 return ret;
1100 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1101 struct torture_context *tctx,
1102 struct policy_handle *handle,
1103 uint16_t level,
1104 uint32_t fields_present,
1105 char **password, uint8_t password_expired,
1106 bool use_setinfo2,
1107 bool *matched_expected_error)
1109 NTSTATUS status;
1110 NTSTATUS expected_error = NT_STATUS_OK;
1111 struct samr_SetUserInfo s;
1112 struct samr_SetUserInfo2 s2;
1113 union samr_UserInfo u;
1114 bool ret = true;
1115 DATA_BLOB session_key;
1116 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1117 struct MD5Context ctx;
1118 uint8_t confounder[16];
1119 char *newpass;
1120 struct samr_GetUserPwInfo pwp;
1121 struct samr_PwInfo info;
1122 int policy_min_pw_len = 0;
1123 const char *comment = NULL;
1124 uint8_t lm_hash[16], nt_hash[16];
1126 pwp.in.user_handle = handle;
1127 pwp.out.info = &info;
1129 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1130 if (NT_STATUS_IS_OK(status)) {
1131 policy_min_pw_len = pwp.out.info->min_password_length;
1133 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1135 if (use_setinfo2) {
1136 s2.in.user_handle = handle;
1137 s2.in.info = &u;
1138 s2.in.level = level;
1139 } else {
1140 s.in.user_handle = handle;
1141 s.in.info = &u;
1142 s.in.level = level;
1145 if (fields_present & SAMR_FIELD_COMMENT) {
1146 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1149 ZERO_STRUCT(u);
1151 switch (level) {
1152 case 18:
1153 E_md4hash(newpass, nt_hash);
1154 E_deshash(newpass, lm_hash);
1156 u.info18.nt_pwd_active = true;
1157 u.info18.lm_pwd_active = true;
1158 u.info18.password_expired = password_expired;
1160 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1161 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1163 break;
1164 case 21:
1165 E_md4hash(newpass, nt_hash);
1166 E_deshash(newpass, lm_hash);
1168 u.info21.fields_present = fields_present;
1169 u.info21.password_expired = password_expired;
1170 u.info21.comment.string = comment;
1172 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1173 u.info21.lm_owf_password.length = 16;
1174 u.info21.lm_owf_password.size = 16;
1175 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1176 u.info21.lm_password_set = true;
1179 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1180 u.info21.nt_owf_password.length = 16;
1181 u.info21.nt_owf_password.size = 16;
1182 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1183 u.info21.nt_password_set = true;
1186 break;
1187 case 23:
1188 u.info23.info.fields_present = fields_present;
1189 u.info23.info.password_expired = password_expired;
1190 u.info23.info.comment.string = comment;
1192 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1194 break;
1195 case 24:
1196 u.info24.password_expired = password_expired;
1198 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1200 break;
1201 case 25:
1202 u.info25.info.fields_present = fields_present;
1203 u.info25.info.password_expired = password_expired;
1204 u.info25.info.comment.string = comment;
1206 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1208 break;
1209 case 26:
1210 u.info26.password_expired = password_expired;
1212 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1214 break;
1217 status = dcerpc_fetch_session_key(p, &session_key);
1218 if (!NT_STATUS_IS_OK(status)) {
1219 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1220 s.in.level, nt_errstr(status));
1221 return false;
1224 generate_random_buffer((uint8_t *)confounder, 16);
1226 MD5Init(&ctx);
1227 MD5Update(&ctx, confounder, 16);
1228 MD5Update(&ctx, session_key.data, session_key.length);
1229 MD5Final(confounded_session_key.data, &ctx);
1231 switch (level) {
1232 case 18:
1234 DATA_BLOB in,out;
1235 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1236 out = data_blob_talloc_zero(tctx, 16);
1237 sess_crypt_blob(&out, &in, &session_key, true);
1238 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1241 DATA_BLOB in,out;
1242 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1243 out = data_blob_talloc_zero(tctx, 16);
1244 sess_crypt_blob(&out, &in, &session_key, true);
1245 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1248 break;
1249 case 21:
1250 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1251 DATA_BLOB in,out;
1252 in = data_blob_const(u.info21.lm_owf_password.array,
1253 u.info21.lm_owf_password.length);
1254 out = data_blob_talloc_zero(tctx, 16);
1255 sess_crypt_blob(&out, &in, &session_key, true);
1256 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1258 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1259 DATA_BLOB in,out;
1260 in = data_blob_const(u.info21.nt_owf_password.array,
1261 u.info21.nt_owf_password.length);
1262 out = data_blob_talloc_zero(tctx, 16);
1263 sess_crypt_blob(&out, &in, &session_key, true);
1264 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1266 break;
1267 case 23:
1268 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1269 break;
1270 case 24:
1271 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1272 break;
1273 case 25:
1274 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1275 memcpy(&u.info25.password.data[516], confounder, 16);
1276 break;
1277 case 26:
1278 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1279 memcpy(&u.info26.password.data[516], confounder, 16);
1280 break;
1283 if (use_setinfo2) {
1284 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1285 } else {
1286 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1289 if (!NT_STATUS_IS_OK(status)) {
1290 if (fields_present == 0) {
1291 expected_error = NT_STATUS_INVALID_PARAMETER;
1293 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1294 expected_error = NT_STATUS_ACCESS_DENIED;
1298 if (!NT_STATUS_IS_OK(expected_error)) {
1299 if (use_setinfo2) {
1300 torture_assert_ntstatus_equal(tctx,
1301 s2.out.result,
1302 expected_error, "SetUserInfo2 failed");
1303 } else {
1304 torture_assert_ntstatus_equal(tctx,
1305 s.out.result,
1306 expected_error, "SetUserInfo failed");
1308 *matched_expected_error = true;
1309 return true;
1312 if (!NT_STATUS_IS_OK(status)) {
1313 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1314 use_setinfo2 ? "2":"", level, nt_errstr(status));
1315 ret = false;
1316 } else {
1317 *password = newpass;
1320 return ret;
1323 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1324 struct policy_handle *handle)
1326 NTSTATUS status;
1327 struct samr_SetAliasInfo r;
1328 struct samr_QueryAliasInfo q;
1329 union samr_AliasInfo *info;
1330 uint16_t levels[] = {2, 3};
1331 int i;
1332 bool ret = true;
1334 /* Ignoring switch level 1, as that includes the number of members for the alias
1335 * and setting this to a wrong value might have negative consequences
1338 for (i=0;i<ARRAY_SIZE(levels);i++) {
1339 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1341 r.in.alias_handle = handle;
1342 r.in.level = levels[i];
1343 r.in.info = talloc(tctx, union samr_AliasInfo);
1344 switch (r.in.level) {
1345 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1346 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1347 "Test Description, should test I18N as well"); break;
1348 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1351 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1352 if (!NT_STATUS_IS_OK(status)) {
1353 torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1354 levels[i], nt_errstr(status));
1355 ret = false;
1358 q.in.alias_handle = handle;
1359 q.in.level = levels[i];
1360 q.out.info = &info;
1362 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1365 levels[i], nt_errstr(status));
1366 ret = false;
1370 return ret;
1373 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1374 struct policy_handle *user_handle)
1376 struct samr_GetGroupsForUser r;
1377 struct samr_RidWithAttributeArray *rids = NULL;
1378 NTSTATUS status;
1380 torture_comment(tctx, "testing GetGroupsForUser\n");
1382 r.in.user_handle = user_handle;
1383 r.out.rids = &rids;
1385 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1386 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1388 return true;
1392 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1393 struct lsa_String *domain_name)
1395 NTSTATUS status;
1396 struct samr_GetDomPwInfo r;
1397 struct samr_PwInfo info;
1399 r.in.domain_name = domain_name;
1400 r.out.info = &info;
1402 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1404 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1405 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1407 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1408 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1410 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1411 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1413 r.in.domain_name->string = "\\\\__NONAME__";
1414 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1416 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1417 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1419 r.in.domain_name->string = "\\\\Builtin";
1420 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1422 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1423 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1425 return true;
1428 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1429 struct policy_handle *handle)
1431 NTSTATUS status;
1432 struct samr_GetUserPwInfo r;
1433 struct samr_PwInfo info;
1435 torture_comment(tctx, "Testing GetUserPwInfo\n");
1437 r.in.user_handle = handle;
1438 r.out.info = &info;
1440 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1441 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1443 return true;
1446 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1447 struct policy_handle *domain_handle, const char *name,
1448 uint32_t *rid)
1450 NTSTATUS status;
1451 struct samr_LookupNames n;
1452 struct lsa_String sname[2];
1453 struct samr_Ids rids, types;
1455 init_lsa_String(&sname[0], name);
1457 n.in.domain_handle = domain_handle;
1458 n.in.num_names = 1;
1459 n.in.names = sname;
1460 n.out.rids = &rids;
1461 n.out.types = &types;
1462 status = dcerpc_samr_LookupNames(p, tctx, &n);
1463 if (NT_STATUS_IS_OK(status)) {
1464 *rid = n.out.rids->ids[0];
1465 } else {
1466 return status;
1469 init_lsa_String(&sname[1], "xxNONAMExx");
1470 n.in.num_names = 2;
1471 status = dcerpc_samr_LookupNames(p, tctx, &n);
1472 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1473 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(status));
1474 if (NT_STATUS_IS_OK(status)) {
1475 return NT_STATUS_UNSUCCESSFUL;
1477 return status;
1480 n.in.num_names = 0;
1481 status = dcerpc_samr_LookupNames(p, tctx, &n);
1482 if (!NT_STATUS_IS_OK(status)) {
1483 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1484 return status;
1487 init_lsa_String(&sname[0], "xxNONAMExx");
1488 n.in.num_names = 1;
1489 status = dcerpc_samr_LookupNames(p, tctx, &n);
1490 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1491 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1492 if (NT_STATUS_IS_OK(status)) {
1493 return NT_STATUS_UNSUCCESSFUL;
1495 return status;
1498 init_lsa_String(&sname[0], "xxNONAMExx");
1499 init_lsa_String(&sname[1], "xxNONAME2xx");
1500 n.in.num_names = 2;
1501 status = dcerpc_samr_LookupNames(p, tctx, &n);
1502 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1503 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1504 if (NT_STATUS_IS_OK(status)) {
1505 return NT_STATUS_UNSUCCESSFUL;
1507 return status;
1510 return NT_STATUS_OK;
1513 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
1514 struct torture_context *tctx,
1515 struct policy_handle *domain_handle,
1516 const char *name, struct policy_handle *user_handle)
1518 NTSTATUS status;
1519 struct samr_OpenUser r;
1520 uint32_t rid;
1522 status = test_LookupName(p, tctx, domain_handle, name, &rid);
1523 if (!NT_STATUS_IS_OK(status)) {
1524 return status;
1527 r.in.domain_handle = domain_handle;
1528 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1529 r.in.rid = rid;
1530 r.out.user_handle = user_handle;
1531 status = dcerpc_samr_OpenUser(p, tctx, &r);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1536 return status;
1539 #if 0
1540 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1541 struct torture_context *tctx,
1542 struct policy_handle *handle)
1544 NTSTATUS status;
1545 struct samr_ChangePasswordUser r;
1546 bool ret = true;
1547 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1548 struct policy_handle user_handle;
1549 char *oldpass = "test";
1550 char *newpass = "test2";
1551 uint8_t old_nt_hash[16], new_nt_hash[16];
1552 uint8_t old_lm_hash[16], new_lm_hash[16];
1554 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1555 if (!NT_STATUS_IS_OK(status)) {
1556 return false;
1559 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1561 torture_comment(tctx, "old password: %s\n", oldpass);
1562 torture_comment(tctx, "new password: %s\n", newpass);
1564 E_md4hash(oldpass, old_nt_hash);
1565 E_md4hash(newpass, new_nt_hash);
1566 E_deshash(oldpass, old_lm_hash);
1567 E_deshash(newpass, new_lm_hash);
1569 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1570 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1571 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1572 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1573 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1574 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1576 r.in.handle = &user_handle;
1577 r.in.lm_present = 1;
1578 r.in.old_lm_crypted = &hash1;
1579 r.in.new_lm_crypted = &hash2;
1580 r.in.nt_present = 1;
1581 r.in.old_nt_crypted = &hash3;
1582 r.in.new_nt_crypted = &hash4;
1583 r.in.cross1_present = 1;
1584 r.in.nt_cross = &hash5;
1585 r.in.cross2_present = 1;
1586 r.in.lm_cross = &hash6;
1588 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1589 if (!NT_STATUS_IS_OK(status)) {
1590 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
1591 ret = false;
1594 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1595 ret = false;
1598 return ret;
1600 #endif
1602 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1603 const char *acct_name,
1604 struct policy_handle *handle, char **password)
1606 NTSTATUS status;
1607 struct samr_ChangePasswordUser r;
1608 bool ret = true;
1609 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1610 struct policy_handle user_handle;
1611 char *oldpass;
1612 uint8_t old_nt_hash[16], new_nt_hash[16];
1613 uint8_t old_lm_hash[16], new_lm_hash[16];
1614 bool changed = true;
1616 char *newpass;
1617 struct samr_GetUserPwInfo pwp;
1618 struct samr_PwInfo info;
1619 int policy_min_pw_len = 0;
1621 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1622 if (!NT_STATUS_IS_OK(status)) {
1623 return false;
1625 pwp.in.user_handle = &user_handle;
1626 pwp.out.info = &info;
1628 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1629 if (NT_STATUS_IS_OK(status)) {
1630 policy_min_pw_len = pwp.out.info->min_password_length;
1632 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1634 torture_comment(tctx, "Testing ChangePasswordUser\n");
1636 torture_assert(tctx, *password != NULL,
1637 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1639 oldpass = *password;
1641 E_md4hash(oldpass, old_nt_hash);
1642 E_md4hash(newpass, new_nt_hash);
1643 E_deshash(oldpass, old_lm_hash);
1644 E_deshash(newpass, new_lm_hash);
1646 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1647 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1648 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1649 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1650 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1651 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1653 r.in.user_handle = &user_handle;
1654 r.in.lm_present = 1;
1655 /* Break the LM hash */
1656 hash1.hash[0]++;
1657 r.in.old_lm_crypted = &hash1;
1658 r.in.new_lm_crypted = &hash2;
1659 r.in.nt_present = 1;
1660 r.in.old_nt_crypted = &hash3;
1661 r.in.new_nt_crypted = &hash4;
1662 r.in.cross1_present = 1;
1663 r.in.nt_cross = &hash5;
1664 r.in.cross2_present = 1;
1665 r.in.lm_cross = &hash6;
1667 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1668 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1669 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1671 /* Unbreak the LM hash */
1672 hash1.hash[0]--;
1674 r.in.user_handle = &user_handle;
1675 r.in.lm_present = 1;
1676 r.in.old_lm_crypted = &hash1;
1677 r.in.new_lm_crypted = &hash2;
1678 /* Break the NT hash */
1679 hash3.hash[0]--;
1680 r.in.nt_present = 1;
1681 r.in.old_nt_crypted = &hash3;
1682 r.in.new_nt_crypted = &hash4;
1683 r.in.cross1_present = 1;
1684 r.in.nt_cross = &hash5;
1685 r.in.cross2_present = 1;
1686 r.in.lm_cross = &hash6;
1688 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1689 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1690 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1692 /* Unbreak the NT hash */
1693 hash3.hash[0]--;
1695 r.in.user_handle = &user_handle;
1696 r.in.lm_present = 1;
1697 r.in.old_lm_crypted = &hash1;
1698 r.in.new_lm_crypted = &hash2;
1699 r.in.nt_present = 1;
1700 r.in.old_nt_crypted = &hash3;
1701 r.in.new_nt_crypted = &hash4;
1702 r.in.cross1_present = 1;
1703 r.in.nt_cross = &hash5;
1704 r.in.cross2_present = 1;
1705 /* Break the LM cross */
1706 hash6.hash[0]++;
1707 r.in.lm_cross = &hash6;
1709 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1710 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1711 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1712 ret = false;
1715 /* Unbreak the LM cross */
1716 hash6.hash[0]--;
1718 r.in.user_handle = &user_handle;
1719 r.in.lm_present = 1;
1720 r.in.old_lm_crypted = &hash1;
1721 r.in.new_lm_crypted = &hash2;
1722 r.in.nt_present = 1;
1723 r.in.old_nt_crypted = &hash3;
1724 r.in.new_nt_crypted = &hash4;
1725 r.in.cross1_present = 1;
1726 /* Break the NT cross */
1727 hash5.hash[0]++;
1728 r.in.nt_cross = &hash5;
1729 r.in.cross2_present = 1;
1730 r.in.lm_cross = &hash6;
1732 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1733 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1734 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1735 ret = false;
1738 /* Unbreak the NT cross */
1739 hash5.hash[0]--;
1742 /* Reset the hashes to not broken values */
1743 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1744 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1745 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1746 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1747 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1748 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1750 r.in.user_handle = &user_handle;
1751 r.in.lm_present = 1;
1752 r.in.old_lm_crypted = &hash1;
1753 r.in.new_lm_crypted = &hash2;
1754 r.in.nt_present = 1;
1755 r.in.old_nt_crypted = &hash3;
1756 r.in.new_nt_crypted = &hash4;
1757 r.in.cross1_present = 1;
1758 r.in.nt_cross = &hash5;
1759 r.in.cross2_present = 0;
1760 r.in.lm_cross = NULL;
1762 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1763 if (NT_STATUS_IS_OK(status)) {
1764 changed = true;
1765 *password = newpass;
1766 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1767 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1768 ret = false;
1771 oldpass = newpass;
1772 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1774 E_md4hash(oldpass, old_nt_hash);
1775 E_md4hash(newpass, new_nt_hash);
1776 E_deshash(oldpass, old_lm_hash);
1777 E_deshash(newpass, new_lm_hash);
1780 /* Reset the hashes to not broken values */
1781 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1782 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1783 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1784 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1785 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1786 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1788 r.in.user_handle = &user_handle;
1789 r.in.lm_present = 1;
1790 r.in.old_lm_crypted = &hash1;
1791 r.in.new_lm_crypted = &hash2;
1792 r.in.nt_present = 1;
1793 r.in.old_nt_crypted = &hash3;
1794 r.in.new_nt_crypted = &hash4;
1795 r.in.cross1_present = 0;
1796 r.in.nt_cross = NULL;
1797 r.in.cross2_present = 1;
1798 r.in.lm_cross = &hash6;
1800 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1801 if (NT_STATUS_IS_OK(status)) {
1802 changed = true;
1803 *password = newpass;
1804 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1805 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1806 ret = false;
1809 oldpass = newpass;
1810 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1812 E_md4hash(oldpass, old_nt_hash);
1813 E_md4hash(newpass, new_nt_hash);
1814 E_deshash(oldpass, old_lm_hash);
1815 E_deshash(newpass, new_lm_hash);
1818 /* Reset the hashes to not broken values */
1819 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1820 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1821 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1822 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1823 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1824 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1826 r.in.user_handle = &user_handle;
1827 r.in.lm_present = 1;
1828 r.in.old_lm_crypted = &hash1;
1829 r.in.new_lm_crypted = &hash2;
1830 r.in.nt_present = 1;
1831 r.in.old_nt_crypted = &hash3;
1832 r.in.new_nt_crypted = &hash4;
1833 r.in.cross1_present = 1;
1834 r.in.nt_cross = &hash5;
1835 r.in.cross2_present = 1;
1836 r.in.lm_cross = &hash6;
1838 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1839 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1840 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1841 } else if (!NT_STATUS_IS_OK(status)) {
1842 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
1843 ret = false;
1844 } else {
1845 changed = true;
1846 *password = newpass;
1849 r.in.user_handle = &user_handle;
1850 r.in.lm_present = 1;
1851 r.in.old_lm_crypted = &hash1;
1852 r.in.new_lm_crypted = &hash2;
1853 r.in.nt_present = 1;
1854 r.in.old_nt_crypted = &hash3;
1855 r.in.new_nt_crypted = &hash4;
1856 r.in.cross1_present = 1;
1857 r.in.nt_cross = &hash5;
1858 r.in.cross2_present = 1;
1859 r.in.lm_cross = &hash6;
1861 if (changed) {
1862 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1863 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1864 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1865 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1866 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1867 ret = false;
1872 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1873 ret = false;
1876 return ret;
1880 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1881 const char *acct_name,
1882 struct policy_handle *handle, char **password)
1884 NTSTATUS status;
1885 struct samr_OemChangePasswordUser2 r;
1886 bool ret = true;
1887 struct samr_Password lm_verifier;
1888 struct samr_CryptPassword lm_pass;
1889 struct lsa_AsciiString server, account, account_bad;
1890 char *oldpass;
1891 char *newpass;
1892 uint8_t old_lm_hash[16], new_lm_hash[16];
1894 struct samr_GetDomPwInfo dom_pw_info;
1895 struct samr_PwInfo info;
1896 int policy_min_pw_len = 0;
1898 struct lsa_String domain_name;
1900 domain_name.string = "";
1901 dom_pw_info.in.domain_name = &domain_name;
1902 dom_pw_info.out.info = &info;
1904 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1906 torture_assert(tctx, *password != NULL,
1907 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1909 oldpass = *password;
1911 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1912 if (NT_STATUS_IS_OK(status)) {
1913 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1916 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1918 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1919 account.string = acct_name;
1921 E_deshash(oldpass, old_lm_hash);
1922 E_deshash(newpass, new_lm_hash);
1924 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1925 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1926 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1928 r.in.server = &server;
1929 r.in.account = &account;
1930 r.in.password = &lm_pass;
1931 r.in.hash = &lm_verifier;
1933 /* Break the verification */
1934 lm_verifier.hash[0]++;
1936 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1938 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1939 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1940 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1941 nt_errstr(status));
1942 ret = false;
1945 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1946 /* Break the old password */
1947 old_lm_hash[0]++;
1948 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1949 /* unbreak it for the next operation */
1950 old_lm_hash[0]--;
1951 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1953 r.in.server = &server;
1954 r.in.account = &account;
1955 r.in.password = &lm_pass;
1956 r.in.hash = &lm_verifier;
1958 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1960 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1961 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1962 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1963 nt_errstr(status));
1964 ret = false;
1967 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1968 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1970 r.in.server = &server;
1971 r.in.account = &account;
1972 r.in.password = &lm_pass;
1973 r.in.hash = NULL;
1975 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1977 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1978 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1979 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1980 nt_errstr(status));
1981 ret = false;
1984 /* This shouldn't be a valid name */
1985 account_bad.string = TEST_ACCOUNT_NAME "XX";
1986 r.in.account = &account_bad;
1988 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1990 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1991 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1992 nt_errstr(status));
1993 ret = false;
1996 /* This shouldn't be a valid name */
1997 account_bad.string = TEST_ACCOUNT_NAME "XX";
1998 r.in.account = &account_bad;
1999 r.in.password = &lm_pass;
2000 r.in.hash = &lm_verifier;
2002 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2004 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2005 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2006 nt_errstr(status));
2007 ret = false;
2010 /* This shouldn't be a valid name */
2011 account_bad.string = TEST_ACCOUNT_NAME "XX";
2012 r.in.account = &account_bad;
2013 r.in.password = NULL;
2014 r.in.hash = &lm_verifier;
2016 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2018 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
2019 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2020 nt_errstr(status));
2021 ret = false;
2024 E_deshash(oldpass, old_lm_hash);
2025 E_deshash(newpass, new_lm_hash);
2027 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2028 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2029 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2031 r.in.server = &server;
2032 r.in.account = &account;
2033 r.in.password = &lm_pass;
2034 r.in.hash = &lm_verifier;
2036 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2037 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2038 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2039 } else if (!NT_STATUS_IS_OK(status)) {
2040 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
2041 ret = false;
2042 } else {
2043 *password = newpass;
2046 return ret;
2050 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2051 const char *acct_name,
2052 char **password,
2053 char *newpass, bool allow_password_restriction)
2055 NTSTATUS status;
2056 struct samr_ChangePasswordUser2 r;
2057 bool ret = true;
2058 struct lsa_String server, account;
2059 struct samr_CryptPassword nt_pass, lm_pass;
2060 struct samr_Password nt_verifier, lm_verifier;
2061 char *oldpass;
2062 uint8_t old_nt_hash[16], new_nt_hash[16];
2063 uint8_t old_lm_hash[16], new_lm_hash[16];
2065 struct samr_GetDomPwInfo dom_pw_info;
2066 struct samr_PwInfo info;
2068 struct lsa_String domain_name;
2070 domain_name.string = "";
2071 dom_pw_info.in.domain_name = &domain_name;
2072 dom_pw_info.out.info = &info;
2074 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2076 torture_assert(tctx, *password != NULL,
2077 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2078 oldpass = *password;
2080 if (!newpass) {
2081 int policy_min_pw_len = 0;
2082 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
2083 if (NT_STATUS_IS_OK(status)) {
2084 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2087 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2090 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2091 init_lsa_String(&account, acct_name);
2093 E_md4hash(oldpass, old_nt_hash);
2094 E_md4hash(newpass, new_nt_hash);
2096 E_deshash(oldpass, old_lm_hash);
2097 E_deshash(newpass, new_lm_hash);
2099 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2100 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2101 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2103 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2104 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2105 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2107 r.in.server = &server;
2108 r.in.account = &account;
2109 r.in.nt_password = &nt_pass;
2110 r.in.nt_verifier = &nt_verifier;
2111 r.in.lm_change = 1;
2112 r.in.lm_password = &lm_pass;
2113 r.in.lm_verifier = &lm_verifier;
2115 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
2116 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2117 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2118 } else if (!NT_STATUS_IS_OK(status)) {
2119 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2120 ret = false;
2121 } else {
2122 *password = newpass;
2125 return ret;
2129 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2130 const char *account_string,
2131 int policy_min_pw_len,
2132 char **password,
2133 const char *newpass,
2134 NTTIME last_password_change,
2135 bool handle_reject_reason)
2137 NTSTATUS status;
2138 struct samr_ChangePasswordUser3 r;
2139 bool ret = true;
2140 struct lsa_String server, account, account_bad;
2141 struct samr_CryptPassword nt_pass, lm_pass;
2142 struct samr_Password nt_verifier, lm_verifier;
2143 char *oldpass;
2144 uint8_t old_nt_hash[16], new_nt_hash[16];
2145 uint8_t old_lm_hash[16], new_lm_hash[16];
2146 NTTIME t;
2147 struct samr_DomInfo1 *dominfo = NULL;
2148 struct userPwdChangeFailureInformation *reject = NULL;
2150 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2152 if (newpass == NULL) {
2153 do {
2154 if (policy_min_pw_len == 0) {
2155 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2156 } else {
2157 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2159 } while (check_password_quality(newpass) == false);
2160 } else {
2161 torture_comment(tctx, "Using password '%s'\n", newpass);
2164 torture_assert(tctx, *password != NULL,
2165 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2167 oldpass = *password;
2168 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2169 init_lsa_String(&account, account_string);
2171 E_md4hash(oldpass, old_nt_hash);
2172 E_md4hash(newpass, new_nt_hash);
2174 E_deshash(oldpass, old_lm_hash);
2175 E_deshash(newpass, new_lm_hash);
2177 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2178 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2179 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2181 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2182 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2183 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2185 /* Break the verification */
2186 nt_verifier.hash[0]++;
2188 r.in.server = &server;
2189 r.in.account = &account;
2190 r.in.nt_password = &nt_pass;
2191 r.in.nt_verifier = &nt_verifier;
2192 r.in.lm_change = 1;
2193 r.in.lm_password = &lm_pass;
2194 r.in.lm_verifier = &lm_verifier;
2195 r.in.password3 = NULL;
2196 r.out.dominfo = &dominfo;
2197 r.out.reject = &reject;
2199 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2200 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2201 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2202 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2203 nt_errstr(status));
2204 ret = false;
2207 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2208 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2209 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2211 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2212 /* Break the NT hash */
2213 old_nt_hash[0]++;
2214 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2215 /* Unbreak it again */
2216 old_nt_hash[0]--;
2217 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2219 r.in.server = &server;
2220 r.in.account = &account;
2221 r.in.nt_password = &nt_pass;
2222 r.in.nt_verifier = &nt_verifier;
2223 r.in.lm_change = 1;
2224 r.in.lm_password = &lm_pass;
2225 r.in.lm_verifier = &lm_verifier;
2226 r.in.password3 = NULL;
2227 r.out.dominfo = &dominfo;
2228 r.out.reject = &reject;
2230 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2231 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2232 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2233 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2234 nt_errstr(status));
2235 ret = false;
2238 /* This shouldn't be a valid name */
2239 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2241 r.in.account = &account_bad;
2242 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2243 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2244 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2245 nt_errstr(status));
2246 ret = false;
2249 E_md4hash(oldpass, old_nt_hash);
2250 E_md4hash(newpass, new_nt_hash);
2252 E_deshash(oldpass, old_lm_hash);
2253 E_deshash(newpass, new_lm_hash);
2255 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2256 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2257 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2259 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2260 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2261 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2263 r.in.server = &server;
2264 r.in.account = &account;
2265 r.in.nt_password = &nt_pass;
2266 r.in.nt_verifier = &nt_verifier;
2267 r.in.lm_change = 1;
2268 r.in.lm_password = &lm_pass;
2269 r.in.lm_verifier = &lm_verifier;
2270 r.in.password3 = NULL;
2271 r.out.dominfo = &dominfo;
2272 r.out.reject = &reject;
2274 unix_to_nt_time(&t, time(NULL));
2276 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2278 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2279 && dominfo
2280 && reject
2281 && handle_reject_reason
2282 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2283 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2285 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2286 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2287 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2288 return false;
2292 /* We tested the order of precendence which is as follows:
2294 * pwd min_age
2295 * pwd length
2296 * pwd complexity
2297 * pwd history
2299 Guenther */
2301 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2302 (last_password_change + dominfo->min_password_age > t)) {
2304 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2305 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2306 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2307 return false;
2310 } else if ((dominfo->min_password_length > 0) &&
2311 (strlen(newpass) < dominfo->min_password_length)) {
2313 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2314 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2315 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2316 return false;
2319 } else if ((dominfo->password_history_length > 0) &&
2320 strequal(oldpass, newpass)) {
2322 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2323 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2324 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2325 return false;
2327 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2329 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2330 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2331 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2332 return false;
2337 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2338 /* retry with adjusted size */
2339 return test_ChangePasswordUser3(p, tctx, account_string,
2340 dominfo->min_password_length,
2341 password, NULL, 0, false);
2345 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2346 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2347 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2348 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2349 return false;
2351 /* Perhaps the server has a 'min password age' set? */
2353 } else {
2354 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2355 *password = talloc_strdup(tctx, newpass);
2358 return ret;
2361 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2362 const char *account_string,
2363 struct policy_handle *handle,
2364 char **password)
2366 NTSTATUS status;
2367 struct samr_ChangePasswordUser3 r;
2368 struct samr_SetUserInfo s;
2369 union samr_UserInfo u;
2370 DATA_BLOB session_key;
2371 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2372 uint8_t confounder[16];
2373 struct MD5Context ctx;
2375 bool ret = true;
2376 struct lsa_String server, account;
2377 struct samr_CryptPassword nt_pass;
2378 struct samr_Password nt_verifier;
2379 DATA_BLOB new_random_pass;
2380 char *newpass;
2381 char *oldpass;
2382 uint8_t old_nt_hash[16], new_nt_hash[16];
2383 NTTIME t;
2384 struct samr_DomInfo1 *dominfo = NULL;
2385 struct userPwdChangeFailureInformation *reject = NULL;
2387 new_random_pass = samr_very_rand_pass(tctx, 128);
2389 torture_assert(tctx, *password != NULL,
2390 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2392 oldpass = *password;
2393 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2394 init_lsa_String(&account, account_string);
2396 s.in.user_handle = handle;
2397 s.in.info = &u;
2398 s.in.level = 25;
2400 ZERO_STRUCT(u);
2402 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2404 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2406 status = dcerpc_fetch_session_key(p, &session_key);
2407 if (!NT_STATUS_IS_OK(status)) {
2408 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2409 s.in.level, nt_errstr(status));
2410 return false;
2413 generate_random_buffer((uint8_t *)confounder, 16);
2415 MD5Init(&ctx);
2416 MD5Update(&ctx, confounder, 16);
2417 MD5Update(&ctx, session_key.data, session_key.length);
2418 MD5Final(confounded_session_key.data, &ctx);
2420 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2421 memcpy(&u.info25.password.data[516], confounder, 16);
2423 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2425 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2426 if (!NT_STATUS_IS_OK(status)) {
2427 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2428 s.in.level, nt_errstr(status));
2429 ret = false;
2432 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2434 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2436 new_random_pass = samr_very_rand_pass(tctx, 128);
2438 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2440 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2441 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2442 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2444 r.in.server = &server;
2445 r.in.account = &account;
2446 r.in.nt_password = &nt_pass;
2447 r.in.nt_verifier = &nt_verifier;
2448 r.in.lm_change = 0;
2449 r.in.lm_password = NULL;
2450 r.in.lm_verifier = NULL;
2451 r.in.password3 = NULL;
2452 r.out.dominfo = &dominfo;
2453 r.out.reject = &reject;
2455 unix_to_nt_time(&t, time(NULL));
2457 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2459 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2460 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2461 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2462 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2463 return false;
2465 /* Perhaps the server has a 'min password age' set? */
2467 } else if (!NT_STATUS_IS_OK(status)) {
2468 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2469 ret = false;
2472 newpass = samr_rand_pass(tctx, 128);
2474 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2476 E_md4hash(newpass, new_nt_hash);
2478 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2479 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2480 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2482 r.in.server = &server;
2483 r.in.account = &account;
2484 r.in.nt_password = &nt_pass;
2485 r.in.nt_verifier = &nt_verifier;
2486 r.in.lm_change = 0;
2487 r.in.lm_password = NULL;
2488 r.in.lm_verifier = NULL;
2489 r.in.password3 = NULL;
2490 r.out.dominfo = &dominfo;
2491 r.out.reject = &reject;
2493 unix_to_nt_time(&t, time(NULL));
2495 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2497 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2498 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2499 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2500 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2501 return false;
2503 /* Perhaps the server has a 'min password age' set? */
2505 } else {
2506 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2507 *password = talloc_strdup(tctx, newpass);
2510 return ret;
2514 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2515 struct policy_handle *alias_handle)
2517 struct samr_GetMembersInAlias r;
2518 struct lsa_SidArray sids;
2519 NTSTATUS status;
2521 torture_comment(tctx, "Testing GetMembersInAlias\n");
2523 r.in.alias_handle = alias_handle;
2524 r.out.sids = &sids;
2526 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2527 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2529 return true;
2532 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2533 struct policy_handle *alias_handle,
2534 const struct dom_sid *domain_sid)
2536 struct samr_AddAliasMember r;
2537 struct samr_DeleteAliasMember d;
2538 NTSTATUS status;
2539 struct dom_sid *sid;
2541 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2543 torture_comment(tctx, "testing AddAliasMember\n");
2544 r.in.alias_handle = alias_handle;
2545 r.in.sid = sid;
2547 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2548 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2550 d.in.alias_handle = alias_handle;
2551 d.in.sid = sid;
2553 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2554 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2556 return true;
2559 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2560 struct policy_handle *alias_handle)
2562 struct samr_AddMultipleMembersToAlias a;
2563 struct samr_RemoveMultipleMembersFromAlias r;
2564 NTSTATUS status;
2565 struct lsa_SidArray sids;
2567 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2568 a.in.alias_handle = alias_handle;
2569 a.in.sids = &sids;
2571 sids.num_sids = 3;
2572 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2574 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2575 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2576 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2578 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2579 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2582 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2583 r.in.alias_handle = alias_handle;
2584 r.in.sids = &sids;
2586 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2587 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2589 /* strange! removing twice doesn't give any error */
2590 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2591 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2593 /* but removing an alias that isn't there does */
2594 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2596 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2597 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2599 return true;
2602 static bool test_GetAliasMembership(struct dcerpc_pipe *p,
2603 struct torture_context *tctx,
2604 struct policy_handle *domain_handle)
2606 struct samr_GetAliasMembership r;
2607 struct lsa_SidArray sids;
2608 struct samr_Ids rids;
2609 NTSTATUS status;
2611 torture_comment(tctx, "Testing GetAliasMembership\n");
2613 if (torture_setting_bool(tctx, "samba4", false)) {
2614 torture_skip(tctx, "skipping GetAliasMembership against s4");
2617 r.in.domain_handle = domain_handle;
2618 r.in.sids = &sids;
2619 r.out.rids = &rids;
2621 sids.num_sids = 0;
2622 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2624 status = dcerpc_samr_GetAliasMembership(p, tctx, &r);
2625 torture_assert_ntstatus_ok(tctx, status,
2626 "samr_GetAliasMembership failed");
2628 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2629 "protocol misbehaviour");
2631 sids.num_sids = 1;
2632 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2633 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2635 status = dcerpc_samr_GetAliasMembership(p, tctx, &r);
2636 torture_assert_ntstatus_ok(tctx, status,
2637 "samr_GetAliasMembership failed");
2639 #if 0
2640 /* only true for w2k8 it seems
2641 * win7, xp, w2k3 will return a 0 length array pointer */
2643 if (rids.ids && (rids.count == 0)) {
2644 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2646 #endif
2647 if (!rids.ids && rids.count) {
2648 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2651 return true;
2654 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2655 struct policy_handle *user_handle)
2657 struct samr_TestPrivateFunctionsUser r;
2658 NTSTATUS status;
2660 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2662 r.in.user_handle = user_handle;
2664 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2665 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2667 return true;
2670 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2671 struct torture_context *tctx,
2672 struct policy_handle *handle,
2673 bool use_info2,
2674 NTTIME *pwdlastset)
2676 NTSTATUS status;
2677 uint16_t levels[] = { /* 3, */ 5, 21 };
2678 int i;
2679 NTTIME pwdlastset3 = 0;
2680 NTTIME pwdlastset5 = 0;
2681 NTTIME pwdlastset21 = 0;
2683 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2684 use_info2 ? "2":"");
2686 for (i=0; i<ARRAY_SIZE(levels); i++) {
2688 struct samr_QueryUserInfo r;
2689 struct samr_QueryUserInfo2 r2;
2690 union samr_UserInfo *info;
2692 if (use_info2) {
2693 r2.in.user_handle = handle;
2694 r2.in.level = levels[i];
2695 r2.out.info = &info;
2696 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2698 } else {
2699 r.in.user_handle = handle;
2700 r.in.level = levels[i];
2701 r.out.info = &info;
2702 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2705 if (!NT_STATUS_IS_OK(status) &&
2706 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2707 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2708 use_info2 ? "2":"", levels[i], nt_errstr(status));
2709 return false;
2712 switch (levels[i]) {
2713 case 3:
2714 pwdlastset3 = info->info3.last_password_change;
2715 break;
2716 case 5:
2717 pwdlastset5 = info->info5.last_password_change;
2718 break;
2719 case 21:
2720 pwdlastset21 = info->info21.last_password_change;
2721 break;
2722 default:
2723 return false;
2726 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2727 "pwdlastset mixup"); */
2728 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2729 "pwdlastset mixup");
2731 *pwdlastset = pwdlastset21;
2733 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2735 return true;
2738 static bool test_SamLogon(struct torture_context *tctx,
2739 struct dcerpc_pipe *p,
2740 struct cli_credentials *test_credentials,
2741 NTSTATUS expected_result,
2742 bool interactive)
2744 NTSTATUS status;
2745 struct netr_LogonSamLogonEx r;
2746 union netr_LogonLevel logon;
2747 union netr_Validation validation;
2748 uint8_t authoritative;
2749 struct netr_IdentityInfo identity;
2750 struct netr_NetworkInfo ninfo;
2751 struct netr_PasswordInfo pinfo;
2752 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2753 int flags = CLI_CRED_NTLM_AUTH;
2754 uint32_t samlogon_flags = 0;
2755 struct netlogon_creds_CredentialState *creds;
2756 struct netr_Authenticator a;
2758 torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2760 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2761 flags |= CLI_CRED_LANMAN_AUTH;
2764 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2765 flags |= CLI_CRED_NTLMv2_AUTH;
2768 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2769 &identity.account_name.string,
2770 &identity.domain_name.string);
2772 identity.parameter_control =
2773 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2774 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2775 identity.logon_id_low = 0;
2776 identity.logon_id_high = 0;
2777 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2779 if (interactive) {
2780 netlogon_creds_client_authenticator(creds, &a);
2782 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
2783 ZERO_STRUCT(pinfo.lmpassword.hash);
2785 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
2787 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
2788 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
2789 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
2790 } else {
2791 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
2792 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
2795 pinfo.identity_info = identity;
2796 logon.password = &pinfo;
2798 r.in.logon_level = NetlogonInteractiveInformation;
2799 } else {
2800 generate_random_buffer(ninfo.challenge,
2801 sizeof(ninfo.challenge));
2802 chal = data_blob_const(ninfo.challenge,
2803 sizeof(ninfo.challenge));
2805 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2806 cli_credentials_get_domain(test_credentials));
2808 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2809 &flags,
2810 chal,
2811 names_blob,
2812 &lm_resp, &nt_resp,
2813 NULL, NULL);
2814 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2816 ninfo.lm.data = lm_resp.data;
2817 ninfo.lm.length = lm_resp.length;
2819 ninfo.nt.data = nt_resp.data;
2820 ninfo.nt.length = nt_resp.length;
2822 ninfo.identity_info = identity;
2823 logon.network = &ninfo;
2825 r.in.logon_level = NetlogonNetworkInformation;
2828 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2829 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2830 r.in.logon = &logon;
2831 r.in.flags = &samlogon_flags;
2832 r.out.flags = &samlogon_flags;
2833 r.out.validation = &validation;
2834 r.out.authoritative = &authoritative;
2836 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
2838 r.in.validation_level = 6;
2840 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2841 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2842 r.in.validation_level = 3;
2843 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2845 if (!NT_STATUS_IS_OK(status)) {
2846 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed");
2847 return true;
2848 } else {
2849 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogonEx failed");
2852 return true;
2855 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2856 struct dcerpc_pipe *p,
2857 struct cli_credentials *machine_creds,
2858 const char *acct_name,
2859 char *password,
2860 NTSTATUS expected_samlogon_result,
2861 bool interactive)
2863 bool ret = true;
2864 struct cli_credentials *test_credentials;
2866 test_credentials = cli_credentials_init(tctx);
2868 cli_credentials_set_workstation(test_credentials,
2869 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2870 cli_credentials_set_domain(test_credentials,
2871 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2872 cli_credentials_set_username(test_credentials,
2873 acct_name, CRED_SPECIFIED);
2874 cli_credentials_set_password(test_credentials,
2875 password, CRED_SPECIFIED);
2877 torture_comment(tctx, "testing samlogon (%s) as %s password: %s\n",
2878 interactive ? "interactive" : "network", acct_name, password);
2880 if (!test_SamLogon(tctx, p, test_credentials,
2881 expected_samlogon_result, interactive)) {
2882 torture_warning(tctx, "new password did not work\n");
2883 ret = false;
2886 return ret;
2889 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2890 struct dcerpc_pipe *np,
2891 struct torture_context *tctx,
2892 struct policy_handle *handle,
2893 uint16_t level,
2894 uint32_t fields_present,
2895 uint8_t password_expired,
2896 bool *matched_expected_error,
2897 bool use_setinfo2,
2898 const char *acct_name,
2899 char **password,
2900 struct cli_credentials *machine_creds,
2901 bool use_queryinfo2,
2902 NTTIME *pwdlastset,
2903 NTSTATUS expected_samlogon_result)
2905 const char *fields = NULL;
2906 bool ret = true;
2908 switch (level) {
2909 case 21:
2910 case 23:
2911 case 25:
2912 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2913 fields_present);
2914 break;
2915 default:
2916 break;
2919 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2920 "(password_expired: %d) %s\n",
2921 use_setinfo2 ? "2":"", level, password_expired,
2922 fields ? fields : "");
2924 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2925 fields_present,
2926 password,
2927 password_expired,
2928 use_setinfo2,
2929 matched_expected_error)) {
2930 ret = false;
2933 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2934 use_queryinfo2,
2935 pwdlastset)) {
2936 ret = false;
2939 if (*matched_expected_error == true) {
2940 return ret;
2943 if (!test_SamLogon_with_creds(tctx, np,
2944 machine_creds,
2945 acct_name,
2946 *password,
2947 expected_samlogon_result,
2948 false)) {
2949 ret = false;
2952 return ret;
2955 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
2956 struct cli_credentials *credentials,
2957 struct dcerpc_pipe **p)
2959 struct dcerpc_binding *b;
2961 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
2962 "failed to get rpc binding");
2964 /* We have to use schannel, otherwise the SamLogonEx fails
2965 * with INTERNAL_ERROR */
2967 b->flags &= ~DCERPC_AUTH_OPTIONS;
2968 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
2970 torture_assert_ntstatus_ok(tctx,
2971 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
2972 credentials, tctx->ev, tctx->lp_ctx),
2973 "failed to bind to netlogon");
2975 return true;
2978 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2979 struct torture_context *tctx,
2980 uint32_t acct_flags,
2981 const char *acct_name,
2982 struct policy_handle *handle,
2983 char **password,
2984 struct cli_credentials *machine_credentials)
2986 int s = 0, q = 0, f = 0, l = 0, z = 0;
2987 bool ret = true;
2988 int delay = 50000;
2989 bool set_levels[] = { false, true };
2990 bool query_levels[] = { false, true };
2991 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
2992 uint32_t nonzeros[] = { 1, 24 };
2993 uint32_t fields_present[] = {
2995 SAMR_FIELD_EXPIRED_FLAG,
2996 SAMR_FIELD_LAST_PWD_CHANGE,
2997 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2998 SAMR_FIELD_COMMENT,
2999 SAMR_FIELD_NT_PASSWORD_PRESENT,
3000 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3001 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3002 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3003 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3004 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3005 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3007 struct dcerpc_pipe *np = NULL;
3009 if (torture_setting_bool(tctx, "samba3", false)) {
3010 delay = 999999;
3011 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3012 delay);
3015 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3017 /* set to 1 to enable testing for all possible opcode
3018 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3019 combinations */
3020 #if 0
3021 #define TEST_ALL_LEVELS 1
3022 #define TEST_SET_LEVELS 1
3023 #define TEST_QUERY_LEVELS 1
3024 #endif
3025 #ifdef TEST_ALL_LEVELS
3026 for (l=0; l<ARRAY_SIZE(levels); l++) {
3027 #else
3028 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3029 #endif
3030 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3031 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3032 #ifdef TEST_SET_LEVELS
3033 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3034 #endif
3035 #ifdef TEST_QUERY_LEVELS
3036 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3037 #endif
3038 NTTIME pwdlastset_old = 0;
3039 NTTIME pwdlastset_new = 0;
3040 bool matched_expected_error = false;
3041 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3043 torture_comment(tctx, "------------------------------\n"
3044 "Testing pwdLastSet attribute for flags: 0x%08x "
3045 "(s: %d (l: %d), q: %d)\n",
3046 acct_flags, s, levels[l], q);
3048 switch (levels[l]) {
3049 case 21:
3050 case 23:
3051 case 25:
3052 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3053 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3054 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3056 break;
3060 /* set #1 */
3062 /* set a password and force password change (pwdlastset 0) by
3063 * setting the password expired flag to a non-0 value */
3065 if (!test_SetPassword_level(p, np, tctx, handle,
3066 levels[l],
3067 fields_present[f],
3068 nonzeros[z],
3069 &matched_expected_error,
3070 set_levels[s],
3071 acct_name,
3072 password,
3073 machine_credentials,
3074 query_levels[q],
3075 &pwdlastset_old,
3076 expected_samlogon_result)) {
3077 ret = false;
3080 if (matched_expected_error == true) {
3081 /* skipping on expected failure */
3082 continue;
3085 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3086 * set without the SAMR_FIELD_EXPIRED_FLAG */
3088 switch (levels[l]) {
3089 case 21:
3090 case 23:
3091 case 25:
3092 if ((pwdlastset_new != 0) &&
3093 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3094 torture_comment(tctx, "not considering a non-0 "
3095 "pwdLastSet as a an error as the "
3096 "SAMR_FIELD_EXPIRED_FLAG has not "
3097 "been set\n");
3098 break;
3100 default:
3101 if (pwdlastset_new != 0) {
3102 torture_warning(tctx, "pwdLastSet test failed: "
3103 "expected pwdLastSet 0 but got %lld\n",
3104 pwdlastset_old);
3105 ret = false;
3107 break;
3110 switch (levels[l]) {
3111 case 21:
3112 case 23:
3113 case 25:
3114 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3115 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3116 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3117 (pwdlastset_old >= pwdlastset_new)) {
3118 torture_warning(tctx, "pwdlastset not increasing\n");
3119 ret = false;
3121 break;
3122 default:
3123 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3124 (pwdlastset_old >= pwdlastset_new)) {
3125 torture_warning(tctx, "pwdlastset not increasing\n");
3126 ret = false;
3128 break;
3131 usleep(delay);
3133 /* set #2 */
3135 /* set a password, pwdlastset needs to get updated (increased
3136 * value), password_expired value used here is 0 */
3138 if (!test_SetPassword_level(p, np, tctx, handle,
3139 levels[l],
3140 fields_present[f],
3142 &matched_expected_error,
3143 set_levels[s],
3144 acct_name,
3145 password,
3146 machine_credentials,
3147 query_levels[q],
3148 &pwdlastset_new,
3149 expected_samlogon_result)) {
3150 ret = false;
3153 /* when a password has been changed, pwdlastset must not be 0 afterwards
3154 * and must be larger then the old value */
3156 switch (levels[l]) {
3157 case 21:
3158 case 23:
3159 case 25:
3161 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3162 * password has been changed, old and new pwdlastset
3163 * need to be the same value */
3165 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3166 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3167 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3169 torture_assert_int_equal(tctx, pwdlastset_old,
3170 pwdlastset_new, "pwdlastset must be equal");
3171 break;
3173 default:
3174 if (pwdlastset_old >= pwdlastset_new) {
3175 torture_warning(tctx, "pwdLastSet test failed: "
3176 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3177 pwdlastset_old, pwdlastset_new);
3178 ret = false;
3180 if (pwdlastset_new == 0) {
3181 torture_warning(tctx, "pwdLastSet test failed: "
3182 "expected non-0 pwdlastset, got: %lld\n",
3183 pwdlastset_new);
3184 ret = false;
3188 switch (levels[l]) {
3189 case 21:
3190 case 23:
3191 case 25:
3192 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3193 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3194 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3195 (pwdlastset_old >= pwdlastset_new)) {
3196 torture_warning(tctx, "pwdlastset not increasing\n");
3197 ret = false;
3199 break;
3200 default:
3201 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3202 (pwdlastset_old >= pwdlastset_new)) {
3203 torture_warning(tctx, "pwdlastset not increasing\n");
3204 ret = false;
3206 break;
3209 pwdlastset_old = pwdlastset_new;
3211 usleep(delay);
3213 /* set #2b */
3215 /* set a password, pwdlastset needs to get updated (increased
3216 * value), password_expired value used here is 0 */
3218 if (!test_SetPassword_level(p, np, tctx, handle,
3219 levels[l],
3220 fields_present[f],
3222 &matched_expected_error,
3223 set_levels[s],
3224 acct_name,
3225 password,
3226 machine_credentials,
3227 query_levels[q],
3228 &pwdlastset_new,
3229 expected_samlogon_result)) {
3230 ret = false;
3233 /* when a password has been changed, pwdlastset must not be 0 afterwards
3234 * and must be larger then the old value */
3236 switch (levels[l]) {
3237 case 21:
3238 case 23:
3239 case 25:
3241 /* if no password has been changed, old and new pwdlastset
3242 * need to be the same value */
3244 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3245 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3247 torture_assert_int_equal(tctx, pwdlastset_old,
3248 pwdlastset_new, "pwdlastset must be equal");
3249 break;
3251 default:
3252 if (pwdlastset_old >= pwdlastset_new) {
3253 torture_warning(tctx, "pwdLastSet test failed: "
3254 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3255 pwdlastset_old, pwdlastset_new);
3256 ret = false;
3258 if (pwdlastset_new == 0) {
3259 torture_warning(tctx, "pwdLastSet test failed: "
3260 "expected non-0 pwdlastset, got: %lld\n",
3261 pwdlastset_new);
3262 ret = false;
3266 /* set #3 */
3268 /* set a password and force password change (pwdlastset 0) by
3269 * setting the password expired flag to a non-0 value */
3271 if (!test_SetPassword_level(p, np, tctx, handle,
3272 levels[l],
3273 fields_present[f],
3274 nonzeros[z],
3275 &matched_expected_error,
3276 set_levels[s],
3277 acct_name,
3278 password,
3279 machine_credentials,
3280 query_levels[q],
3281 &pwdlastset_new,
3282 expected_samlogon_result)) {
3283 ret = false;
3286 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3287 * set without the SAMR_FIELD_EXPIRED_FLAG */
3289 switch (levels[l]) {
3290 case 21:
3291 case 23:
3292 case 25:
3293 if ((pwdlastset_new != 0) &&
3294 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3295 torture_comment(tctx, "not considering a non-0 "
3296 "pwdLastSet as a an error as the "
3297 "SAMR_FIELD_EXPIRED_FLAG has not "
3298 "been set\n");
3299 break;
3302 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3303 * password has been changed, old and new pwdlastset
3304 * need to be the same value */
3306 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3307 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3308 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3310 torture_assert_int_equal(tctx, pwdlastset_old,
3311 pwdlastset_new, "pwdlastset must be equal");
3312 break;
3314 default:
3316 if (pwdlastset_old == pwdlastset_new) {
3317 torture_warning(tctx, "pwdLastSet test failed: "
3318 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3319 pwdlastset_old, pwdlastset_new);
3320 ret = false;
3323 if (pwdlastset_new != 0) {
3324 torture_warning(tctx, "pwdLastSet test failed: "
3325 "expected pwdLastSet 0, got %lld\n",
3326 pwdlastset_old);
3327 ret = false;
3329 break;
3332 switch (levels[l]) {
3333 case 21:
3334 case 23:
3335 case 25:
3336 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3337 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3338 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3339 (pwdlastset_old >= pwdlastset_new)) {
3340 torture_warning(tctx, "pwdlastset not increasing\n");
3341 ret = false;
3343 break;
3344 default:
3345 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3346 (pwdlastset_old >= pwdlastset_new)) {
3347 torture_warning(tctx, "pwdlastset not increasing\n");
3348 ret = false;
3350 break;
3353 /* if the level we are testing does not have a fields_present
3354 * field, skip all fields present tests by setting f to to
3355 * arraysize */
3356 switch (levels[l]) {
3357 case 18:
3358 case 24:
3359 case 26:
3360 f = ARRAY_SIZE(fields_present);
3361 break;
3364 #ifdef TEST_QUERY_LEVELS
3366 #endif
3367 #ifdef TEST_SET_LEVELS
3369 #endif
3370 } /* fields present */
3371 } /* nonzeros */
3372 } /* levels */
3374 #undef TEST_SET_LEVELS
3375 #undef TEST_QUERY_LEVELS
3377 talloc_free(np);
3379 return ret;
3382 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_pipe *p,
3383 struct torture_context *tctx,
3384 struct policy_handle *handle,
3385 uint32_t *badpwdcount)
3387 union samr_UserInfo *info;
3388 struct samr_QueryUserInfo r;
3390 r.in.user_handle = handle;
3391 r.in.level = 3;
3392 r.out.info = &info;
3394 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3396 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo(p, tctx, &r),
3397 "failed to query userinfo");
3399 *badpwdcount = info->info3.bad_password_count;
3401 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3403 return true;
3406 static bool test_SetUserInfo_acct_flags(struct dcerpc_pipe *p,
3407 struct torture_context *tctx,
3408 struct policy_handle *user_handle,
3409 uint32_t acct_flags)
3411 struct samr_SetUserInfo r;
3412 union samr_UserInfo user_info;
3414 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3416 user_info.info16.acct_flags = acct_flags;
3418 r.in.user_handle = user_handle;
3419 r.in.level = 16;
3420 r.in.info = &user_info;
3422 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo(p, tctx, &r),
3423 "failed to set account flags");
3425 return true;
3428 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3429 struct torture_context *tctx,
3430 struct policy_handle *user_handle,
3431 uint32_t acct_flags,
3432 char **password)
3434 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3435 "failed to set password");
3437 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3439 torture_assert(tctx,
3440 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3441 acct_flags & ~ACB_DISABLED),
3442 "failed to enable user");
3444 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3445 "failed to set password");
3447 return true;
3450 static bool test_SetDomainInfo(struct dcerpc_pipe *p,
3451 struct torture_context *tctx,
3452 struct policy_handle *domain_handle,
3453 enum samr_DomainInfoClass level,
3454 union samr_DomainInfo *info)
3456 struct samr_SetDomainInfo r;
3458 r.in.domain_handle = domain_handle;
3459 r.in.level = level;
3460 r.in.info = info;
3462 torture_assert_ntstatus_ok(tctx,
3463 dcerpc_samr_SetDomainInfo(p, tctx, &r),
3464 "failed to set domain info");
3466 return true;
3469 static bool test_SetDomainInfo_ntstatus(struct dcerpc_pipe *p,
3470 struct torture_context *tctx,
3471 struct policy_handle *domain_handle,
3472 enum samr_DomainInfoClass level,
3473 union samr_DomainInfo *info,
3474 NTSTATUS expected)
3476 struct samr_SetDomainInfo r;
3478 r.in.domain_handle = domain_handle;
3479 r.in.level = level;
3480 r.in.info = info;
3482 torture_assert_ntstatus_equal(tctx,
3483 dcerpc_samr_SetDomainInfo(p, tctx, &r),
3484 expected,
3485 "");
3487 return true;
3490 static bool test_QueryDomainInfo2_level(struct dcerpc_pipe *p,
3491 struct torture_context *tctx,
3492 struct policy_handle *domain_handle,
3493 enum samr_DomainInfoClass level,
3494 union samr_DomainInfo **q_info)
3496 struct samr_QueryDomainInfo2 r;
3498 r.in.domain_handle = domain_handle;
3499 r.in.level = level;
3500 r.out.info = q_info;
3502 torture_assert_ntstatus_ok(tctx,
3503 dcerpc_samr_QueryDomainInfo2(p, tctx, &r),
3504 "failed to query domain info");
3506 return true;
3509 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3510 struct dcerpc_pipe *np,
3511 struct torture_context *tctx,
3512 uint32_t acct_flags,
3513 const char *acct_name,
3514 struct policy_handle *domain_handle,
3515 struct policy_handle *user_handle,
3516 char **password,
3517 struct cli_credentials *machine_credentials,
3518 const char *comment,
3519 bool disable,
3520 bool interactive,
3521 NTSTATUS expected_success_status,
3522 struct samr_DomInfo1 *info1,
3523 struct samr_DomInfo12 *info12)
3525 union samr_DomainInfo info;
3526 char **passwords;
3527 int i;
3528 uint32_t badpwdcount, tmp;
3529 uint32_t password_history_length = 12;
3530 uint32_t lockout_threshold = 15;
3532 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3534 torture_assert(tctx, password_history_length < lockout_threshold,
3535 "password history length needs to be smaller than account lockout threshold for this test");
3538 /* set policies */
3540 info.info1 = *info1;
3541 info.info1.password_history_length = password_history_length;
3543 torture_assert(tctx,
3544 test_SetDomainInfo(p, tctx, domain_handle,
3545 DomainPasswordInformation, &info),
3546 "failed to set password history length");
3548 info.info12 = *info12;
3549 info.info12.lockout_threshold = lockout_threshold;
3551 torture_assert(tctx,
3552 test_SetDomainInfo(p, tctx, domain_handle,
3553 DomainLockoutInformation, &info),
3554 "failed to set lockout threshold");
3556 /* reset bad pwd count */
3558 torture_assert(tctx,
3559 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3562 /* enable or disable account */
3563 if (disable) {
3564 torture_assert(tctx,
3565 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3566 acct_flags | ACB_DISABLED),
3567 "failed to disable user");
3568 } else {
3569 torture_assert(tctx,
3570 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3571 acct_flags & ~ACB_DISABLED),
3572 "failed to enable user");
3576 /* setup password history */
3578 passwords = talloc_array(tctx, char *, password_history_length);
3580 for (i=0; i < password_history_length; i++) {
3582 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3583 "failed to set password");
3584 passwords[i] = talloc_strdup(tctx, *password);
3586 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3587 acct_name, passwords[i],
3588 expected_success_status, interactive)) {
3589 torture_fail(tctx, "failed to auth with latest password");
3592 torture_assert(tctx,
3593 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3595 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3599 /* test with wrong password */
3601 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3602 acct_name, "random_crap",
3603 NT_STATUS_WRONG_PASSWORD, interactive)) {
3604 torture_fail(tctx, "succeeded to authenticate with wrong password");
3607 torture_assert(tctx,
3608 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3610 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3613 /* test with latest good password */
3615 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3616 passwords[password_history_length-1],
3617 expected_success_status, interactive)) {
3618 torture_fail(tctx, "succeeded to authenticate with wrong password");
3621 torture_assert(tctx,
3622 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3624 if (disable) {
3625 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3626 } else {
3627 /* only enabled accounts get the bad pwd count reset upon
3628 * successful logon */
3629 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3632 tmp = badpwdcount;
3635 /* test password history */
3637 for (i=0; i < password_history_length; i++) {
3639 torture_comment(tctx, "Testing bad password count behavior with "
3640 "password #%d of #%d\n", i, password_history_length);
3642 /* - network samlogon will succeed auth and not
3643 * increase badpwdcount for 2 last entries
3644 * - interactive samlogon only for the last one */
3646 if (i == password_history_length - 1 ||
3647 (i == password_history_length - 2 && !interactive)) {
3649 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3650 acct_name, passwords[i],
3651 expected_success_status, interactive)) {
3652 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3655 torture_assert(tctx,
3656 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3658 if (disable) {
3659 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3660 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3661 } else {
3662 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3663 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3666 tmp = badpwdcount;
3668 continue;
3671 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3672 acct_name, passwords[i],
3673 NT_STATUS_WRONG_PASSWORD, interactive)) {
3674 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3677 torture_assert(tctx,
3678 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3680 /* - network samlogon will fail auth but not increase
3681 * badpwdcount for 3rd last entry
3682 * - interactive samlogon for 3rd and 2nd last entry */
3684 if (i == password_history_length - 3 ||
3685 (i == password_history_length - 2 && interactive)) {
3686 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3687 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3688 } else {
3689 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3690 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3693 tmp = badpwdcount;
3696 return true;
3699 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3700 struct torture_context *tctx,
3701 uint32_t acct_flags,
3702 const char *acct_name,
3703 struct policy_handle *domain_handle,
3704 struct policy_handle *user_handle,
3705 char **password,
3706 struct cli_credentials *machine_credentials)
3708 union samr_DomainInfo *q_info, s_info;
3709 struct samr_DomInfo1 info1, _info1;
3710 struct samr_DomInfo12 info12, _info12;
3711 bool ret = true;
3712 struct dcerpc_pipe *np;
3713 int i;
3715 struct {
3716 const char *comment;
3717 bool disabled;
3718 bool interactive;
3719 NTSTATUS expected_success_status;
3720 } creds[] = {
3722 .comment = "network logon (disabled account)",
3723 .disabled = true,
3724 .interactive = false,
3725 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3728 .comment = "network logon (enabled account)",
3729 .disabled = false,
3730 .interactive = false,
3731 .expected_success_status= NT_STATUS_OK
3734 .comment = "interactive logon (disabled account)",
3735 .disabled = true,
3736 .interactive = true,
3737 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3740 .comment = "interactive logon (enabled account)",
3741 .disabled = false,
3742 .interactive = true,
3743 .expected_success_status= NT_STATUS_OK
3747 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3749 /* backup old policies */
3751 torture_assert(tctx,
3752 test_QueryDomainInfo2_level(p, tctx, domain_handle,
3753 DomainPasswordInformation, &q_info),
3754 "failed to query domain info level 1");
3756 info1 = q_info->info1;
3757 _info1 = info1;
3759 torture_assert(tctx,
3760 test_QueryDomainInfo2_level(p, tctx, domain_handle,
3761 DomainLockoutInformation, &q_info),
3762 "failed to query domain info level 12");
3764 info12 = q_info->info12;
3765 _info12 = info12;
3767 /* run tests */
3769 for (i=0; i < ARRAY_SIZE(creds); i++) {
3771 /* skip trust tests for now */
3772 if (acct_flags & ACB_WSTRUST ||
3773 acct_flags & ACB_SVRTRUST ||
3774 acct_flags & ACB_DOMTRUST) {
3775 continue;
3778 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
3779 domain_handle, user_handle, password,
3780 machine_credentials,
3781 creds[i].comment,
3782 creds[i].disabled,
3783 creds[i].interactive,
3784 creds[i].expected_success_status,
3785 &_info1, &_info12);
3786 if (!ret) {
3787 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
3788 } else {
3789 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
3793 /* restore policies */
3795 s_info.info1 = info1;
3797 torture_assert(tctx,
3798 test_SetDomainInfo(p, tctx, domain_handle,
3799 DomainPasswordInformation, &s_info),
3800 "failed to set password information");
3802 s_info.info12 = info12;
3804 torture_assert(tctx,
3805 test_SetDomainInfo(p, tctx, domain_handle,
3806 DomainLockoutInformation, &s_info),
3807 "failed to set lockout information");
3809 return ret;
3812 static bool test_QueryUserInfo_acct_flags(struct dcerpc_pipe *p,
3813 struct torture_context *tctx,
3814 struct policy_handle *handle,
3815 uint32_t *acct_flags)
3817 union samr_UserInfo *info;
3818 struct samr_QueryUserInfo r;
3820 r.in.user_handle = handle;
3821 r.in.level = 16;
3822 r.out.info = &info;
3824 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3826 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo(p, tctx, &r),
3827 "failed to query userinfo");
3829 *acct_flags = info->info16.acct_flags;
3831 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
3833 return true;
3836 static bool test_Password_lockout(struct dcerpc_pipe *p,
3837 struct dcerpc_pipe *np,
3838 struct torture_context *tctx,
3839 uint32_t acct_flags,
3840 const char *acct_name,
3841 struct policy_handle *domain_handle,
3842 struct policy_handle *user_handle,
3843 char **password,
3844 struct cli_credentials *machine_credentials,
3845 const char *comment,
3846 bool disable,
3847 bool interactive,
3848 NTSTATUS expected_success_status,
3849 struct samr_DomInfo1 *info1,
3850 struct samr_DomInfo12 *info12)
3852 union samr_DomainInfo info;
3853 uint32_t badpwdcount;
3854 uint32_t password_history_length = 1;
3855 uint64_t lockout_threshold = 1;
3856 uint32_t lockout_seconds = 5;
3857 uint64_t delta_time_factor = 10 * 1000 * 1000;
3859 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
3861 /* set policies */
3863 info.info1 = *info1;
3865 torture_comment(tctx, "setting password history lenght.\n");
3866 info.info1.password_history_length = password_history_length;
3868 torture_assert(tctx,
3869 test_SetDomainInfo(p, tctx, domain_handle,
3870 DomainPasswordInformation, &info),
3871 "failed to set password history length");
3873 info.info12 = *info12;
3874 info.info12.lockout_threshold = lockout_threshold;
3876 /* set lockout duration < lockout window: should fail */
3877 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3878 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
3880 torture_assert(tctx,
3881 test_SetDomainInfo_ntstatus(p, tctx, domain_handle,
3882 DomainLockoutInformation, &info,
3883 NT_STATUS_INVALID_PARAMETER),
3884 "setting lockout duration < lockout window gave unexpected result");
3886 info.info12.lockout_duration = 0;
3887 info.info12.lockout_window = 0;
3889 torture_assert(tctx,
3890 test_SetDomainInfo(p, tctx, domain_handle,
3891 DomainLockoutInformation, &info),
3892 "failed to set lockout window and duration to 0");
3895 /* set lockout duration of 5 seconds */
3896 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3897 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
3899 torture_assert(tctx,
3900 test_SetDomainInfo(p, tctx, domain_handle,
3901 DomainLockoutInformation, &info),
3902 "failed to set lockout window and duration to 5 seconds");
3904 /* reset bad pwd count */
3906 torture_assert(tctx,
3907 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3910 /* enable or disable account */
3912 if (disable) {
3913 torture_assert(tctx,
3914 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3915 acct_flags | ACB_DISABLED),
3916 "failed to disable user");
3917 } else {
3918 torture_assert(tctx,
3919 test_SetUserInfo_acct_flags(p, tctx, user_handle,
3920 acct_flags & ~ACB_DISABLED),
3921 "failed to enable user");
3925 /* test logon with right password */
3927 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3928 acct_name, *password,
3929 expected_success_status, interactive)) {
3930 torture_fail(tctx, "failed to auth with latest password");
3933 torture_assert(tctx,
3934 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3935 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3938 /* test with wrong password ==> lockout */
3940 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3941 acct_name, "random_crap",
3942 NT_STATUS_WRONG_PASSWORD, interactive)) {
3943 torture_fail(tctx, "succeeded to authenticate with wrong password");
3946 torture_assert(tctx,
3947 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3948 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3950 torture_assert(tctx,
3951 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3952 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3953 "expected account to be locked");
3956 /* test with good password */
3958 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3959 *password,
3960 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
3962 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
3965 /* bad pwd count should not get updated */
3966 torture_assert(tctx,
3967 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3968 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3970 /* curiously, windows does _not_ set the autlock flag */
3971 torture_assert(tctx,
3972 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3973 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3974 "expected account to be locked");
3977 /* with bad password */
3979 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3980 acct_name, "random_crap2",
3981 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
3983 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
3986 /* bad pwd count should not get updated */
3987 torture_assert(tctx,
3988 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3989 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3991 /* curiously, windows does _not_ set the autlock flag */
3992 torture_assert(tctx,
3993 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3994 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3995 "expected account to be locked");
3998 /* let lockout duration expire ==> unlock */
4000 torture_comment(tctx, "let lockout duration expire...\n");
4001 sleep(lockout_seconds + 1);
4003 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4004 *password,
4005 expected_success_status, interactive))
4007 torture_fail(tctx, "failed to authenticate after lockout expired");
4010 torture_assert(tctx,
4011 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
4012 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4013 "expected account not to be locked");
4015 return true;
4018 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4019 struct torture_context *tctx,
4020 uint32_t acct_flags,
4021 const char *acct_name,
4022 struct policy_handle *domain_handle,
4023 struct policy_handle *user_handle,
4024 char **password,
4025 struct cli_credentials *machine_credentials)
4027 union samr_DomainInfo *q_info, s_info;
4028 struct samr_DomInfo1 info1, _info1;
4029 struct samr_DomInfo12 info12, _info12;
4030 bool ret = true;
4031 struct dcerpc_pipe *np;
4032 int i;
4034 struct {
4035 const char *comment;
4036 bool disabled;
4037 bool interactive;
4038 NTSTATUS expected_success_status;
4039 } creds[] = {
4041 .comment = "network logon (disabled account)",
4042 .disabled = true,
4043 .interactive = false,
4044 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4047 .comment = "network logon (enabled account)",
4048 .disabled = false,
4049 .interactive = false,
4050 .expected_success_status= NT_STATUS_OK
4053 .comment = "interactive logon (disabled account)",
4054 .disabled = true,
4055 .interactive = true,
4056 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4059 .comment = "interactive logon (enabled account)",
4060 .disabled = false,
4061 .interactive = true,
4062 .expected_success_status= NT_STATUS_OK
4066 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4068 /* backup old policies */
4070 torture_assert(tctx,
4071 test_QueryDomainInfo2_level(p, tctx, domain_handle,
4072 DomainPasswordInformation, &q_info),
4073 "failed to query domain info level 1");
4075 info1 = q_info->info1;
4076 _info1 = info1;
4078 torture_assert(tctx,
4079 test_QueryDomainInfo2_level(p, tctx, domain_handle,
4080 DomainLockoutInformation, &q_info),
4081 "failed to query domain info level 12");
4083 info12 = q_info->info12;
4084 _info12 = info12;
4086 /* run tests */
4088 for (i=0; i < ARRAY_SIZE(creds); i++) {
4090 /* skip trust tests for now */
4091 if (acct_flags & ACB_WSTRUST ||
4092 acct_flags & ACB_SVRTRUST ||
4093 acct_flags & ACB_DOMTRUST) {
4094 continue;
4097 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4098 domain_handle, user_handle, password,
4099 machine_credentials,
4100 creds[i].comment,
4101 creds[i].disabled,
4102 creds[i].interactive,
4103 creds[i].expected_success_status,
4104 &_info1, &_info12);
4105 if (!ret) {
4106 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4107 } else {
4108 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4112 /* restore policies */
4114 s_info.info1 = info1;
4116 torture_assert(tctx,
4117 test_SetDomainInfo(p, tctx, domain_handle,
4118 DomainPasswordInformation, &s_info),
4119 "failed to set password information");
4121 s_info.info12 = info12;
4123 torture_assert(tctx,
4124 test_SetDomainInfo(p, tctx, domain_handle,
4125 DomainLockoutInformation, &s_info),
4126 "failed to set lockout information");
4128 return ret;
4131 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4132 struct dcerpc_pipe *lp,
4133 struct torture_context *tctx,
4134 struct policy_handle *domain_handle,
4135 struct policy_handle *lsa_handle,
4136 struct policy_handle *user_handle,
4137 const struct dom_sid *domain_sid,
4138 uint32_t rid,
4139 struct cli_credentials *machine_credentials)
4141 NTSTATUS status;
4142 bool ret = true;
4144 struct policy_handle lsa_acct_handle;
4145 struct dom_sid *user_sid;
4147 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4150 struct lsa_EnumAccountRights r;
4151 struct lsa_RightSet rights;
4153 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4155 r.in.handle = lsa_handle;
4156 r.in.sid = user_sid;
4157 r.out.rights = &rights;
4159 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4160 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4161 "Expected enum rights for account to fail");
4165 struct lsa_RightSet rights;
4166 struct lsa_StringLarge names[2];
4167 struct lsa_AddAccountRights r;
4169 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4171 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4172 init_lsa_StringLarge(&names[1], NULL);
4174 rights.count = 1;
4175 rights.names = names;
4177 r.in.handle = lsa_handle;
4178 r.in.sid = user_sid;
4179 r.in.rights = &rights;
4181 status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
4182 torture_assert_ntstatus_ok(tctx, status,
4183 "Failed to add privileges");
4187 struct lsa_EnumAccounts r;
4188 uint32_t resume_handle = 0;
4189 struct lsa_SidArray lsa_sid_array;
4190 int i;
4191 bool found_sid = false;
4193 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4195 r.in.handle = lsa_handle;
4196 r.in.num_entries = 0x1000;
4197 r.in.resume_handle = &resume_handle;
4198 r.out.sids = &lsa_sid_array;
4199 r.out.resume_handle = &resume_handle;
4201 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4202 torture_assert_ntstatus_ok(tctx, status,
4203 "Failed to enum accounts");
4205 for (i=0; i < lsa_sid_array.num_sids; i++) {
4206 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4207 found_sid = true;
4211 torture_assert(tctx, found_sid,
4212 "failed to list privileged account");
4216 struct lsa_EnumAccountRights r;
4217 struct lsa_RightSet user_rights;
4219 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4221 r.in.handle = lsa_handle;
4222 r.in.sid = user_sid;
4223 r.out.rights = &user_rights;
4225 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4226 torture_assert_ntstatus_ok(tctx, status,
4227 "Failed to enum rights for account");
4229 if (user_rights.count < 1) {
4230 torture_warning(tctx, "failed to find newly added rights");
4231 return false;
4236 struct lsa_OpenAccount r;
4238 torture_comment(tctx, "Testing LSA OpenAccount\n");
4240 r.in.handle = lsa_handle;
4241 r.in.sid = user_sid;
4242 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4243 r.out.acct_handle = &lsa_acct_handle;
4245 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
4246 torture_assert_ntstatus_ok(tctx, status,
4247 "Failed to open lsa account");
4251 struct lsa_GetSystemAccessAccount r;
4252 uint32_t access_mask;
4254 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4256 r.in.handle = &lsa_acct_handle;
4257 r.out.access_mask = &access_mask;
4259 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
4260 torture_assert_ntstatus_ok(tctx, status,
4261 "Failed to get lsa system access account");
4265 struct lsa_Close r;
4267 torture_comment(tctx, "Testing LSA Close\n");
4269 r.in.handle = &lsa_acct_handle;
4270 r.out.handle = &lsa_acct_handle;
4272 status = dcerpc_lsa_Close(lp, tctx, &r);
4273 torture_assert_ntstatus_ok(tctx, status,
4274 "Failed to close lsa");
4278 struct samr_DeleteUser r;
4280 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4282 r.in.user_handle = user_handle;
4283 r.out.user_handle = user_handle;
4285 status = dcerpc_samr_DeleteUser(p, tctx, &r);
4286 torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
4290 struct lsa_EnumAccounts r;
4291 uint32_t resume_handle = 0;
4292 struct lsa_SidArray lsa_sid_array;
4293 int i;
4294 bool found_sid = false;
4296 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4298 r.in.handle = lsa_handle;
4299 r.in.num_entries = 0x1000;
4300 r.in.resume_handle = &resume_handle;
4301 r.out.sids = &lsa_sid_array;
4302 r.out.resume_handle = &resume_handle;
4304 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4305 torture_assert_ntstatus_ok(tctx, status,
4306 "Failed to enum accounts");
4308 for (i=0; i < lsa_sid_array.num_sids; i++) {
4309 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4310 found_sid = true;
4314 torture_assert(tctx, found_sid,
4315 "failed to list privileged account");
4319 struct lsa_EnumAccountRights r;
4320 struct lsa_RightSet user_rights;
4322 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4324 r.in.handle = lsa_handle;
4325 r.in.sid = user_sid;
4326 r.out.rights = &user_rights;
4328 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4329 torture_assert_ntstatus_ok(tctx, status,
4330 "Failed to enum rights for account");
4332 if (user_rights.count < 1) {
4333 torture_warning(tctx, "failed to find newly added rights");
4334 return false;
4339 struct lsa_OpenAccount r;
4341 torture_comment(tctx, "Testing LSA OpenAccount\n");
4343 r.in.handle = lsa_handle;
4344 r.in.sid = user_sid;
4345 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4346 r.out.acct_handle = &lsa_acct_handle;
4348 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
4349 torture_assert_ntstatus_ok(tctx, status,
4350 "Failed to open lsa account");
4354 struct lsa_GetSystemAccessAccount r;
4355 uint32_t access_mask;
4357 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4359 r.in.handle = &lsa_acct_handle;
4360 r.out.access_mask = &access_mask;
4362 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
4363 torture_assert_ntstatus_ok(tctx, status,
4364 "Failed to get lsa system access account");
4368 struct lsa_DeleteObject r;
4370 torture_comment(tctx, "Testing LSA DeleteObject\n");
4372 r.in.handle = &lsa_acct_handle;
4373 r.out.handle = &lsa_acct_handle;
4375 status = dcerpc_lsa_DeleteObject(lp, tctx, &r);
4376 torture_assert_ntstatus_ok(tctx, status,
4377 "Failed to delete object");
4381 struct lsa_EnumAccounts r;
4382 uint32_t resume_handle = 0;
4383 struct lsa_SidArray lsa_sid_array;
4384 int i;
4385 bool found_sid = false;
4387 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4389 r.in.handle = lsa_handle;
4390 r.in.num_entries = 0x1000;
4391 r.in.resume_handle = &resume_handle;
4392 r.out.sids = &lsa_sid_array;
4393 r.out.resume_handle = &resume_handle;
4395 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4396 torture_assert_ntstatus_ok(tctx, status,
4397 "Failed to enum accounts");
4399 for (i=0; i < lsa_sid_array.num_sids; i++) {
4400 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4401 found_sid = true;
4405 torture_assert(tctx, !found_sid,
4406 "should not have listed privileged account");
4410 struct lsa_EnumAccountRights r;
4411 struct lsa_RightSet user_rights;
4413 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4415 r.in.handle = lsa_handle;
4416 r.in.sid = user_sid;
4417 r.out.rights = &user_rights;
4419 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4420 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4421 "Failed to enum rights for account");
4424 return ret;
4427 static bool test_user_ops(struct dcerpc_pipe *p,
4428 struct torture_context *tctx,
4429 struct policy_handle *user_handle,
4430 struct policy_handle *domain_handle,
4431 const struct dom_sid *domain_sid,
4432 uint32_t base_acct_flags,
4433 const char *base_acct_name, enum torture_samr_choice which_ops,
4434 struct cli_credentials *machine_credentials)
4436 char *password = NULL;
4437 struct samr_QueryUserInfo q;
4438 union samr_UserInfo *info;
4439 NTSTATUS status;
4441 bool ret = true;
4442 int i;
4443 uint32_t rid;
4444 const uint32_t password_fields[] = {
4445 SAMR_FIELD_NT_PASSWORD_PRESENT,
4446 SAMR_FIELD_LM_PASSWORD_PRESENT,
4447 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4451 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
4452 if (!NT_STATUS_IS_OK(status)) {
4453 ret = false;
4456 switch (which_ops) {
4457 case TORTURE_SAMR_USER_ATTRIBUTES:
4458 if (!test_QuerySecurity(p, tctx, user_handle)) {
4459 ret = false;
4462 if (!test_QueryUserInfo(p, tctx, user_handle)) {
4463 ret = false;
4466 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
4467 ret = false;
4470 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
4471 base_acct_name)) {
4472 ret = false;
4475 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
4476 ret = false;
4479 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
4480 ret = false;
4483 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4484 ret = false;
4486 break;
4487 case TORTURE_SAMR_PASSWORDS:
4488 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4489 char simple_pass[9];
4490 char *v = generate_random_str(tctx, 1);
4492 ZERO_STRUCT(simple_pass);
4493 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4495 torture_comment(tctx, "Testing machine account password policy rules\n");
4497 /* Workstation trust accounts don't seem to need to honour password quality policy */
4498 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4499 ret = false;
4502 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4503 ret = false;
4506 /* reset again, to allow another 'user' password change */
4507 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4508 ret = false;
4511 /* Try a 'short' password */
4512 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4513 ret = false;
4516 /* Try a compleatly random password */
4517 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4518 ret = false;
4522 for (i = 0; password_fields[i]; i++) {
4523 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4524 ret = false;
4527 /* check it was set right */
4528 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4529 ret = false;
4533 for (i = 0; password_fields[i]; i++) {
4534 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4535 ret = false;
4538 /* check it was set right */
4539 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4540 ret = false;
4544 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4545 ret = false;
4548 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4549 ret = false;
4552 if (torture_setting_bool(tctx, "samba4", false)) {
4553 torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
4554 } else {
4556 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4557 ret = false;
4560 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4561 ret = false;
4564 for (i = 0; password_fields[i]; i++) {
4566 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4567 /* we need to skip as that would break
4568 * the ChangePasswordUser3 verify */
4569 continue;
4572 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4573 ret = false;
4576 /* check it was set right */
4577 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4578 ret = false;
4583 q.in.user_handle = user_handle;
4584 q.in.level = 5;
4585 q.out.info = &info;
4587 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4588 if (!NT_STATUS_IS_OK(status)) {
4589 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4590 q.in.level, nt_errstr(status));
4591 ret = false;
4592 } else {
4593 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4594 if ((info->info5.acct_flags) != expected_flags) {
4595 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4596 info->info5.acct_flags,
4597 expected_flags);
4598 /* FIXME: GD */
4599 if (!torture_setting_bool(tctx, "samba3", false)) {
4600 ret = false;
4603 if (info->info5.rid != rid) {
4604 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4605 info->info5.rid, rid);
4610 break;
4612 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4614 /* test last password change timestamp behaviour */
4615 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4616 base_acct_name,
4617 user_handle, &password,
4618 machine_credentials)) {
4619 ret = false;
4622 if (ret == true) {
4623 torture_comment(tctx, "pwdLastSet test succeeded\n");
4624 } else {
4625 torture_warning(tctx, "pwdLastSet test failed\n");
4628 break;
4630 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4632 /* test bad pwd count change behaviour */
4633 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4634 base_acct_name,
4635 domain_handle,
4636 user_handle, &password,
4637 machine_credentials)) {
4638 ret = false;
4641 if (ret == true) {
4642 torture_comment(tctx, "badPwdCount test succeeded\n");
4643 } else {
4644 torture_warning(tctx, "badPwdCount test failed\n");
4647 break;
4649 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4651 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4652 base_acct_name,
4653 domain_handle,
4654 user_handle, &password,
4655 machine_credentials))
4657 ret = false;
4660 if (ret == true) {
4661 torture_comment(tctx, "lockout test succeeded\n");
4662 } else {
4663 torture_warning(tctx, "lockout test failed\n");
4666 break;
4669 case TORTURE_SAMR_USER_PRIVILEGES: {
4671 struct dcerpc_pipe *lp;
4672 struct policy_handle *lsa_handle;
4674 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4675 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4677 if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
4678 ret = false;
4681 if (!test_DeleteUser_with_privs(p, lp, tctx,
4682 domain_handle, lsa_handle, user_handle,
4683 domain_sid, rid,
4684 machine_credentials)) {
4685 ret = false;
4688 if (!test_lsa_Close(lp, tctx, lsa_handle)) {
4689 ret = false;
4692 if (!ret) {
4693 torture_warning(tctx, "privileged user delete test failed\n");
4696 break;
4698 case TORTURE_SAMR_OTHER:
4699 /* We just need the account to exist */
4700 break;
4702 return ret;
4705 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
4706 struct policy_handle *alias_handle,
4707 const struct dom_sid *domain_sid)
4709 bool ret = true;
4711 if (!torture_setting_bool(tctx, "samba3", false)) {
4712 if (!test_QuerySecurity(p, tctx, alias_handle)) {
4713 ret = false;
4717 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
4718 ret = false;
4721 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
4722 ret = false;
4725 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
4726 ret = false;
4729 if (torture_setting_bool(tctx, "samba3", false) ||
4730 torture_setting_bool(tctx, "samba4", false)) {
4731 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4732 return ret;
4735 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
4736 ret = false;
4739 return ret;
4743 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
4744 struct policy_handle *user_handle)
4746 struct samr_DeleteUser d;
4747 NTSTATUS status;
4748 torture_comment(tctx, "Testing DeleteUser\n");
4750 d.in.user_handle = user_handle;
4751 d.out.user_handle = user_handle;
4753 status = dcerpc_samr_DeleteUser(p, tctx, &d);
4754 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
4756 return true;
4759 bool test_DeleteUser_byname(struct dcerpc_pipe *p,
4760 struct torture_context *tctx,
4761 struct policy_handle *handle, const char *name)
4763 NTSTATUS status;
4764 struct samr_DeleteUser d;
4765 struct policy_handle user_handle;
4766 uint32_t rid;
4768 status = test_LookupName(p, tctx, handle, name, &rid);
4769 if (!NT_STATUS_IS_OK(status)) {
4770 goto failed;
4773 status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
4774 if (!NT_STATUS_IS_OK(status)) {
4775 goto failed;
4778 d.in.user_handle = &user_handle;
4779 d.out.user_handle = &user_handle;
4780 status = dcerpc_samr_DeleteUser(p, tctx, &d);
4781 if (!NT_STATUS_IS_OK(status)) {
4782 goto failed;
4785 return true;
4787 failed:
4788 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
4789 return false;
4793 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
4794 struct torture_context *tctx,
4795 struct policy_handle *handle, const char *name)
4797 NTSTATUS status;
4798 struct samr_OpenGroup r;
4799 struct samr_DeleteDomainGroup d;
4800 struct policy_handle group_handle;
4801 uint32_t rid;
4803 status = test_LookupName(p, tctx, handle, name, &rid);
4804 if (!NT_STATUS_IS_OK(status)) {
4805 goto failed;
4808 r.in.domain_handle = handle;
4809 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4810 r.in.rid = rid;
4811 r.out.group_handle = &group_handle;
4812 status = dcerpc_samr_OpenGroup(p, tctx, &r);
4813 if (!NT_STATUS_IS_OK(status)) {
4814 goto failed;
4817 d.in.group_handle = &group_handle;
4818 d.out.group_handle = &group_handle;
4819 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
4820 if (!NT_STATUS_IS_OK(status)) {
4821 goto failed;
4824 return true;
4826 failed:
4827 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
4828 return false;
4832 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
4833 struct torture_context *tctx,
4834 struct policy_handle *domain_handle,
4835 const char *name)
4837 NTSTATUS status;
4838 struct samr_OpenAlias r;
4839 struct samr_DeleteDomAlias d;
4840 struct policy_handle alias_handle;
4841 uint32_t rid;
4843 torture_comment(tctx, "testing DeleteAlias_byname\n");
4845 status = test_LookupName(p, tctx, domain_handle, name, &rid);
4846 if (!NT_STATUS_IS_OK(status)) {
4847 goto failed;
4850 r.in.domain_handle = domain_handle;
4851 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4852 r.in.rid = rid;
4853 r.out.alias_handle = &alias_handle;
4854 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 goto failed;
4859 d.in.alias_handle = &alias_handle;
4860 d.out.alias_handle = &alias_handle;
4861 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 goto failed;
4866 return true;
4868 failed:
4869 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
4870 return false;
4873 static bool test_DeleteAlias(struct dcerpc_pipe *p,
4874 struct torture_context *tctx,
4875 struct policy_handle *alias_handle)
4877 struct samr_DeleteDomAlias d;
4878 NTSTATUS status;
4879 bool ret = true;
4881 torture_comment(tctx, "Testing DeleteAlias\n");
4883 d.in.alias_handle = alias_handle;
4884 d.out.alias_handle = alias_handle;
4886 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4887 if (!NT_STATUS_IS_OK(status)) {
4888 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(status));
4889 ret = false;
4892 return ret;
4895 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4896 struct policy_handle *domain_handle,
4897 const char *alias_name,
4898 struct policy_handle *alias_handle,
4899 const struct dom_sid *domain_sid,
4900 bool test_alias)
4902 NTSTATUS status;
4903 struct samr_CreateDomAlias r;
4904 struct lsa_String name;
4905 uint32_t rid;
4906 bool ret = true;
4908 init_lsa_String(&name, alias_name);
4909 r.in.domain_handle = domain_handle;
4910 r.in.alias_name = &name;
4911 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4912 r.out.alias_handle = alias_handle;
4913 r.out.rid = &rid;
4915 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
4917 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4919 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4920 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4921 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
4922 return true;
4923 } else {
4924 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
4925 nt_errstr(status));
4926 return false;
4930 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
4931 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
4932 return false;
4934 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4937 if (!NT_STATUS_IS_OK(status)) {
4938 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(status));
4939 return false;
4942 if (!test_alias) {
4943 return ret;
4946 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
4947 ret = false;
4950 return ret;
4953 static bool test_ChangePassword(struct dcerpc_pipe *p,
4954 struct torture_context *tctx,
4955 const char *acct_name,
4956 struct policy_handle *domain_handle, char **password)
4958 bool ret = true;
4960 if (!*password) {
4961 return false;
4964 if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
4965 ret = false;
4968 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
4969 ret = false;
4972 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
4973 ret = false;
4976 /* test what happens when setting the old password again */
4977 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
4978 ret = false;
4982 char simple_pass[9];
4983 char *v = generate_random_str(tctx, 1);
4985 ZERO_STRUCT(simple_pass);
4986 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4988 /* test what happens when picking a simple password */
4989 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
4990 ret = false;
4994 /* set samr_SetDomainInfo level 1 with min_length 5 */
4996 struct samr_QueryDomainInfo r;
4997 union samr_DomainInfo *info = NULL;
4998 struct samr_SetDomainInfo s;
4999 uint16_t len_old, len;
5000 uint32_t pwd_prop_old;
5001 int64_t min_pwd_age_old;
5002 NTSTATUS status;
5004 len = 5;
5006 r.in.domain_handle = domain_handle;
5007 r.in.level = 1;
5008 r.out.info = &info;
5010 torture_comment(tctx, "testing samr_QueryDomainInfo level 1\n");
5011 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5012 if (!NT_STATUS_IS_OK(status)) {
5013 return false;
5016 s.in.domain_handle = domain_handle;
5017 s.in.level = 1;
5018 s.in.info = info;
5020 /* remember the old min length, so we can reset it */
5021 len_old = s.in.info->info1.min_password_length;
5022 s.in.info->info1.min_password_length = len;
5023 pwd_prop_old = s.in.info->info1.password_properties;
5024 /* turn off password complexity checks for this test */
5025 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5027 min_pwd_age_old = s.in.info->info1.min_password_age;
5028 s.in.info->info1.min_password_age = 0;
5030 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
5031 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5032 if (!NT_STATUS_IS_OK(status)) {
5033 return false;
5036 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5038 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5039 ret = false;
5042 s.in.info->info1.min_password_length = len_old;
5043 s.in.info->info1.password_properties = pwd_prop_old;
5044 s.in.info->info1.min_password_age = min_pwd_age_old;
5046 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
5047 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5048 if (!NT_STATUS_IS_OK(status)) {
5049 return false;
5055 NTSTATUS status;
5056 struct samr_OpenUser r;
5057 struct samr_QueryUserInfo q;
5058 union samr_UserInfo *info;
5059 struct samr_LookupNames n;
5060 struct policy_handle user_handle;
5061 struct samr_Ids rids, types;
5063 n.in.domain_handle = domain_handle;
5064 n.in.num_names = 1;
5065 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5066 n.in.names[0].string = acct_name;
5067 n.out.rids = &rids;
5068 n.out.types = &types;
5070 status = dcerpc_samr_LookupNames(p, tctx, &n);
5071 if (!NT_STATUS_IS_OK(status)) {
5072 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5073 return false;
5076 r.in.domain_handle = domain_handle;
5077 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5078 r.in.rid = n.out.rids->ids[0];
5079 r.out.user_handle = &user_handle;
5081 status = dcerpc_samr_OpenUser(p, tctx, &r);
5082 if (!NT_STATUS_IS_OK(status)) {
5083 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
5084 return false;
5087 q.in.user_handle = &user_handle;
5088 q.in.level = 5;
5089 q.out.info = &info;
5091 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5092 if (!NT_STATUS_IS_OK(status)) {
5093 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(status));
5094 return false;
5097 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5099 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5100 info->info5.last_password_change, true)) {
5101 ret = false;
5105 /* we change passwords twice - this has the effect of verifying
5106 they were changed correctly for the final call */
5107 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5108 ret = false;
5111 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5112 ret = false;
5115 return ret;
5118 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5119 struct policy_handle *domain_handle,
5120 const char *user_name,
5121 struct policy_handle *user_handle_out,
5122 struct dom_sid *domain_sid,
5123 enum torture_samr_choice which_ops,
5124 struct cli_credentials *machine_credentials,
5125 bool test_user)
5128 TALLOC_CTX *user_ctx;
5130 NTSTATUS status;
5131 struct samr_CreateUser r;
5132 struct samr_QueryUserInfo q;
5133 union samr_UserInfo *info;
5134 struct samr_DeleteUser d;
5135 uint32_t rid;
5137 /* This call creates a 'normal' account - check that it really does */
5138 const uint32_t acct_flags = ACB_NORMAL;
5139 struct lsa_String name;
5140 bool ret = true;
5142 struct policy_handle user_handle;
5143 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5144 init_lsa_String(&name, user_name);
5146 r.in.domain_handle = domain_handle;
5147 r.in.account_name = &name;
5148 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5149 r.out.user_handle = &user_handle;
5150 r.out.rid = &rid;
5152 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5154 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
5156 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5157 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5158 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5159 return true;
5160 } else {
5161 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5162 nt_errstr(status));
5163 return false;
5167 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5168 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
5169 talloc_free(user_ctx);
5170 return false;
5172 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
5175 if (!NT_STATUS_IS_OK(status)) {
5176 talloc_free(user_ctx);
5177 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(status));
5178 return false;
5181 if (!test_user) {
5182 if (user_handle_out) {
5183 *user_handle_out = user_handle;
5185 return ret;
5189 q.in.user_handle = &user_handle;
5190 q.in.level = 16;
5191 q.out.info = &info;
5193 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
5194 if (!NT_STATUS_IS_OK(status)) {
5195 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5196 q.in.level, nt_errstr(status));
5197 ret = false;
5198 } else {
5199 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5200 torture_warning(tctx, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5201 info->info16.acct_flags,
5202 acct_flags);
5203 ret = false;
5207 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5208 domain_sid, acct_flags, name.string, which_ops,
5209 machine_credentials)) {
5210 ret = false;
5213 if (user_handle_out) {
5214 *user_handle_out = user_handle;
5215 } else {
5216 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5218 d.in.user_handle = &user_handle;
5219 d.out.user_handle = &user_handle;
5221 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
5222 if (!NT_STATUS_IS_OK(status)) {
5223 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
5224 ret = false;
5230 talloc_free(user_ctx);
5232 return ret;
5236 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5237 struct policy_handle *domain_handle,
5238 struct dom_sid *domain_sid,
5239 enum torture_samr_choice which_ops,
5240 struct cli_credentials *machine_credentials)
5242 NTSTATUS status;
5243 struct samr_CreateUser2 r;
5244 struct samr_QueryUserInfo q;
5245 union samr_UserInfo *info;
5246 struct samr_DeleteUser d;
5247 struct policy_handle user_handle;
5248 uint32_t rid;
5249 struct lsa_String name;
5250 bool ret = true;
5251 int i;
5253 struct {
5254 uint32_t acct_flags;
5255 const char *account_name;
5256 NTSTATUS nt_status;
5257 } account_types[] = {
5258 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5259 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5260 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5261 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5262 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5263 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5264 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5265 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5266 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5267 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5268 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5269 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5270 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5271 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5272 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5275 for (i = 0; account_types[i].account_name; i++) {
5276 TALLOC_CTX *user_ctx;
5277 uint32_t acct_flags = account_types[i].acct_flags;
5278 uint32_t access_granted;
5279 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5280 init_lsa_String(&name, account_types[i].account_name);
5282 r.in.domain_handle = domain_handle;
5283 r.in.account_name = &name;
5284 r.in.acct_flags = acct_flags;
5285 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5286 r.out.user_handle = &user_handle;
5287 r.out.access_granted = &access_granted;
5288 r.out.rid = &rid;
5290 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5292 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
5294 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5295 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5296 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5297 continue;
5298 } else {
5299 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5300 nt_errstr(status));
5301 ret = false;
5302 continue;
5306 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5307 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
5308 talloc_free(user_ctx);
5309 ret = false;
5310 continue;
5312 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
5315 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
5316 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5317 nt_errstr(status), nt_errstr(account_types[i].nt_status));
5318 ret = false;
5321 if (NT_STATUS_IS_OK(status)) {
5322 q.in.user_handle = &user_handle;
5323 q.in.level = 5;
5324 q.out.info = &info;
5326 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
5327 if (!NT_STATUS_IS_OK(status)) {
5328 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5329 q.in.level, nt_errstr(status));
5330 ret = false;
5331 } else {
5332 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5333 if (acct_flags == ACB_NORMAL) {
5334 expected_flags |= ACB_PW_EXPIRED;
5336 if ((info->info5.acct_flags) != expected_flags) {
5337 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5338 info->info5.acct_flags,
5339 expected_flags);
5340 ret = false;
5342 switch (acct_flags) {
5343 case ACB_SVRTRUST:
5344 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5345 torture_warning(tctx, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5346 DOMAIN_RID_DCS, info->info5.primary_gid);
5347 ret = false;
5349 break;
5350 case ACB_WSTRUST:
5351 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5352 torture_warning(tctx, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5353 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5354 ret = false;
5356 break;
5357 case ACB_NORMAL:
5358 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5359 torture_warning(tctx, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5360 DOMAIN_RID_USERS, info->info5.primary_gid);
5361 ret = false;
5363 break;
5367 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5368 domain_sid, acct_flags, name.string, which_ops,
5369 machine_credentials)) {
5370 ret = false;
5373 if (!policy_handle_empty(&user_handle)) {
5374 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5376 d.in.user_handle = &user_handle;
5377 d.out.user_handle = &user_handle;
5379 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
5380 if (!NT_STATUS_IS_OK(status)) {
5381 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
5382 ret = false;
5386 talloc_free(user_ctx);
5389 return ret;
5392 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
5393 struct torture_context *tctx,
5394 struct policy_handle *handle)
5396 NTSTATUS status;
5397 struct samr_QueryAliasInfo r;
5398 union samr_AliasInfo *info;
5399 uint16_t levels[] = {1, 2, 3};
5400 int i;
5401 bool ret = true;
5403 for (i=0;i<ARRAY_SIZE(levels);i++) {
5404 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5406 r.in.alias_handle = handle;
5407 r.in.level = levels[i];
5408 r.out.info = &info;
5410 status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
5411 if (!NT_STATUS_IS_OK(status)) {
5412 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5413 levels[i], nt_errstr(status));
5414 ret = false;
5418 return ret;
5421 static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
5422 struct torture_context *tctx,
5423 struct policy_handle *handle)
5425 NTSTATUS status;
5426 struct samr_QueryGroupInfo r;
5427 union samr_GroupInfo *info;
5428 uint16_t levels[] = {1, 2, 3, 4, 5};
5429 int i;
5430 bool ret = true;
5432 for (i=0;i<ARRAY_SIZE(levels);i++) {
5433 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5435 r.in.group_handle = handle;
5436 r.in.level = levels[i];
5437 r.out.info = &info;
5439 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
5440 if (!NT_STATUS_IS_OK(status)) {
5441 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5442 levels[i], nt_errstr(status));
5443 ret = false;
5447 return ret;
5450 static bool test_QueryGroupMember(struct dcerpc_pipe *p,
5451 struct torture_context *tctx,
5452 struct policy_handle *handle)
5454 NTSTATUS status;
5455 struct samr_QueryGroupMember r;
5456 struct samr_RidTypeArray *rids = NULL;
5457 bool ret = true;
5459 torture_comment(tctx, "Testing QueryGroupMember\n");
5461 r.in.group_handle = handle;
5462 r.out.rids = &rids;
5464 status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
5465 if (!NT_STATUS_IS_OK(status)) {
5466 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(status));
5467 ret = false;
5470 return ret;
5474 static bool test_SetGroupInfo(struct dcerpc_pipe *p,
5475 struct torture_context *tctx,
5476 struct policy_handle *handle)
5478 NTSTATUS status;
5479 struct samr_QueryGroupInfo r;
5480 union samr_GroupInfo *info;
5481 struct samr_SetGroupInfo s;
5482 uint16_t levels[] = {1, 2, 3, 4};
5483 uint16_t set_ok[] = {0, 1, 1, 1};
5484 int i;
5485 bool ret = true;
5487 for (i=0;i<ARRAY_SIZE(levels);i++) {
5488 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5490 r.in.group_handle = handle;
5491 r.in.level = levels[i];
5492 r.out.info = &info;
5494 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5497 levels[i], nt_errstr(status));
5498 ret = false;
5501 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5503 s.in.group_handle = handle;
5504 s.in.level = levels[i];
5505 s.in.info = *r.out.info;
5507 #if 0
5508 /* disabled this, as it changes the name only from the point of view of samr,
5509 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5510 the name is still reserved, so creating the old name fails, but deleting by the old name
5511 also fails */
5512 if (s.in.level == 2) {
5513 init_lsa_String(&s.in.info->string, "NewName");
5515 #endif
5517 if (s.in.level == 4) {
5518 init_lsa_String(&s.in.info->description, "test description");
5521 status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
5522 if (set_ok[i]) {
5523 if (!NT_STATUS_IS_OK(status)) {
5524 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5525 r.in.level, nt_errstr(status));
5526 ret = false;
5527 continue;
5529 } else {
5530 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5531 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5532 r.in.level, nt_errstr(status));
5533 ret = false;
5534 continue;
5539 return ret;
5542 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
5543 struct torture_context *tctx,
5544 struct policy_handle *handle)
5546 NTSTATUS status;
5547 struct samr_QueryUserInfo r;
5548 union samr_UserInfo *info;
5549 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5550 11, 12, 13, 14, 16, 17, 20, 21};
5551 int i;
5552 bool ret = true;
5554 for (i=0;i<ARRAY_SIZE(levels);i++) {
5555 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5557 r.in.user_handle = handle;
5558 r.in.level = levels[i];
5559 r.out.info = &info;
5561 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
5562 if (!NT_STATUS_IS_OK(status)) {
5563 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5564 levels[i], nt_errstr(status));
5565 ret = false;
5569 return ret;
5572 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
5573 struct torture_context *tctx,
5574 struct policy_handle *handle)
5576 NTSTATUS status;
5577 struct samr_QueryUserInfo2 r;
5578 union samr_UserInfo *info;
5579 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5580 11, 12, 13, 14, 16, 17, 20, 21};
5581 int i;
5582 bool ret = true;
5584 for (i=0;i<ARRAY_SIZE(levels);i++) {
5585 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5587 r.in.user_handle = handle;
5588 r.in.level = levels[i];
5589 r.out.info = &info;
5591 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
5592 if (!NT_STATUS_IS_OK(status)) {
5593 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5594 levels[i], nt_errstr(status));
5595 ret = false;
5599 return ret;
5602 static bool test_OpenUser(struct dcerpc_pipe *p,
5603 struct torture_context *tctx,
5604 struct policy_handle *handle, uint32_t rid)
5606 NTSTATUS status;
5607 struct samr_OpenUser r;
5608 struct policy_handle user_handle;
5609 bool ret = true;
5611 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5613 r.in.domain_handle = handle;
5614 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5615 r.in.rid = rid;
5616 r.out.user_handle = &user_handle;
5618 status = dcerpc_samr_OpenUser(p, tctx, &r);
5619 if (!NT_STATUS_IS_OK(status)) {
5620 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
5621 return false;
5624 if (!test_QuerySecurity(p, tctx, &user_handle)) {
5625 ret = false;
5628 if (!test_QueryUserInfo(p, tctx, &user_handle)) {
5629 ret = false;
5632 if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
5633 ret = false;
5636 if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
5637 ret = false;
5640 if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
5641 ret = false;
5644 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5645 ret = false;
5648 return ret;
5651 static bool test_OpenGroup(struct dcerpc_pipe *p,
5652 struct torture_context *tctx,
5653 struct policy_handle *handle, uint32_t rid)
5655 NTSTATUS status;
5656 struct samr_OpenGroup r;
5657 struct policy_handle group_handle;
5658 bool ret = true;
5660 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5662 r.in.domain_handle = handle;
5663 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5664 r.in.rid = rid;
5665 r.out.group_handle = &group_handle;
5667 status = dcerpc_samr_OpenGroup(p, tctx, &r);
5668 if (!NT_STATUS_IS_OK(status)) {
5669 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
5670 return false;
5673 if (!torture_setting_bool(tctx, "samba3", false)) {
5674 if (!test_QuerySecurity(p, tctx, &group_handle)) {
5675 ret = false;
5679 if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
5680 ret = false;
5683 if (!test_QueryGroupMember(p, tctx, &group_handle)) {
5684 ret = false;
5687 if (!test_samr_handle_Close(p, tctx, &group_handle)) {
5688 ret = false;
5691 return ret;
5694 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
5695 struct policy_handle *handle, uint32_t rid)
5697 NTSTATUS status;
5698 struct samr_OpenAlias r;
5699 struct policy_handle alias_handle;
5700 bool ret = true;
5702 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5704 r.in.domain_handle = handle;
5705 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5706 r.in.rid = rid;
5707 r.out.alias_handle = &alias_handle;
5709 status = dcerpc_samr_OpenAlias(p, tctx, &r);
5710 if (!NT_STATUS_IS_OK(status)) {
5711 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
5712 return false;
5715 if (!torture_setting_bool(tctx, "samba3", false)) {
5716 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
5717 ret = false;
5721 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
5722 ret = false;
5725 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
5726 ret = false;
5729 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
5730 ret = false;
5733 return ret;
5736 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
5737 struct policy_handle *handle, uint32_t rid,
5738 uint32_t acct_flag_mask)
5740 NTSTATUS status;
5741 struct samr_OpenUser r;
5742 struct samr_QueryUserInfo q;
5743 union samr_UserInfo *info;
5744 struct policy_handle user_handle;
5745 bool ret = true;
5747 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5749 r.in.domain_handle = handle;
5750 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5751 r.in.rid = rid;
5752 r.out.user_handle = &user_handle;
5754 status = dcerpc_samr_OpenUser(p, tctx, &r);
5755 if (!NT_STATUS_IS_OK(status)) {
5756 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
5757 return false;
5760 q.in.user_handle = &user_handle;
5761 q.in.level = 16;
5762 q.out.info = &info;
5764 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5765 if (!NT_STATUS_IS_OK(status)) {
5766 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
5767 nt_errstr(status));
5768 ret = false;
5769 } else {
5770 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
5771 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
5772 acct_flag_mask, info->info16.acct_flags, rid);
5773 ret = false;
5777 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5778 ret = false;
5781 return ret;
5784 static bool test_EnumDomainUsers_all(struct dcerpc_pipe *p,
5785 struct torture_context *tctx,
5786 struct policy_handle *handle)
5788 NTSTATUS status = STATUS_MORE_ENTRIES;
5789 struct samr_EnumDomainUsers r;
5790 uint32_t mask, resume_handle=0;
5791 int i, mask_idx;
5792 bool ret = true;
5793 struct samr_LookupNames n;
5794 struct samr_LookupRids lr ;
5795 struct lsa_Strings names;
5796 struct samr_Ids rids, types;
5797 struct samr_SamArray *sam = NULL;
5798 uint32_t num_entries = 0;
5800 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
5801 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
5802 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
5803 ACB_PWNOEXP, 0};
5805 torture_comment(tctx, "Testing EnumDomainUsers\n");
5807 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
5808 r.in.domain_handle = handle;
5809 r.in.resume_handle = &resume_handle;
5810 r.in.acct_flags = mask = masks[mask_idx];
5811 r.in.max_size = (uint32_t)-1;
5812 r.out.resume_handle = &resume_handle;
5813 r.out.num_entries = &num_entries;
5814 r.out.sam = &sam;
5816 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
5817 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5818 !NT_STATUS_IS_OK(status)) {
5819 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(status));
5820 return false;
5823 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
5825 if (sam->count == 0) {
5826 continue;
5829 for (i=0;i<sam->count;i++) {
5830 if (mask) {
5831 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
5832 ret = false;
5834 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
5835 ret = false;
5840 torture_comment(tctx, "Testing LookupNames\n");
5841 n.in.domain_handle = handle;
5842 n.in.num_names = sam->count;
5843 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
5844 n.out.rids = &rids;
5845 n.out.types = &types;
5846 for (i=0;i<sam->count;i++) {
5847 n.in.names[i].string = sam->entries[i].name.string;
5849 status = dcerpc_samr_LookupNames(p, tctx, &n);
5850 if (!NT_STATUS_IS_OK(status)) {
5851 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5852 ret = false;
5856 torture_comment(tctx, "Testing LookupRids\n");
5857 lr.in.domain_handle = handle;
5858 lr.in.num_rids = sam->count;
5859 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
5860 lr.out.names = &names;
5861 lr.out.types = &types;
5862 for (i=0;i<sam->count;i++) {
5863 lr.in.rids[i] = sam->entries[i].idx;
5865 status = dcerpc_samr_LookupRids(p, tctx, &lr);
5866 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
5868 return ret;
5872 try blasting the server with a bunch of sync requests
5874 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
5875 struct policy_handle *handle)
5877 NTSTATUS status;
5878 struct samr_EnumDomainUsers r;
5879 uint32_t resume_handle=0;
5880 int i;
5881 #define ASYNC_COUNT 100
5882 struct rpc_request *req[ASYNC_COUNT];
5884 if (!torture_setting_bool(tctx, "dangerous", false)) {
5885 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
5888 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
5890 r.in.domain_handle = handle;
5891 r.in.resume_handle = &resume_handle;
5892 r.in.acct_flags = 0;
5893 r.in.max_size = (uint32_t)-1;
5894 r.out.resume_handle = &resume_handle;
5896 for (i=0;i<ASYNC_COUNT;i++) {
5897 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
5900 for (i=0;i<ASYNC_COUNT;i++) {
5901 status = dcerpc_ndr_request_recv(req[i]);
5902 if (!NT_STATUS_IS_OK(status)) {
5903 torture_warning(tctx, "EnumDomainUsers[%d] failed - %s\n",
5904 i, nt_errstr(status));
5905 return false;
5909 torture_comment(tctx, "%d async requests OK\n", i);
5911 return true;
5914 static bool test_EnumDomainGroups_all(struct dcerpc_pipe *p,
5915 struct torture_context *tctx,
5916 struct policy_handle *handle)
5918 NTSTATUS status;
5919 struct samr_EnumDomainGroups r;
5920 uint32_t resume_handle=0;
5921 struct samr_SamArray *sam = NULL;
5922 uint32_t num_entries = 0;
5923 int i;
5924 bool ret = true;
5926 torture_comment(tctx, "Testing EnumDomainGroups\n");
5928 r.in.domain_handle = handle;
5929 r.in.resume_handle = &resume_handle;
5930 r.in.max_size = (uint32_t)-1;
5931 r.out.resume_handle = &resume_handle;
5932 r.out.num_entries = &num_entries;
5933 r.out.sam = &sam;
5935 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
5936 if (!NT_STATUS_IS_OK(status)) {
5937 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(status));
5938 return false;
5941 if (!sam) {
5942 return false;
5945 for (i=0;i<sam->count;i++) {
5946 if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
5947 ret = false;
5951 return ret;
5954 static bool test_EnumDomainAliases_all(struct dcerpc_pipe *p,
5955 struct torture_context *tctx,
5956 struct policy_handle *handle)
5958 NTSTATUS status;
5959 struct samr_EnumDomainAliases r;
5960 uint32_t resume_handle=0;
5961 struct samr_SamArray *sam = NULL;
5962 uint32_t num_entries = 0;
5963 int i;
5964 bool ret = true;
5966 torture_comment(tctx, "Testing EnumDomainAliases\n");
5968 r.in.domain_handle = handle;
5969 r.in.resume_handle = &resume_handle;
5970 r.in.max_size = (uint32_t)-1;
5971 r.out.sam = &sam;
5972 r.out.num_entries = &num_entries;
5973 r.out.resume_handle = &resume_handle;
5975 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
5976 if (!NT_STATUS_IS_OK(status)) {
5977 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(status));
5978 return false;
5981 if (!sam) {
5982 return false;
5985 for (i=0;i<sam->count;i++) {
5986 if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
5987 ret = false;
5991 return ret;
5994 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
5995 struct torture_context *tctx,
5996 struct policy_handle *handle)
5998 NTSTATUS status;
5999 struct samr_GetDisplayEnumerationIndex r;
6000 bool ret = true;
6001 uint16_t levels[] = {1, 2, 3, 4, 5};
6002 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6003 struct lsa_String name;
6004 uint32_t idx = 0;
6005 int i;
6007 for (i=0;i<ARRAY_SIZE(levels);i++) {
6008 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6010 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6012 r.in.domain_handle = handle;
6013 r.in.level = levels[i];
6014 r.in.name = &name;
6015 r.out.idx = &idx;
6017 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
6019 if (ok_lvl[i] &&
6020 !NT_STATUS_IS_OK(status) &&
6021 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6022 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6023 levels[i], nt_errstr(status));
6024 ret = false;
6027 init_lsa_String(&name, "zzzzzzzz");
6029 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
6031 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6032 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6033 levels[i], nt_errstr(status));
6034 ret = false;
6038 return ret;
6041 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
6042 struct torture_context *tctx,
6043 struct policy_handle *handle)
6045 NTSTATUS status;
6046 struct samr_GetDisplayEnumerationIndex2 r;
6047 bool ret = true;
6048 uint16_t levels[] = {1, 2, 3, 4, 5};
6049 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6050 struct lsa_String name;
6051 uint32_t idx = 0;
6052 int i;
6054 for (i=0;i<ARRAY_SIZE(levels);i++) {
6055 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6057 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6059 r.in.domain_handle = handle;
6060 r.in.level = levels[i];
6061 r.in.name = &name;
6062 r.out.idx = &idx;
6064 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
6065 if (ok_lvl[i] &&
6066 !NT_STATUS_IS_OK(status) &&
6067 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6068 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6069 levels[i], nt_errstr(status));
6070 ret = false;
6073 init_lsa_String(&name, "zzzzzzzz");
6075 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
6076 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6077 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6078 levels[i], nt_errstr(status));
6079 ret = false;
6083 return ret;
6086 #define STRING_EQUAL_QUERY(s1, s2, user) \
6087 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6088 /* odd, but valid */ \
6089 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6090 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6091 #s1, user.string, s1.string, s2.string, __location__); \
6092 ret = false; \
6094 #define INT_EQUAL_QUERY(s1, s2, user) \
6095 if (s1 != s2) { \
6096 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6097 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6098 ret = false; \
6101 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
6102 struct torture_context *tctx,
6103 struct samr_QueryDisplayInfo *querydisplayinfo,
6104 bool *seen_testuser)
6106 struct samr_OpenUser r;
6107 struct samr_QueryUserInfo q;
6108 union samr_UserInfo *info;
6109 struct policy_handle user_handle;
6110 int i, ret = true;
6111 NTSTATUS status;
6112 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6113 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6114 for (i = 0; ; i++) {
6115 switch (querydisplayinfo->in.level) {
6116 case 1:
6117 if (i >= querydisplayinfo->out.info->info1.count) {
6118 return ret;
6120 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6121 break;
6122 case 2:
6123 if (i >= querydisplayinfo->out.info->info2.count) {
6124 return ret;
6126 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6127 break;
6128 case 3:
6129 /* Groups */
6130 case 4:
6131 case 5:
6132 /* Not interested in validating just the account name */
6133 return true;
6136 r.out.user_handle = &user_handle;
6138 switch (querydisplayinfo->in.level) {
6139 case 1:
6140 case 2:
6141 status = dcerpc_samr_OpenUser(p, tctx, &r);
6142 if (!NT_STATUS_IS_OK(status)) {
6143 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
6144 return false;
6148 q.in.user_handle = &user_handle;
6149 q.in.level = 21;
6150 q.out.info = &info;
6151 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
6152 if (!NT_STATUS_IS_OK(status)) {
6153 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
6154 return false;
6157 switch (querydisplayinfo->in.level) {
6158 case 1:
6159 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6160 *seen_testuser = true;
6162 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6163 info->info21.full_name, info->info21.account_name);
6164 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6165 info->info21.account_name, info->info21.account_name);
6166 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6167 info->info21.description, info->info21.account_name);
6168 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6169 info->info21.rid, info->info21.account_name);
6170 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6171 info->info21.acct_flags, info->info21.account_name);
6173 break;
6174 case 2:
6175 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6176 info->info21.account_name, info->info21.account_name);
6177 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6178 info->info21.description, info->info21.account_name);
6179 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6180 info->info21.rid, info->info21.account_name);
6181 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6182 info->info21.acct_flags, info->info21.account_name);
6184 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6185 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6186 info->info21.account_name.string);
6189 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6190 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6191 info->info21.account_name.string,
6192 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6193 info->info21.acct_flags);
6194 return false;
6197 break;
6200 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
6201 return false;
6204 return ret;
6207 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
6208 struct torture_context *tctx,
6209 struct policy_handle *handle)
6211 NTSTATUS status;
6212 struct samr_QueryDisplayInfo r;
6213 struct samr_QueryDomainInfo dom_info;
6214 union samr_DomainInfo *info = NULL;
6215 bool ret = true;
6216 uint16_t levels[] = {1, 2, 3, 4, 5};
6217 int i;
6218 bool seen_testuser = false;
6219 uint32_t total_size;
6220 uint32_t returned_size;
6221 union samr_DispInfo disp_info;
6224 for (i=0;i<ARRAY_SIZE(levels);i++) {
6225 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6227 r.in.start_idx = 0;
6228 status = STATUS_MORE_ENTRIES;
6229 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6230 r.in.domain_handle = handle;
6231 r.in.level = levels[i];
6232 r.in.max_entries = 2;
6233 r.in.buf_size = (uint32_t)-1;
6234 r.out.total_size = &total_size;
6235 r.out.returned_size = &returned_size;
6236 r.out.info = &disp_info;
6238 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6239 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
6240 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6241 levels[i], nt_errstr(status));
6242 ret = false;
6244 switch (r.in.level) {
6245 case 1:
6246 if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
6247 ret = false;
6249 r.in.start_idx += r.out.info->info1.count;
6250 break;
6251 case 2:
6252 if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
6253 ret = false;
6255 r.in.start_idx += r.out.info->info2.count;
6256 break;
6257 case 3:
6258 r.in.start_idx += r.out.info->info3.count;
6259 break;
6260 case 4:
6261 r.in.start_idx += r.out.info->info4.count;
6262 break;
6263 case 5:
6264 r.in.start_idx += r.out.info->info5.count;
6265 break;
6268 dom_info.in.domain_handle = handle;
6269 dom_info.in.level = 2;
6270 dom_info.out.info = &info;
6272 /* Check number of users returned is correct */
6273 status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
6274 if (!NT_STATUS_IS_OK(status)) {
6275 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6276 r.in.level, nt_errstr(status));
6277 ret = false;
6278 break;
6280 switch (r.in.level) {
6281 case 1:
6282 case 4:
6283 if (info->general.num_users < r.in.start_idx) {
6284 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6285 r.in.start_idx, info->general.num_groups,
6286 info->general.domain_name.string);
6287 ret = false;
6289 if (!seen_testuser) {
6290 struct policy_handle user_handle;
6291 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6292 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6293 info->general.domain_name.string);
6294 ret = false;
6295 test_samr_handle_Close(p, tctx, &user_handle);
6298 break;
6299 case 3:
6300 case 5:
6301 if (info->general.num_groups != r.in.start_idx) {
6302 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6303 r.in.start_idx, info->general.num_groups,
6304 info->general.domain_name.string);
6305 ret = false;
6308 break;
6313 return ret;
6316 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
6317 struct torture_context *tctx,
6318 struct policy_handle *handle)
6320 NTSTATUS status;
6321 struct samr_QueryDisplayInfo2 r;
6322 bool ret = true;
6323 uint16_t levels[] = {1, 2, 3, 4, 5};
6324 int i;
6325 uint32_t total_size;
6326 uint32_t returned_size;
6327 union samr_DispInfo info;
6329 for (i=0;i<ARRAY_SIZE(levels);i++) {
6330 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6332 r.in.domain_handle = handle;
6333 r.in.level = levels[i];
6334 r.in.start_idx = 0;
6335 r.in.max_entries = 1000;
6336 r.in.buf_size = (uint32_t)-1;
6337 r.out.total_size = &total_size;
6338 r.out.returned_size = &returned_size;
6339 r.out.info = &info;
6341 status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
6342 if (!NT_STATUS_IS_OK(status)) {
6343 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6344 levels[i], nt_errstr(status));
6345 ret = false;
6349 return ret;
6352 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
6353 struct policy_handle *handle)
6355 NTSTATUS status;
6356 struct samr_QueryDisplayInfo3 r;
6357 bool ret = true;
6358 uint16_t levels[] = {1, 2, 3, 4, 5};
6359 int i;
6360 uint32_t total_size;
6361 uint32_t returned_size;
6362 union samr_DispInfo info;
6364 for (i=0;i<ARRAY_SIZE(levels);i++) {
6365 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6367 r.in.domain_handle = handle;
6368 r.in.level = levels[i];
6369 r.in.start_idx = 0;
6370 r.in.max_entries = 1000;
6371 r.in.buf_size = (uint32_t)-1;
6372 r.out.total_size = &total_size;
6373 r.out.returned_size = &returned_size;
6374 r.out.info = &info;
6376 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
6377 if (!NT_STATUS_IS_OK(status)) {
6378 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6379 levels[i], nt_errstr(status));
6380 ret = false;
6384 return ret;
6388 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
6389 struct torture_context *tctx,
6390 struct policy_handle *handle)
6392 NTSTATUS status;
6393 struct samr_QueryDisplayInfo r;
6394 bool ret = true;
6395 uint32_t total_size;
6396 uint32_t returned_size;
6397 union samr_DispInfo info;
6399 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6401 r.in.domain_handle = handle;
6402 r.in.level = 1;
6403 r.in.start_idx = 0;
6404 r.in.max_entries = 1;
6405 r.in.buf_size = (uint32_t)-1;
6406 r.out.total_size = &total_size;
6407 r.out.returned_size = &returned_size;
6408 r.out.info = &info;
6410 do {
6411 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6412 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
6413 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6414 torture_warning(tctx, "expected idx %d but got %d\n",
6415 r.in.start_idx + 1,
6416 r.out.info->info1.entries[0].idx);
6417 break;
6420 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
6421 !NT_STATUS_IS_OK(status)) {
6422 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6423 r.in.level, nt_errstr(status));
6424 ret = false;
6425 break;
6427 r.in.start_idx++;
6428 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
6429 NT_STATUS_IS_OK(status)) &&
6430 *r.out.returned_size != 0);
6432 return ret;
6435 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
6436 struct policy_handle *handle)
6438 NTSTATUS status;
6439 struct samr_QueryDomainInfo r;
6440 union samr_DomainInfo *info = NULL;
6441 struct samr_SetDomainInfo s;
6442 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6443 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6444 int i;
6445 bool ret = true;
6446 const char *domain_comment = talloc_asprintf(tctx,
6447 "Tortured by Samba4 RPC-SAMR: %s",
6448 timestring(tctx, time(NULL)));
6450 s.in.domain_handle = handle;
6451 s.in.level = 4;
6452 s.in.info = talloc(tctx, union samr_DomainInfo);
6454 s.in.info->oem.oem_information.string = domain_comment;
6455 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
6456 if (!NT_STATUS_IS_OK(status)) {
6457 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6458 s.in.level, nt_errstr(status));
6459 return false;
6462 for (i=0;i<ARRAY_SIZE(levels);i++) {
6463 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6465 r.in.domain_handle = handle;
6466 r.in.level = levels[i];
6467 r.out.info = &info;
6469 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
6470 if (!NT_STATUS_IS_OK(status)) {
6471 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6472 r.in.level, nt_errstr(status));
6473 ret = false;
6474 continue;
6477 switch (levels[i]) {
6478 case 2:
6479 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6480 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6481 levels[i], info->general.oem_information.string, domain_comment);
6482 if (!torture_setting_bool(tctx, "samba3", false)) {
6483 ret = false;
6486 if (!info->general.primary.string) {
6487 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6488 levels[i]);
6489 ret = false;
6490 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6491 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6492 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6493 levels[i], info->general.primary.string, dcerpc_server_name(p));
6496 break;
6497 case 4:
6498 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6499 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6500 levels[i], info->oem.oem_information.string, domain_comment);
6501 if (!torture_setting_bool(tctx, "samba3", false)) {
6502 ret = false;
6505 break;
6506 case 6:
6507 if (!info->info6.primary.string) {
6508 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6509 levels[i]);
6510 ret = false;
6512 break;
6513 case 11:
6514 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6515 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6516 levels[i], info->general2.general.oem_information.string, domain_comment);
6517 if (!torture_setting_bool(tctx, "samba3", false)) {
6518 ret = false;
6521 break;
6524 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6526 s.in.domain_handle = handle;
6527 s.in.level = levels[i];
6528 s.in.info = info;
6530 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
6531 if (set_ok[i]) {
6532 if (!NT_STATUS_IS_OK(status)) {
6533 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6534 r.in.level, nt_errstr(status));
6535 ret = false;
6536 continue;
6538 } else {
6539 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
6540 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6541 r.in.level, nt_errstr(status));
6542 ret = false;
6543 continue;
6547 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
6548 if (!NT_STATUS_IS_OK(status)) {
6549 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6550 r.in.level, nt_errstr(status));
6551 ret = false;
6552 continue;
6556 return ret;
6560 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
6561 struct policy_handle *handle)
6563 NTSTATUS status;
6564 struct samr_QueryDomainInfo2 r;
6565 union samr_DomainInfo *info = NULL;
6566 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6567 int i;
6568 bool ret = true;
6570 for (i=0;i<ARRAY_SIZE(levels);i++) {
6571 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6573 r.in.domain_handle = handle;
6574 r.in.level = levels[i];
6575 r.out.info = &info;
6577 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
6578 if (!NT_STATUS_IS_OK(status)) {
6579 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6580 r.in.level, nt_errstr(status));
6581 ret = false;
6582 continue;
6586 return true;
6589 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6590 set of group names. */
6591 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
6592 struct policy_handle *handle)
6594 struct samr_EnumDomainGroups q1;
6595 struct samr_QueryDisplayInfo q2;
6596 NTSTATUS status;
6597 uint32_t resume_handle=0;
6598 struct samr_SamArray *sam = NULL;
6599 uint32_t num_entries = 0;
6600 int i;
6601 bool ret = true;
6602 uint32_t total_size;
6603 uint32_t returned_size;
6604 union samr_DispInfo info;
6606 int num_names = 0;
6607 const char **names = NULL;
6609 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6611 q1.in.domain_handle = handle;
6612 q1.in.resume_handle = &resume_handle;
6613 q1.in.max_size = 5;
6614 q1.out.resume_handle = &resume_handle;
6615 q1.out.num_entries = &num_entries;
6616 q1.out.sam = &sam;
6618 status = STATUS_MORE_ENTRIES;
6619 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6620 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
6622 if (!NT_STATUS_IS_OK(status) &&
6623 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6624 break;
6626 for (i=0; i<*q1.out.num_entries; i++) {
6627 add_string_to_array(tctx,
6628 sam->entries[i].name.string,
6629 &names, &num_names);
6633 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6635 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6637 q2.in.domain_handle = handle;
6638 q2.in.level = 5;
6639 q2.in.start_idx = 0;
6640 q2.in.max_entries = 5;
6641 q2.in.buf_size = (uint32_t)-1;
6642 q2.out.total_size = &total_size;
6643 q2.out.returned_size = &returned_size;
6644 q2.out.info = &info;
6646 status = STATUS_MORE_ENTRIES;
6647 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6648 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
6650 if (!NT_STATUS_IS_OK(status) &&
6651 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6652 break;
6654 for (i=0; i<q2.out.info->info5.count; i++) {
6655 int j;
6656 const char *name = q2.out.info->info5.entries[i].account_name.string;
6657 bool found = false;
6658 for (j=0; j<num_names; j++) {
6659 if (names[j] == NULL)
6660 continue;
6661 if (strequal(names[j], name)) {
6662 names[j] = NULL;
6663 found = true;
6664 break;
6668 if (!found) {
6669 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
6670 name);
6671 ret = false;
6674 q2.in.start_idx += q2.out.info->info5.count;
6677 if (!NT_STATUS_IS_OK(status)) {
6678 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
6679 nt_errstr(status));
6680 ret = false;
6683 for (i=0; i<num_names; i++) {
6684 if (names[i] != NULL) {
6685 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
6686 names[i]);
6687 ret = false;
6691 return ret;
6694 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
6695 struct policy_handle *group_handle)
6697 struct samr_DeleteDomainGroup d;
6698 NTSTATUS status;
6700 torture_comment(tctx, "Testing DeleteDomainGroup\n");
6702 d.in.group_handle = group_handle;
6703 d.out.group_handle = group_handle;
6705 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
6706 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
6708 return true;
6711 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6712 struct policy_handle *domain_handle)
6714 struct samr_TestPrivateFunctionsDomain r;
6715 NTSTATUS status;
6716 bool ret = true;
6718 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
6720 r.in.domain_handle = domain_handle;
6722 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
6723 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
6725 return ret;
6728 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
6729 struct dom_sid *domain_sid,
6730 struct policy_handle *domain_handle)
6732 struct samr_RidToSid r;
6733 NTSTATUS status;
6734 bool ret = true;
6735 struct dom_sid *calc_sid, *out_sid;
6736 int rids[] = { 0, 42, 512, 10200 };
6737 int i;
6739 for (i=0;i<ARRAY_SIZE(rids);i++) {
6740 torture_comment(tctx, "Testing RidToSid\n");
6742 calc_sid = dom_sid_dup(tctx, domain_sid);
6743 r.in.domain_handle = domain_handle;
6744 r.in.rid = rids[i];
6745 r.out.sid = &out_sid;
6747 status = dcerpc_samr_RidToSid(p, tctx, &r);
6748 if (!NT_STATUS_IS_OK(status)) {
6749 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
6750 ret = false;
6751 } else {
6752 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
6754 if (!dom_sid_equal(calc_sid, out_sid)) {
6755 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
6756 dom_sid_string(tctx, out_sid),
6757 dom_sid_string(tctx, calc_sid));
6758 ret = false;
6763 return ret;
6766 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
6767 struct policy_handle *domain_handle)
6769 struct samr_GetBootKeyInformation r;
6770 NTSTATUS status;
6771 bool ret = true;
6772 uint32_t unknown = 0;
6774 torture_comment(tctx, "Testing GetBootKeyInformation\n");
6776 r.in.domain_handle = domain_handle;
6777 r.out.unknown = &unknown;
6779 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
6780 if (!NT_STATUS_IS_OK(status)) {
6781 /* w2k3 seems to fail this sometimes and pass it sometimes */
6782 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
6785 return ret;
6788 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
6789 struct policy_handle *domain_handle,
6790 struct policy_handle *group_handle)
6792 NTSTATUS status;
6793 struct samr_AddGroupMember r;
6794 struct samr_DeleteGroupMember d;
6795 struct samr_QueryGroupMember q;
6796 struct samr_RidTypeArray *rids = NULL;
6797 struct samr_SetMemberAttributesOfGroup s;
6798 uint32_t rid;
6799 bool found_member = false;
6800 int i;
6802 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
6803 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
6805 r.in.group_handle = group_handle;
6806 r.in.rid = rid;
6807 r.in.flags = 0; /* ??? */
6809 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
6811 d.in.group_handle = group_handle;
6812 d.in.rid = rid;
6814 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
6815 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
6817 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6818 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6820 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6821 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
6823 if (torture_setting_bool(tctx, "samba4", false) ||
6824 torture_setting_bool(tctx, "samba3", false)) {
6825 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
6826 } else {
6827 /* this one is quite strange. I am using random inputs in the
6828 hope of triggering an error that might give us a clue */
6830 s.in.group_handle = group_handle;
6831 s.in.unknown1 = random();
6832 s.in.unknown2 = random();
6834 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
6835 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
6838 q.in.group_handle = group_handle;
6839 q.out.rids = &rids;
6841 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
6842 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6843 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6845 for (i=0; i < rids->count; i++) {
6846 if (rids->rids[i] == rid) {
6847 found_member = true;
6851 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
6853 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
6854 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
6856 rids = NULL;
6857 found_member = false;
6859 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
6860 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6861 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6863 for (i=0; i < rids->count; i++) {
6864 if (rids->rids[i] == rid) {
6865 found_member = true;
6869 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
6871 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6872 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6874 return true;
6878 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
6879 struct torture_context *tctx,
6880 struct policy_handle *domain_handle,
6881 const char *group_name,
6882 struct policy_handle *group_handle,
6883 struct dom_sid *domain_sid,
6884 bool test_group)
6886 NTSTATUS status;
6887 struct samr_CreateDomainGroup r;
6888 uint32_t rid;
6889 struct lsa_String name;
6890 bool ret = true;
6892 init_lsa_String(&name, group_name);
6894 r.in.domain_handle = domain_handle;
6895 r.in.name = &name;
6896 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6897 r.out.group_handle = group_handle;
6898 r.out.rid = &rid;
6900 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
6902 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6904 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6905 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6906 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
6907 return true;
6908 } else {
6909 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
6910 nt_errstr(status));
6911 return false;
6915 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
6916 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
6917 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
6918 nt_errstr(status));
6919 return false;
6921 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6923 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
6924 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
6926 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
6927 nt_errstr(status));
6928 return false;
6930 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6932 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
6934 if (!test_group) {
6935 return ret;
6938 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
6939 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(status));
6940 ret = false;
6943 if (!test_SetGroupInfo(p, tctx, group_handle)) {
6944 ret = false;
6947 return ret;
6952 its not totally clear what this does. It seems to accept any sid you like.
6954 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
6955 struct torture_context *tctx,
6956 struct policy_handle *domain_handle)
6958 NTSTATUS status;
6959 struct samr_RemoveMemberFromForeignDomain r;
6961 r.in.domain_handle = domain_handle;
6962 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
6964 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
6965 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
6967 return true;
6970 static bool test_EnumDomainUsers(struct dcerpc_pipe *p,
6971 struct torture_context *tctx,
6972 struct policy_handle *domain_handle,
6973 uint32_t *total_num_entries_p)
6975 NTSTATUS status;
6976 struct samr_EnumDomainUsers r;
6977 uint32_t resume_handle = 0;
6978 uint32_t num_entries = 0;
6979 uint32_t total_num_entries = 0;
6980 struct samr_SamArray *sam;
6982 r.in.domain_handle = domain_handle;
6983 r.in.acct_flags = 0;
6984 r.in.max_size = (uint32_t)-1;
6985 r.in.resume_handle = &resume_handle;
6987 r.out.sam = &sam;
6988 r.out.num_entries = &num_entries;
6989 r.out.resume_handle = &resume_handle;
6991 torture_comment(tctx, "Testing EnumDomainUsers\n");
6993 do {
6994 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
6995 if (NT_STATUS_IS_ERR(status)) {
6996 torture_assert_ntstatus_ok(tctx, status,
6997 "failed to enumerate users");
7000 total_num_entries += num_entries;
7001 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7003 if (total_num_entries_p) {
7004 *total_num_entries_p = total_num_entries;
7007 return true;
7010 static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
7011 struct torture_context *tctx,
7012 struct policy_handle *domain_handle,
7013 uint32_t *total_num_entries_p)
7015 NTSTATUS status;
7016 struct samr_EnumDomainGroups r;
7017 uint32_t resume_handle = 0;
7018 uint32_t num_entries = 0;
7019 uint32_t total_num_entries = 0;
7020 struct samr_SamArray *sam;
7022 r.in.domain_handle = domain_handle;
7023 r.in.max_size = (uint32_t)-1;
7024 r.in.resume_handle = &resume_handle;
7026 r.out.sam = &sam;
7027 r.out.num_entries = &num_entries;
7028 r.out.resume_handle = &resume_handle;
7030 torture_comment(tctx, "Testing EnumDomainGroups\n");
7032 do {
7033 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
7034 if (NT_STATUS_IS_ERR(status)) {
7035 torture_assert_ntstatus_ok(tctx, status,
7036 "failed to enumerate groups");
7039 total_num_entries += num_entries;
7040 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7042 if (total_num_entries_p) {
7043 *total_num_entries_p = total_num_entries;
7046 return true;
7049 static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
7050 struct torture_context *tctx,
7051 struct policy_handle *domain_handle,
7052 uint32_t *total_num_entries_p)
7054 NTSTATUS status;
7055 struct samr_EnumDomainAliases r;
7056 uint32_t resume_handle = 0;
7057 uint32_t num_entries = 0;
7058 uint32_t total_num_entries = 0;
7059 struct samr_SamArray *sam;
7061 r.in.domain_handle = domain_handle;
7062 r.in.max_size = (uint32_t)-1;
7063 r.in.resume_handle = &resume_handle;
7065 r.out.sam = &sam;
7066 r.out.num_entries = &num_entries;
7067 r.out.resume_handle = &resume_handle;
7069 torture_comment(tctx, "Testing EnumDomainAliases\n");
7071 do {
7072 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
7073 if (NT_STATUS_IS_ERR(status)) {
7074 torture_assert_ntstatus_ok(tctx, status,
7075 "failed to enumerate aliases");
7078 total_num_entries += num_entries;
7079 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7081 if (total_num_entries_p) {
7082 *total_num_entries_p = total_num_entries;
7085 return true;
7088 static bool test_QueryDisplayInfo_level(struct dcerpc_pipe *p,
7089 struct torture_context *tctx,
7090 struct policy_handle *handle,
7091 uint16_t level,
7092 uint32_t *total_num_entries_p)
7094 NTSTATUS status;
7095 struct samr_QueryDisplayInfo r;
7096 uint32_t total_num_entries = 0;
7098 r.in.domain_handle = handle;
7099 r.in.level = level;
7100 r.in.start_idx = 0;
7101 r.in.max_entries = (uint32_t)-1;
7102 r.in.buf_size = (uint32_t)-1;
7104 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7106 do {
7107 uint32_t total_size;
7108 uint32_t returned_size;
7109 union samr_DispInfo info;
7111 r.out.total_size = &total_size;
7112 r.out.returned_size = &returned_size;
7113 r.out.info = &info;
7115 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
7116 if (NT_STATUS_IS_ERR(status)) {
7117 torture_assert_ntstatus_ok(tctx, status,
7118 "failed to query displayinfo");
7121 if (*r.out.returned_size == 0) {
7122 break;
7125 switch (r.in.level) {
7126 case 1:
7127 total_num_entries += info.info1.count;
7128 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7129 break;
7130 case 2:
7131 total_num_entries += info.info2.count;
7132 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7133 break;
7134 case 3:
7135 total_num_entries += info.info3.count;
7136 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7137 break;
7138 case 4:
7139 total_num_entries += info.info4.count;
7140 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7141 break;
7142 case 5:
7143 total_num_entries += info.info5.count;
7144 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7145 break;
7146 default:
7147 return false;
7150 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7152 if (total_num_entries_p) {
7153 *total_num_entries_p = total_num_entries;
7156 return true;
7159 static bool test_ManyObjects(struct dcerpc_pipe *p,
7160 struct torture_context *tctx,
7161 struct policy_handle *domain_handle,
7162 struct dom_sid *domain_sid,
7163 struct torture_samr_context *ctx)
7165 uint32_t num_total = ctx->num_objects_large_dc;
7166 uint32_t num_enum = 0;
7167 uint32_t num_disp = 0;
7168 uint32_t num_created = 0;
7169 uint32_t num_anounced = 0;
7170 bool ret = true;
7171 NTSTATUS status;
7172 uint32_t i;
7174 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7176 /* query */
7179 struct samr_QueryDomainInfo2 r;
7180 union samr_DomainInfo *info;
7181 r.in.domain_handle = domain_handle;
7182 r.in.level = 2;
7183 r.out.info = &info;
7185 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
7186 torture_assert_ntstatus_ok(tctx, status,
7187 "failed to query domain info");
7189 switch (ctx->choice) {
7190 case TORTURE_SAMR_MANY_ACCOUNTS:
7191 num_anounced = info->general.num_users;
7192 break;
7193 case TORTURE_SAMR_MANY_GROUPS:
7194 num_anounced = info->general.num_groups;
7195 break;
7196 case TORTURE_SAMR_MANY_ALIASES:
7197 num_anounced = info->general.num_aliases;
7198 break;
7199 default:
7200 return false;
7204 /* create */
7206 for (i=0; i < num_total; i++) {
7208 const char *name = NULL;
7210 switch (ctx->choice) {
7211 case TORTURE_SAMR_MANY_ACCOUNTS:
7212 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7213 ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
7214 break;
7215 case TORTURE_SAMR_MANY_GROUPS:
7216 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7217 ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
7218 break;
7219 case TORTURE_SAMR_MANY_ALIASES:
7220 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7221 ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
7222 break;
7223 default:
7224 return false;
7226 if (!policy_handle_empty(&handles[i])) {
7227 num_created++;
7231 /* enum */
7233 switch (ctx->choice) {
7234 case TORTURE_SAMR_MANY_ACCOUNTS:
7235 ret &= test_EnumDomainUsers(p, tctx, domain_handle, &num_enum);
7236 break;
7237 case TORTURE_SAMR_MANY_GROUPS:
7238 ret &= test_EnumDomainGroups(p, tctx, domain_handle, &num_enum);
7239 break;
7240 case TORTURE_SAMR_MANY_ALIASES:
7241 ret &= test_EnumDomainAliases(p, tctx, domain_handle, &num_enum);
7242 break;
7243 default:
7244 return false;
7247 /* dispinfo */
7249 switch (ctx->choice) {
7250 case TORTURE_SAMR_MANY_ACCOUNTS:
7251 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 1, &num_disp);
7252 break;
7253 case TORTURE_SAMR_MANY_GROUPS:
7254 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 3, &num_disp);
7255 break;
7256 case TORTURE_SAMR_MANY_ALIASES:
7257 /* no aliases in dispinfo */
7258 break;
7259 default:
7260 return false;
7263 /* close or delete */
7265 for (i=0; i < num_total; i++) {
7267 if (policy_handle_empty(&handles[i])) {
7268 continue;
7271 if (torture_setting_bool(tctx, "samba3", false)) {
7272 ret &= test_samr_handle_Close(p, tctx, &handles[i]);
7273 } else {
7274 switch (ctx->choice) {
7275 case TORTURE_SAMR_MANY_ACCOUNTS:
7276 ret &= test_DeleteUser(p, tctx, &handles[i]);
7277 break;
7278 case TORTURE_SAMR_MANY_GROUPS:
7279 ret &= test_DeleteDomainGroup(p, tctx, &handles[i]);
7280 break;
7281 case TORTURE_SAMR_MANY_ALIASES:
7282 ret &= test_DeleteAlias(p, tctx, &handles[i]);
7283 break;
7284 default:
7285 return false;
7290 talloc_free(handles);
7292 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7293 torture_comment(tctx,
7294 "unexpected number of results (%u) returned in enum call, expected %u\n",
7295 num_enum, num_anounced + num_created);
7297 torture_comment(tctx,
7298 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7299 num_disp, num_anounced + num_created);
7301 return ret;
7304 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
7305 struct policy_handle *handle);
7307 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7308 struct torture_samr_context *ctx, struct dom_sid *sid)
7310 NTSTATUS status;
7311 struct samr_OpenDomain r;
7312 struct policy_handle domain_handle;
7313 struct policy_handle alias_handle;
7314 struct policy_handle user_handle;
7315 struct policy_handle group_handle;
7316 bool ret = true;
7318 ZERO_STRUCT(alias_handle);
7319 ZERO_STRUCT(user_handle);
7320 ZERO_STRUCT(group_handle);
7321 ZERO_STRUCT(domain_handle);
7323 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7325 r.in.connect_handle = &ctx->handle;
7326 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7327 r.in.sid = sid;
7328 r.out.domain_handle = &domain_handle;
7330 status = dcerpc_samr_OpenDomain(p, tctx, &r);
7331 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
7333 /* run the domain tests with the main handle closed - this tests
7334 the servers reference counting */
7335 torture_assert(tctx, test_samr_handle_Close(p, tctx, &ctx->handle), "Failed to close SAMR handle");
7337 switch (ctx->choice) {
7338 case TORTURE_SAMR_PASSWORDS:
7339 case TORTURE_SAMR_USER_PRIVILEGES:
7340 if (!torture_setting_bool(tctx, "samba3", false)) {
7341 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7343 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7344 if (!ret) {
7345 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7347 break;
7348 case TORTURE_SAMR_USER_ATTRIBUTES:
7349 if (!torture_setting_bool(tctx, "samba3", false)) {
7350 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7352 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7353 /* This test needs 'complex' users to validate */
7354 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
7355 if (!ret) {
7356 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7358 break;
7359 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7360 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7361 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7362 if (!torture_setting_bool(tctx, "samba3", false)) {
7363 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7365 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7366 if (!ret) {
7367 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7369 break;
7370 case TORTURE_SAMR_MANY_ACCOUNTS:
7371 case TORTURE_SAMR_MANY_GROUPS:
7372 case TORTURE_SAMR_MANY_ALIASES:
7373 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7374 if (!ret) {
7375 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7377 break;
7378 case TORTURE_SAMR_OTHER:
7379 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7380 if (!ret) {
7381 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7383 if (!torture_setting_bool(tctx, "samba3", false)) {
7384 ret &= test_QuerySecurity(p, tctx, &domain_handle);
7386 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
7387 ret &= test_CreateAlias(p, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7388 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7389 ret &= test_GetAliasMembership(p, tctx, &domain_handle);
7390 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7391 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
7392 ret &= test_EnumDomainUsers_all(p, tctx, &domain_handle);
7393 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7394 ret &= test_EnumDomainGroups_all(p, tctx, &domain_handle);
7395 ret &= test_EnumDomainAliases_all(p, tctx, &domain_handle);
7396 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
7397 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
7398 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
7400 if (torture_setting_bool(tctx, "samba4", false)) {
7401 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7402 } else {
7403 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
7404 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
7406 ret &= test_GroupList(p, tctx, &domain_handle);
7407 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
7408 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
7409 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
7410 if (!ret) {
7411 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7413 break;
7416 if (!policy_handle_empty(&user_handle) &&
7417 !test_DeleteUser(p, tctx, &user_handle)) {
7418 ret = false;
7421 if (!policy_handle_empty(&alias_handle) &&
7422 !test_DeleteAlias(p, tctx, &alias_handle)) {
7423 ret = false;
7426 if (!policy_handle_empty(&group_handle) &&
7427 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
7428 ret = false;
7431 torture_assert(tctx, test_samr_handle_Close(p, tctx, &domain_handle), "Failed to close SAMR domain handle");
7433 torture_assert(tctx, test_Connect(p, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7434 /* reconnect the main handle */
7436 if (!ret) {
7437 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7440 return ret;
7443 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7444 struct torture_samr_context *ctx, const char *domain)
7446 NTSTATUS status;
7447 struct samr_LookupDomain r;
7448 struct dom_sid2 *sid = NULL;
7449 struct lsa_String n1;
7450 struct lsa_String n2;
7451 bool ret = true;
7453 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7455 /* check for correct error codes */
7456 r.in.connect_handle = &ctx->handle;
7457 r.in.domain_name = &n2;
7458 r.out.sid = &sid;
7459 n2.string = NULL;
7461 status = dcerpc_samr_LookupDomain(p, tctx, &r);
7462 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7464 init_lsa_String(&n2, "xxNODOMAINxx");
7466 status = dcerpc_samr_LookupDomain(p, tctx, &r);
7467 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7469 r.in.connect_handle = &ctx->handle;
7471 init_lsa_String(&n1, domain);
7472 r.in.domain_name = &n1;
7474 status = dcerpc_samr_LookupDomain(p, tctx, &r);
7475 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
7477 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7478 ret = false;
7481 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7482 ret = false;
7485 return ret;
7489 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7490 struct torture_samr_context *ctx)
7492 NTSTATUS status;
7493 struct samr_EnumDomains r;
7494 uint32_t resume_handle = 0;
7495 uint32_t num_entries = 0;
7496 struct samr_SamArray *sam = NULL;
7497 int i;
7498 bool ret = true;
7500 r.in.connect_handle = &ctx->handle;
7501 r.in.resume_handle = &resume_handle;
7502 r.in.buf_size = (uint32_t)-1;
7503 r.out.resume_handle = &resume_handle;
7504 r.out.num_entries = &num_entries;
7505 r.out.sam = &sam;
7507 status = dcerpc_samr_EnumDomains(p, tctx, &r);
7508 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
7510 if (!*r.out.sam) {
7511 return false;
7514 for (i=0;i<sam->count;i++) {
7515 if (!test_LookupDomain(p, tctx, ctx,
7516 sam->entries[i].name.string)) {
7517 ret = false;
7521 status = dcerpc_samr_EnumDomains(p, tctx, &r);
7522 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
7524 return ret;
7528 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
7529 struct policy_handle *handle)
7531 NTSTATUS status;
7532 struct samr_Connect r;
7533 struct samr_Connect2 r2;
7534 struct samr_Connect3 r3;
7535 struct samr_Connect4 r4;
7536 struct samr_Connect5 r5;
7537 union samr_ConnectInfo info;
7538 struct policy_handle h;
7539 uint32_t level_out = 0;
7540 bool ret = true, got_handle = false;
7542 torture_comment(tctx, "testing samr_Connect\n");
7544 r.in.system_name = 0;
7545 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7546 r.out.connect_handle = &h;
7548 status = dcerpc_samr_Connect(p, tctx, &r);
7549 if (!NT_STATUS_IS_OK(status)) {
7550 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
7551 ret = false;
7552 } else {
7553 got_handle = true;
7554 *handle = h;
7557 torture_comment(tctx, "testing samr_Connect2\n");
7559 r2.in.system_name = NULL;
7560 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7561 r2.out.connect_handle = &h;
7563 status = dcerpc_samr_Connect2(p, tctx, &r2);
7564 if (!NT_STATUS_IS_OK(status)) {
7565 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
7566 ret = false;
7567 } else {
7568 if (got_handle) {
7569 test_samr_handle_Close(p, tctx, handle);
7571 got_handle = true;
7572 *handle = h;
7575 torture_comment(tctx, "testing samr_Connect3\n");
7577 r3.in.system_name = NULL;
7578 r3.in.unknown = 0;
7579 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7580 r3.out.connect_handle = &h;
7582 status = dcerpc_samr_Connect3(p, tctx, &r3);
7583 if (!NT_STATUS_IS_OK(status)) {
7584 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(status));
7585 ret = false;
7586 } else {
7587 if (got_handle) {
7588 test_samr_handle_Close(p, tctx, handle);
7590 got_handle = true;
7591 *handle = h;
7594 torture_comment(tctx, "testing samr_Connect4\n");
7596 r4.in.system_name = "";
7597 r4.in.client_version = 0;
7598 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7599 r4.out.connect_handle = &h;
7601 status = dcerpc_samr_Connect4(p, tctx, &r4);
7602 if (!NT_STATUS_IS_OK(status)) {
7603 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(status));
7604 ret = false;
7605 } else {
7606 if (got_handle) {
7607 test_samr_handle_Close(p, tctx, handle);
7609 got_handle = true;
7610 *handle = h;
7613 torture_comment(tctx, "testing samr_Connect5\n");
7615 info.info1.client_version = 0;
7616 info.info1.unknown2 = 0;
7618 r5.in.system_name = "";
7619 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7620 r5.in.level_in = 1;
7621 r5.out.level_out = &level_out;
7622 r5.in.info_in = &info;
7623 r5.out.info_out = &info;
7624 r5.out.connect_handle = &h;
7626 status = dcerpc_samr_Connect5(p, tctx, &r5);
7627 if (!NT_STATUS_IS_OK(status)) {
7628 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(status));
7629 ret = false;
7630 } else {
7631 if (got_handle) {
7632 test_samr_handle_Close(p, tctx, handle);
7634 got_handle = true;
7635 *handle = h;
7638 return ret;
7642 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p, struct torture_context *tctx)
7644 struct samr_ValidatePassword r;
7645 union samr_ValidatePasswordReq req;
7646 union samr_ValidatePasswordRep *repp = NULL;
7647 NTSTATUS status;
7648 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
7649 int i;
7651 torture_comment(tctx, "testing samr_ValidatePassword\n");
7653 ZERO_STRUCT(r);
7654 r.in.level = NetValidatePasswordReset;
7655 r.in.req = &req;
7656 r.out.rep = &repp;
7658 ZERO_STRUCT(req);
7659 req.req3.account.string = "non-existant-account-aklsdji";
7661 for (i=0; passwords[i]; i++) {
7662 req.req3.password.string = passwords[i];
7663 status = dcerpc_samr_ValidatePassword(p, tctx, &r);
7664 torture_assert_ntstatus_ok(tctx, status, "samr_ValidatePassword");
7665 torture_comment(tctx, "Server %s password '%s' with code %i\n",
7666 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
7667 req.req3.password.string, repp->ctr3.status);
7670 return true;
7673 bool torture_rpc_samr(struct torture_context *torture)
7675 NTSTATUS status;
7676 struct dcerpc_pipe *p;
7677 bool ret = true;
7678 struct torture_samr_context *ctx;
7680 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7681 if (!NT_STATUS_IS_OK(status)) {
7682 return false;
7685 ctx = talloc_zero(torture, struct torture_samr_context);
7687 ctx->choice = TORTURE_SAMR_OTHER;
7689 ret &= test_Connect(p, torture, &ctx->handle);
7691 if (!torture_setting_bool(torture, "samba3", false)) {
7692 ret &= test_QuerySecurity(p, torture, &ctx->handle);
7695 ret &= test_EnumDomains(p, torture, ctx);
7697 ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
7699 ret &= test_Shutdown(p, torture, &ctx->handle);
7701 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7703 return ret;
7707 bool torture_rpc_samr_users(struct torture_context *torture)
7709 NTSTATUS status;
7710 struct dcerpc_pipe *p;
7711 bool ret = true;
7712 struct torture_samr_context *ctx;
7714 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7715 if (!NT_STATUS_IS_OK(status)) {
7716 return false;
7719 ctx = talloc_zero(torture, struct torture_samr_context);
7721 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
7723 ret &= test_Connect(p, torture, &ctx->handle);
7725 if (!torture_setting_bool(torture, "samba3", false)) {
7726 ret &= test_QuerySecurity(p, torture, &ctx->handle);
7729 ret &= test_EnumDomains(p, torture, ctx);
7731 ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
7733 ret &= test_Shutdown(p, torture, &ctx->handle);
7735 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7737 return ret;
7741 bool torture_rpc_samr_passwords(struct torture_context *torture)
7743 NTSTATUS status;
7744 struct dcerpc_pipe *p;
7745 bool ret = true;
7746 struct torture_samr_context *ctx;
7748 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7749 if (!NT_STATUS_IS_OK(status)) {
7750 return false;
7753 ctx = talloc_zero(torture, struct torture_samr_context);
7755 ctx->choice = TORTURE_SAMR_PASSWORDS;
7757 ret &= test_Connect(p, torture, &ctx->handle);
7759 ret &= test_EnumDomains(p, torture, ctx);
7761 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7763 ret &= test_samr_ValidatePassword(p, torture);
7765 return ret;
7768 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
7769 struct dcerpc_pipe *p2,
7770 struct cli_credentials *machine_credentials)
7772 NTSTATUS status;
7773 struct dcerpc_pipe *p;
7774 bool ret = true;
7775 struct torture_samr_context *ctx;
7777 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7778 if (!NT_STATUS_IS_OK(status)) {
7779 return false;
7782 ctx = talloc_zero(torture, struct torture_samr_context);
7784 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
7785 ctx->machine_credentials = machine_credentials;
7787 ret &= test_Connect(p, torture, &ctx->handle);
7789 ret &= test_EnumDomains(p, torture, ctx);
7791 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7793 return ret;
7796 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
7798 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
7799 struct torture_rpc_tcase *tcase;
7801 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7802 &ndr_table_samr,
7803 TEST_ACCOUNT_NAME_PWD);
7805 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
7806 torture_rpc_samr_pwdlastset);
7808 return suite;
7811 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
7812 struct dcerpc_pipe *p2,
7813 struct cli_credentials *machine_credentials)
7815 NTSTATUS status;
7816 struct dcerpc_pipe *p;
7817 bool ret = true;
7818 struct torture_samr_context *ctx;
7820 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7821 if (!NT_STATUS_IS_OK(status)) {
7822 return false;
7825 ctx = talloc_zero(torture, struct torture_samr_context);
7827 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
7828 ctx->machine_credentials = machine_credentials;
7830 ret &= test_Connect(p, torture, &ctx->handle);
7832 ret &= test_EnumDomains(p, torture, ctx);
7834 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7836 return ret;
7839 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
7841 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
7842 struct torture_rpc_tcase *tcase;
7844 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7845 &ndr_table_samr,
7846 TEST_ACCOUNT_NAME_PWD);
7848 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
7849 torture_rpc_samr_users_privileges_delete_user);
7851 return suite;
7854 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
7855 struct dcerpc_pipe *p2,
7856 void *data)
7858 NTSTATUS status;
7859 struct dcerpc_pipe *p;
7860 bool ret = true;
7861 struct torture_samr_context *ctx =
7862 talloc_get_type_abort(data, struct torture_samr_context);
7864 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7865 if (!NT_STATUS_IS_OK(status)) {
7866 return false;
7869 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
7870 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7871 ctx->num_objects_large_dc);
7873 ret &= test_Connect(p, torture, &ctx->handle);
7875 ret &= test_EnumDomains(p, torture, ctx);
7877 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7879 return ret;
7882 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
7883 struct dcerpc_pipe *p2,
7884 void *data)
7886 NTSTATUS status;
7887 struct dcerpc_pipe *p;
7888 bool ret = true;
7889 struct torture_samr_context *ctx =
7890 talloc_get_type_abort(data, struct torture_samr_context);
7892 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7893 if (!NT_STATUS_IS_OK(status)) {
7894 return false;
7897 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
7898 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7899 ctx->num_objects_large_dc);
7901 ret &= test_Connect(p, torture, &ctx->handle);
7903 ret &= test_EnumDomains(p, torture, ctx);
7905 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7907 return ret;
7910 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
7911 struct dcerpc_pipe *p2,
7912 void *data)
7914 NTSTATUS status;
7915 struct dcerpc_pipe *p;
7916 bool ret = true;
7917 struct torture_samr_context *ctx =
7918 talloc_get_type_abort(data, struct torture_samr_context);
7920 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7921 if (!NT_STATUS_IS_OK(status)) {
7922 return false;
7925 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
7926 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7927 ctx->num_objects_large_dc);
7929 ret &= test_Connect(p, torture, &ctx->handle);
7931 ret &= test_EnumDomains(p, torture, ctx);
7933 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7935 return ret;
7938 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
7940 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
7941 struct torture_rpc_tcase *tcase;
7942 struct torture_samr_context *ctx;
7944 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
7946 ctx = talloc_zero(suite, struct torture_samr_context);
7947 ctx->num_objects_large_dc = 150;
7949 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
7950 torture_rpc_samr_many_aliases, ctx);
7951 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
7952 torture_rpc_samr_many_groups, ctx);
7953 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
7954 torture_rpc_samr_many_accounts, ctx);
7956 return suite;
7959 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
7960 struct dcerpc_pipe *p2,
7961 struct cli_credentials *machine_credentials)
7963 NTSTATUS status;
7964 struct dcerpc_pipe *p;
7965 bool ret = true;
7966 struct torture_samr_context *ctx;
7968 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7969 if (!NT_STATUS_IS_OK(status)) {
7970 return false;
7973 ctx = talloc_zero(torture, struct torture_samr_context);
7975 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
7976 ctx->machine_credentials = machine_credentials;
7978 ret &= test_Connect(p, torture, &ctx->handle);
7980 ret &= test_EnumDomains(p, torture, ctx);
7982 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7984 return ret;
7987 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
7989 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-BADPWDCOUNT");
7990 struct torture_rpc_tcase *tcase;
7992 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7993 &ndr_table_samr,
7994 TEST_ACCOUNT_NAME_PWD);
7996 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
7997 torture_rpc_samr_badpwdcount);
7999 return suite;
8002 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8003 struct dcerpc_pipe *p2,
8004 struct cli_credentials *machine_credentials)
8006 NTSTATUS status;
8007 struct dcerpc_pipe *p;
8008 bool ret = true;
8009 struct torture_samr_context *ctx;
8011 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8012 if (!NT_STATUS_IS_OK(status)) {
8013 return false;
8016 ctx = talloc_zero(torture, struct torture_samr_context);
8018 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8019 ctx->machine_credentials = machine_credentials;
8021 ret &= test_Connect(p, torture, &ctx->handle);
8023 ret &= test_EnumDomains(p, torture, ctx);
8025 ret &= test_samr_handle_Close(p, torture, &ctx->handle);
8027 return ret;
8030 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8032 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-LOCKOUT");
8033 struct torture_rpc_tcase *tcase;
8035 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8036 &ndr_table_samr,
8037 TEST_ACCOUNT_NAME_PWD);
8039 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8040 torture_rpc_samr_lockout);
8042 return suite;