s3:torture: fix password timestamp checks on NetBSD
[Samba/gbeck.git] / source4 / torture / rpc / samr.c
blob94c646a91c11c4711ca04cea463f946c3e58c48d
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,2009
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"
37 #include <unistd.h>
39 #define TEST_ACCOUNT_NAME "samrtorturetest"
40 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
41 #define TEST_ALIASNAME "samrtorturetestalias"
42 #define TEST_GROUPNAME "samrtorturetestgroup"
43 #define TEST_MACHINENAME "samrtestmach$"
44 #define TEST_DOMAINNAME "samrtestdom$"
46 enum torture_samr_choice {
47 TORTURE_SAMR_PASSWORDS,
48 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
49 TORTURE_SAMR_USER_ATTRIBUTES,
50 TORTURE_SAMR_USER_PRIVILEGES,
51 TORTURE_SAMR_OTHER,
52 TORTURE_SAMR_MANY_ACCOUNTS,
53 TORTURE_SAMR_MANY_GROUPS,
54 TORTURE_SAMR_MANY_ALIASES
57 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
58 struct torture_context *tctx,
59 struct policy_handle *handle);
61 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
62 struct torture_context *tctx,
63 struct policy_handle *handle);
65 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
66 struct torture_context *tctx,
67 struct policy_handle *handle);
69 static bool test_ChangePassword(struct dcerpc_pipe *p,
70 struct torture_context *tctx,
71 const char *acct_name,
72 struct policy_handle *domain_handle, char **password);
74 static void init_lsa_String(struct lsa_String *string, const char *s)
76 string->string = s;
79 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
81 string->string = s;
84 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
86 string->length = length;
87 string->size = length;
88 string->array = (uint16_t *)discard_const(s);
91 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
92 struct policy_handle *handle)
94 NTSTATUS status;
95 struct samr_Close r;
97 r.in.handle = handle;
98 r.out.handle = handle;
100 status = dcerpc_samr_Close(p, tctx, &r);
101 torture_assert_ntstatus_ok(tctx, status, "Close");
103 return true;
106 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
107 struct policy_handle *handle)
109 NTSTATUS status;
110 struct samr_Shutdown r;
112 if (!torture_setting_bool(tctx, "dangerous", false)) {
113 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
114 return true;
117 r.in.connect_handle = handle;
119 torture_comment(tctx, "testing samr_Shutdown\n");
121 status = dcerpc_samr_Shutdown(p, tctx, &r);
122 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
124 return true;
127 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
128 struct policy_handle *handle)
130 NTSTATUS status;
131 struct samr_SetDsrmPassword r;
132 struct lsa_String string;
133 struct samr_Password hash;
135 if (!torture_setting_bool(tctx, "dangerous", false)) {
136 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
139 E_md4hash("TeSTDSRM123", hash.hash);
141 init_lsa_String(&string, "Administrator");
143 r.in.name = &string;
144 r.in.unknown = 0;
145 r.in.hash = &hash;
147 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
149 status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
150 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
152 return true;
156 static bool test_QuerySecurity(struct dcerpc_pipe *p,
157 struct torture_context *tctx,
158 struct policy_handle *handle)
160 NTSTATUS status;
161 struct samr_QuerySecurity r;
162 struct samr_SetSecurity s;
163 struct sec_desc_buf *sdbuf = NULL;
165 r.in.handle = handle;
166 r.in.sec_info = 7;
167 r.out.sdbuf = &sdbuf;
169 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
170 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
172 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
174 s.in.handle = handle;
175 s.in.sec_info = 7;
176 s.in.sdbuf = sdbuf;
178 if (torture_setting_bool(tctx, "samba4", false)) {
179 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
182 status = dcerpc_samr_SetSecurity(p, tctx, &s);
183 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
185 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
186 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
188 return true;
192 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
193 struct policy_handle *handle, uint32_t base_acct_flags,
194 const char *base_account_name)
196 NTSTATUS status;
197 struct samr_SetUserInfo s;
198 struct samr_SetUserInfo2 s2;
199 struct samr_QueryUserInfo q;
200 struct samr_QueryUserInfo q0;
201 union samr_UserInfo u;
202 union samr_UserInfo *info;
203 bool ret = true;
204 const char *test_account_name;
206 uint32_t user_extra_flags = 0;
208 if (!torture_setting_bool(tctx, "samba3", false)) {
209 if (base_acct_flags == ACB_NORMAL) {
210 /* When created, accounts are expired by default */
211 user_extra_flags = ACB_PW_EXPIRED;
215 s.in.user_handle = handle;
216 s.in.info = &u;
218 s2.in.user_handle = handle;
219 s2.in.info = &u;
221 q.in.user_handle = handle;
222 q.out.info = &info;
223 q0 = q;
225 #define TESTCALL(call, r) \
226 status = dcerpc_samr_ ##call(p, tctx, &r); \
227 if (!NT_STATUS_IS_OK(status)) { \
228 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
229 r.in.level, nt_errstr(status), __location__); \
230 ret = false; \
231 break; \
234 #define STRING_EQUAL(s1, s2, field) \
235 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
236 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
237 #field, s2, __location__); \
238 ret = false; \
239 break; \
242 #define MEM_EQUAL(s1, s2, length, field) \
243 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
244 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
245 #field, (const char *)s2, __location__); \
246 ret = false; \
247 break; \
250 #define INT_EQUAL(i1, i2, field) \
251 if (i1 != i2) { \
252 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
253 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
254 ret = false; \
255 break; \
258 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
259 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
260 q.in.level = lvl1; \
261 TESTCALL(QueryUserInfo, q) \
262 s.in.level = lvl1; \
263 s2.in.level = lvl1; \
264 u = *info; \
265 if (lvl1 == 21) { \
266 ZERO_STRUCT(u.info21); \
267 u.info21.fields_present = fpval; \
269 init_lsa_String(&u.info ## lvl1.field1, value); \
270 TESTCALL(SetUserInfo, s) \
271 TESTCALL(SetUserInfo2, s2) \
272 init_lsa_String(&u.info ## lvl1.field1, ""); \
273 TESTCALL(QueryUserInfo, q); \
274 u = *info; \
275 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
276 q.in.level = lvl2; \
277 TESTCALL(QueryUserInfo, q) \
278 u = *info; \
279 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
280 } while (0)
282 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
283 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
284 q.in.level = lvl1; \
285 TESTCALL(QueryUserInfo, q) \
286 s.in.level = lvl1; \
287 s2.in.level = lvl1; \
288 u = *info; \
289 if (lvl1 == 21) { \
290 ZERO_STRUCT(u.info21); \
291 u.info21.fields_present = fpval; \
293 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
294 TESTCALL(SetUserInfo, s) \
295 TESTCALL(SetUserInfo2, s2) \
296 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
297 TESTCALL(QueryUserInfo, q); \
298 u = *info; \
299 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
300 q.in.level = lvl2; \
301 TESTCALL(QueryUserInfo, q) \
302 u = *info; \
303 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
304 } while (0)
306 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
307 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
308 q.in.level = lvl1; \
309 TESTCALL(QueryUserInfo, q) \
310 s.in.level = lvl1; \
311 s2.in.level = lvl1; \
312 u = *info; \
313 if (lvl1 == 21) { \
314 uint8_t *bits = u.info21.logon_hours.bits; \
315 ZERO_STRUCT(u.info21); \
316 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
317 u.info21.logon_hours.units_per_week = 168; \
318 u.info21.logon_hours.bits = bits; \
320 u.info21.fields_present = fpval; \
322 u.info ## lvl1.field1 = value; \
323 TESTCALL(SetUserInfo, s) \
324 TESTCALL(SetUserInfo2, s2) \
325 u.info ## lvl1.field1 = 0; \
326 TESTCALL(QueryUserInfo, q); \
327 u = *info; \
328 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
329 q.in.level = lvl2; \
330 TESTCALL(QueryUserInfo, q) \
331 u = *info; \
332 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
333 } while (0)
335 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
336 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
337 } while (0)
339 q0.in.level = 12;
340 do { TESTCALL(QueryUserInfo, q0) } while (0);
342 /* Samba 3 cannot store comment fields atm. - gd */
343 if (!torture_setting_bool(tctx, "samba3", false)) {
344 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
345 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
346 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
347 SAMR_FIELD_COMMENT);
350 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
351 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
352 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
353 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
354 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
355 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
356 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
357 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
358 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
359 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
360 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
361 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
362 test_account_name = base_account_name;
363 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
364 SAMR_FIELD_ACCOUNT_NAME);
366 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
367 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
368 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
369 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
370 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
371 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
372 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
373 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
374 SAMR_FIELD_FULL_NAME);
376 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
377 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
378 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
379 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
380 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
381 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
382 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
383 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
384 SAMR_FIELD_FULL_NAME);
386 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
387 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
388 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
389 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
390 SAMR_FIELD_LOGON_SCRIPT);
392 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
393 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
394 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
395 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
396 SAMR_FIELD_PROFILE_PATH);
398 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
399 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
400 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
401 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
402 SAMR_FIELD_HOME_DIRECTORY);
403 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
404 SAMR_FIELD_HOME_DIRECTORY);
406 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
407 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
408 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
409 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
410 SAMR_FIELD_HOME_DRIVE);
411 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
412 SAMR_FIELD_HOME_DRIVE);
414 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
415 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
416 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
417 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
418 SAMR_FIELD_DESCRIPTION);
420 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
421 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
422 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
423 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
424 SAMR_FIELD_WORKSTATIONS);
425 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
426 SAMR_FIELD_WORKSTATIONS);
427 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
428 SAMR_FIELD_WORKSTATIONS);
429 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
430 SAMR_FIELD_WORKSTATIONS);
432 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
433 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
434 SAMR_FIELD_PARAMETERS);
435 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
436 SAMR_FIELD_PARAMETERS);
437 /* also empty user parameters are allowed */
438 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
439 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
440 SAMR_FIELD_PARAMETERS);
441 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
442 SAMR_FIELD_PARAMETERS);
444 /* Samba 3 cannot store country_code and copy_page atm. - gd */
445 if (!torture_setting_bool(tctx, "samba3", false)) {
446 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
447 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
448 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
449 SAMR_FIELD_COUNTRY_CODE);
450 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
451 SAMR_FIELD_COUNTRY_CODE);
453 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
454 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
455 SAMR_FIELD_CODE_PAGE);
456 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
457 SAMR_FIELD_CODE_PAGE);
460 if (!torture_setting_bool(tctx, "samba3", false)) {
461 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
462 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
463 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
464 SAMR_FIELD_ACCT_EXPIRY);
465 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
466 SAMR_FIELD_ACCT_EXPIRY);
467 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
468 SAMR_FIELD_ACCT_EXPIRY);
469 } else {
470 /* Samba 3 can only store seconds / time_t in passdb - gd */
471 NTTIME nt;
472 unix_to_nt_time(&nt, time(NULL) + __LINE__);
473 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
474 unix_to_nt_time(&nt, time(NULL) + __LINE__);
475 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
476 unix_to_nt_time(&nt, time(NULL) + __LINE__);
477 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
478 unix_to_nt_time(&nt, time(NULL) + __LINE__);
479 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
480 unix_to_nt_time(&nt, time(NULL) + __LINE__);
481 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
484 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
485 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
486 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
487 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
488 SAMR_FIELD_LOGON_HOURS);
490 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
491 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
492 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
494 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
495 (base_acct_flags | ACB_DISABLED),
496 (base_acct_flags | ACB_DISABLED | user_extra_flags),
499 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
500 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
501 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
502 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
504 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
505 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
506 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
510 /* The 'autolock' flag doesn't stick - check this */
511 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
512 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
513 (base_acct_flags | ACB_DISABLED | user_extra_flags),
515 #if 0
516 /* Removing the 'disabled' flag doesn't stick - check this */
517 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
518 (base_acct_flags),
519 (base_acct_flags | ACB_DISABLED | user_extra_flags),
521 #endif
523 /* Samba3 cannot store these atm */
524 if (!torture_setting_bool(tctx, "samba3", false)) {
525 /* The 'store plaintext' flag does stick */
526 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
527 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
528 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
530 /* The 'use DES' flag does stick */
531 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
532 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
533 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
535 /* The 'don't require kerberos pre-authentication flag does stick */
536 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
537 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
538 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
540 /* The 'no kerberos PAC required' flag sticks */
541 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
542 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
543 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
546 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
547 (base_acct_flags | ACB_DISABLED),
548 (base_acct_flags | ACB_DISABLED | user_extra_flags),
549 SAMR_FIELD_ACCT_FLAGS);
551 #if 0
552 /* these fail with win2003 - it appears you can't set the primary gid?
553 the set succeeds, but the gid isn't changed. Very weird! */
554 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
555 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
556 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
557 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
558 #endif
560 return ret;
564 generate a random password for password change tests
566 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
568 size_t len = MAX(8, min_len) + (random() % 6);
569 char *s = generate_random_str(mem_ctx, len);
570 return s;
573 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
575 char *s = samr_rand_pass_silent(mem_ctx, min_len);
576 printf("Generated password '%s'\n", s);
577 return s;
582 generate a random password for password change tests
584 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
586 int i;
587 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
588 generate_random_buffer(password.data, password.length);
590 for (i=0; i < len; i++) {
591 if (((uint16_t *)password.data)[i] == 0) {
592 ((uint16_t *)password.data)[i] = 1;
596 return password;
600 generate a random password for password change tests (fixed length)
602 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
604 char *s = generate_random_str(mem_ctx, len);
605 printf("Generated password '%s'\n", s);
606 return s;
609 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
610 struct policy_handle *handle, char **password)
612 NTSTATUS status;
613 struct samr_SetUserInfo s;
614 union samr_UserInfo u;
615 bool ret = true;
616 DATA_BLOB session_key;
617 char *newpass;
618 struct samr_GetUserPwInfo pwp;
619 struct samr_PwInfo info;
620 int policy_min_pw_len = 0;
621 pwp.in.user_handle = handle;
622 pwp.out.info = &info;
624 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
625 if (NT_STATUS_IS_OK(status)) {
626 policy_min_pw_len = pwp.out.info->min_password_length;
628 newpass = samr_rand_pass(tctx, policy_min_pw_len);
630 s.in.user_handle = handle;
631 s.in.info = &u;
632 s.in.level = 24;
634 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
635 u.info24.password_expired = 0;
637 status = dcerpc_fetch_session_key(p, &session_key);
638 if (!NT_STATUS_IS_OK(status)) {
639 printf("SetUserInfo level %u - no session key - %s\n",
640 s.in.level, nt_errstr(status));
641 return false;
644 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
646 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
648 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
649 if (!NT_STATUS_IS_OK(status)) {
650 printf("SetUserInfo level %u failed - %s\n",
651 s.in.level, nt_errstr(status));
652 ret = false;
653 } else {
654 *password = newpass;
657 return ret;
661 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
662 struct policy_handle *handle, uint32_t fields_present,
663 char **password)
665 NTSTATUS status;
666 struct samr_SetUserInfo s;
667 union samr_UserInfo u;
668 bool ret = true;
669 DATA_BLOB session_key;
670 char *newpass;
671 struct samr_GetUserPwInfo pwp;
672 struct samr_PwInfo info;
673 int policy_min_pw_len = 0;
674 pwp.in.user_handle = handle;
675 pwp.out.info = &info;
677 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
678 if (NT_STATUS_IS_OK(status)) {
679 policy_min_pw_len = pwp.out.info->min_password_length;
681 newpass = samr_rand_pass(tctx, policy_min_pw_len);
683 s.in.user_handle = handle;
684 s.in.info = &u;
685 s.in.level = 23;
687 ZERO_STRUCT(u);
689 u.info23.info.fields_present = fields_present;
691 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
693 status = dcerpc_fetch_session_key(p, &session_key);
694 if (!NT_STATUS_IS_OK(status)) {
695 printf("SetUserInfo level %u - no session key - %s\n",
696 s.in.level, nt_errstr(status));
697 return false;
700 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
702 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
704 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
705 if (!NT_STATUS_IS_OK(status)) {
706 printf("SetUserInfo level %u failed - %s\n",
707 s.in.level, nt_errstr(status));
708 ret = false;
709 } else {
710 *password = newpass;
713 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
715 status = dcerpc_fetch_session_key(p, &session_key);
716 if (!NT_STATUS_IS_OK(status)) {
717 printf("SetUserInfo level %u - no session key - %s\n",
718 s.in.level, nt_errstr(status));
719 return false;
722 /* This should break the key nicely */
723 session_key.length--;
724 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
726 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
728 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
729 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
730 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
731 s.in.level, nt_errstr(status));
732 ret = false;
735 return ret;
739 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
740 struct policy_handle *handle, bool makeshort,
741 char **password)
743 NTSTATUS status;
744 struct samr_SetUserInfo s;
745 union samr_UserInfo u;
746 bool ret = true;
747 DATA_BLOB session_key;
748 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
749 uint8_t confounder[16];
750 char *newpass;
751 struct MD5Context ctx;
752 struct samr_GetUserPwInfo pwp;
753 struct samr_PwInfo info;
754 int policy_min_pw_len = 0;
755 pwp.in.user_handle = handle;
756 pwp.out.info = &info;
758 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
759 if (NT_STATUS_IS_OK(status)) {
760 policy_min_pw_len = pwp.out.info->min_password_length;
762 if (makeshort && policy_min_pw_len) {
763 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
764 } else {
765 newpass = samr_rand_pass(tctx, policy_min_pw_len);
768 s.in.user_handle = handle;
769 s.in.info = &u;
770 s.in.level = 26;
772 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
773 u.info26.password_expired = 0;
775 status = dcerpc_fetch_session_key(p, &session_key);
776 if (!NT_STATUS_IS_OK(status)) {
777 printf("SetUserInfo level %u - no session key - %s\n",
778 s.in.level, nt_errstr(status));
779 return false;
782 generate_random_buffer((uint8_t *)confounder, 16);
784 MD5Init(&ctx);
785 MD5Update(&ctx, confounder, 16);
786 MD5Update(&ctx, session_key.data, session_key.length);
787 MD5Final(confounded_session_key.data, &ctx);
789 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
790 memcpy(&u.info26.password.data[516], confounder, 16);
792 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
794 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
795 if (!NT_STATUS_IS_OK(status)) {
796 printf("SetUserInfo level %u failed - %s\n",
797 s.in.level, nt_errstr(status));
798 ret = false;
799 } else {
800 *password = newpass;
803 /* This should break the key nicely */
804 confounded_session_key.data[0]++;
806 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
807 memcpy(&u.info26.password.data[516], confounder, 16);
809 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
811 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
812 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
813 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
814 s.in.level, nt_errstr(status));
815 ret = false;
816 } else {
817 *password = newpass;
820 return ret;
823 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
824 struct policy_handle *handle, uint32_t fields_present,
825 char **password)
827 NTSTATUS status;
828 struct samr_SetUserInfo s;
829 union samr_UserInfo u;
830 bool ret = true;
831 DATA_BLOB session_key;
832 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
833 struct MD5Context ctx;
834 uint8_t confounder[16];
835 char *newpass;
836 struct samr_GetUserPwInfo pwp;
837 struct samr_PwInfo info;
838 int policy_min_pw_len = 0;
839 pwp.in.user_handle = handle;
840 pwp.out.info = &info;
842 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
843 if (NT_STATUS_IS_OK(status)) {
844 policy_min_pw_len = pwp.out.info->min_password_length;
846 newpass = samr_rand_pass(tctx, policy_min_pw_len);
848 s.in.user_handle = handle;
849 s.in.info = &u;
850 s.in.level = 25;
852 ZERO_STRUCT(u);
854 u.info25.info.fields_present = fields_present;
856 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
858 status = dcerpc_fetch_session_key(p, &session_key);
859 if (!NT_STATUS_IS_OK(status)) {
860 printf("SetUserInfo level %u - no session key - %s\n",
861 s.in.level, nt_errstr(status));
862 return false;
865 generate_random_buffer((uint8_t *)confounder, 16);
867 MD5Init(&ctx);
868 MD5Update(&ctx, confounder, 16);
869 MD5Update(&ctx, session_key.data, session_key.length);
870 MD5Final(confounded_session_key.data, &ctx);
872 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
873 memcpy(&u.info25.password.data[516], confounder, 16);
875 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
877 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
878 if (!NT_STATUS_IS_OK(status)) {
879 printf("SetUserInfo level %u failed - %s\n",
880 s.in.level, nt_errstr(status));
881 ret = false;
882 } else {
883 *password = newpass;
886 /* This should break the key nicely */
887 confounded_session_key.data[0]++;
889 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
890 memcpy(&u.info25.password.data[516], confounder, 16);
892 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
894 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
895 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
896 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
897 s.in.level, nt_errstr(status));
898 ret = false;
901 return ret;
904 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
905 struct policy_handle *handle, char **password)
907 NTSTATUS status;
908 struct samr_SetUserInfo s;
909 union samr_UserInfo u;
910 bool ret = true;
911 DATA_BLOB session_key;
912 char *newpass;
913 struct samr_GetUserPwInfo pwp;
914 struct samr_PwInfo info;
915 int policy_min_pw_len = 0;
916 uint8_t lm_hash[16], nt_hash[16];
918 pwp.in.user_handle = handle;
919 pwp.out.info = &info;
921 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
922 if (NT_STATUS_IS_OK(status)) {
923 policy_min_pw_len = pwp.out.info->min_password_length;
925 newpass = samr_rand_pass(tctx, policy_min_pw_len);
927 s.in.user_handle = handle;
928 s.in.info = &u;
929 s.in.level = 18;
931 ZERO_STRUCT(u);
933 u.info18.nt_pwd_active = true;
934 u.info18.lm_pwd_active = true;
936 E_md4hash(newpass, nt_hash);
937 E_deshash(newpass, lm_hash);
939 status = dcerpc_fetch_session_key(p, &session_key);
940 if (!NT_STATUS_IS_OK(status)) {
941 printf("SetUserInfo level %u - no session key - %s\n",
942 s.in.level, nt_errstr(status));
943 return false;
947 DATA_BLOB in,out;
948 in = data_blob_const(nt_hash, 16);
949 out = data_blob_talloc_zero(tctx, 16);
950 sess_crypt_blob(&out, &in, &session_key, true);
951 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
954 DATA_BLOB in,out;
955 in = data_blob_const(lm_hash, 16);
956 out = data_blob_talloc_zero(tctx, 16);
957 sess_crypt_blob(&out, &in, &session_key, true);
958 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
961 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
963 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
964 if (!NT_STATUS_IS_OK(status)) {
965 printf("SetUserInfo level %u failed - %s\n",
966 s.in.level, nt_errstr(status));
967 ret = false;
968 } else {
969 *password = newpass;
972 return ret;
975 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
976 struct policy_handle *handle, uint32_t fields_present,
977 char **password)
979 NTSTATUS status;
980 struct samr_SetUserInfo s;
981 union samr_UserInfo u;
982 bool ret = true;
983 DATA_BLOB session_key;
984 char *newpass;
985 struct samr_GetUserPwInfo pwp;
986 struct samr_PwInfo info;
987 int policy_min_pw_len = 0;
988 uint8_t lm_hash[16], nt_hash[16];
990 pwp.in.user_handle = handle;
991 pwp.out.info = &info;
993 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
994 if (NT_STATUS_IS_OK(status)) {
995 policy_min_pw_len = pwp.out.info->min_password_length;
997 newpass = samr_rand_pass(tctx, policy_min_pw_len);
999 s.in.user_handle = handle;
1000 s.in.info = &u;
1001 s.in.level = 21;
1003 E_md4hash(newpass, nt_hash);
1004 E_deshash(newpass, lm_hash);
1006 ZERO_STRUCT(u);
1008 u.info21.fields_present = fields_present;
1010 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1011 u.info21.lm_owf_password.length = 16;
1012 u.info21.lm_owf_password.size = 16;
1013 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1014 u.info21.lm_password_set = true;
1017 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1018 u.info21.nt_owf_password.length = 16;
1019 u.info21.nt_owf_password.size = 16;
1020 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1021 u.info21.nt_password_set = true;
1024 status = dcerpc_fetch_session_key(p, &session_key);
1025 if (!NT_STATUS_IS_OK(status)) {
1026 printf("SetUserInfo level %u - no session key - %s\n",
1027 s.in.level, nt_errstr(status));
1028 return false;
1031 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1032 DATA_BLOB in,out;
1033 in = data_blob_const(u.info21.lm_owf_password.array,
1034 u.info21.lm_owf_password.length);
1035 out = data_blob_talloc_zero(tctx, 16);
1036 sess_crypt_blob(&out, &in, &session_key, true);
1037 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1040 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1041 DATA_BLOB in,out;
1042 in = data_blob_const(u.info21.nt_owf_password.array,
1043 u.info21.nt_owf_password.length);
1044 out = data_blob_talloc_zero(tctx, 16);
1045 sess_crypt_blob(&out, &in, &session_key, true);
1046 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1049 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1051 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 printf("SetUserInfo level %u failed - %s\n",
1054 s.in.level, nt_errstr(status));
1055 ret = false;
1056 } else {
1057 *password = newpass;
1060 /* try invalid length */
1061 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1063 u.info21.nt_owf_password.length++;
1065 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1067 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1068 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1069 s.in.level, nt_errstr(status));
1070 ret = false;
1074 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1076 u.info21.lm_owf_password.length++;
1078 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1080 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1081 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1082 s.in.level, nt_errstr(status));
1083 ret = false;
1087 return ret;
1090 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1091 struct torture_context *tctx,
1092 struct policy_handle *handle,
1093 uint16_t level,
1094 uint32_t fields_present,
1095 char **password, uint8_t password_expired,
1096 bool use_setinfo2,
1097 bool *matched_expected_error)
1099 NTSTATUS status;
1100 NTSTATUS expected_error = NT_STATUS_OK;
1101 struct samr_SetUserInfo s;
1102 struct samr_SetUserInfo2 s2;
1103 union samr_UserInfo u;
1104 bool ret = true;
1105 DATA_BLOB session_key;
1106 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1107 struct MD5Context ctx;
1108 uint8_t confounder[16];
1109 char *newpass;
1110 struct samr_GetUserPwInfo pwp;
1111 struct samr_PwInfo info;
1112 int policy_min_pw_len = 0;
1113 const char *comment = NULL;
1114 uint8_t lm_hash[16], nt_hash[16];
1116 pwp.in.user_handle = handle;
1117 pwp.out.info = &info;
1119 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1120 if (NT_STATUS_IS_OK(status)) {
1121 policy_min_pw_len = pwp.out.info->min_password_length;
1123 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1125 if (use_setinfo2) {
1126 s2.in.user_handle = handle;
1127 s2.in.info = &u;
1128 s2.in.level = level;
1129 } else {
1130 s.in.user_handle = handle;
1131 s.in.info = &u;
1132 s.in.level = level;
1135 if (fields_present & SAMR_FIELD_COMMENT) {
1136 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1139 ZERO_STRUCT(u);
1141 switch (level) {
1142 case 18:
1143 E_md4hash(newpass, nt_hash);
1144 E_deshash(newpass, lm_hash);
1146 u.info18.nt_pwd_active = true;
1147 u.info18.lm_pwd_active = true;
1148 u.info18.password_expired = password_expired;
1150 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1151 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1153 break;
1154 case 21:
1155 E_md4hash(newpass, nt_hash);
1156 E_deshash(newpass, lm_hash);
1158 u.info21.fields_present = fields_present;
1159 u.info21.password_expired = password_expired;
1160 u.info21.comment.string = comment;
1162 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1163 u.info21.lm_owf_password.length = 16;
1164 u.info21.lm_owf_password.size = 16;
1165 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1166 u.info21.lm_password_set = true;
1169 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1170 u.info21.nt_owf_password.length = 16;
1171 u.info21.nt_owf_password.size = 16;
1172 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1173 u.info21.nt_password_set = true;
1176 break;
1177 case 23:
1178 u.info23.info.fields_present = fields_present;
1179 u.info23.info.password_expired = password_expired;
1180 u.info23.info.comment.string = comment;
1182 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1184 break;
1185 case 24:
1186 u.info24.password_expired = password_expired;
1188 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1190 break;
1191 case 25:
1192 u.info25.info.fields_present = fields_present;
1193 u.info25.info.password_expired = password_expired;
1194 u.info25.info.comment.string = comment;
1196 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1198 break;
1199 case 26:
1200 u.info26.password_expired = password_expired;
1202 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1204 break;
1207 status = dcerpc_fetch_session_key(p, &session_key);
1208 if (!NT_STATUS_IS_OK(status)) {
1209 printf("SetUserInfo level %u - no session key - %s\n",
1210 s.in.level, nt_errstr(status));
1211 return false;
1214 generate_random_buffer((uint8_t *)confounder, 16);
1216 MD5Init(&ctx);
1217 MD5Update(&ctx, confounder, 16);
1218 MD5Update(&ctx, session_key.data, session_key.length);
1219 MD5Final(confounded_session_key.data, &ctx);
1221 switch (level) {
1222 case 18:
1224 DATA_BLOB in,out;
1225 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1226 out = data_blob_talloc_zero(tctx, 16);
1227 sess_crypt_blob(&out, &in, &session_key, true);
1228 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1231 DATA_BLOB in,out;
1232 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1233 out = data_blob_talloc_zero(tctx, 16);
1234 sess_crypt_blob(&out, &in, &session_key, true);
1235 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1238 break;
1239 case 21:
1240 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1241 DATA_BLOB in,out;
1242 in = data_blob_const(u.info21.lm_owf_password.array,
1243 u.info21.lm_owf_password.length);
1244 out = data_blob_talloc_zero(tctx, 16);
1245 sess_crypt_blob(&out, &in, &session_key, true);
1246 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1248 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1249 DATA_BLOB in,out;
1250 in = data_blob_const(u.info21.nt_owf_password.array,
1251 u.info21.nt_owf_password.length);
1252 out = data_blob_talloc_zero(tctx, 16);
1253 sess_crypt_blob(&out, &in, &session_key, true);
1254 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1256 break;
1257 case 23:
1258 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1259 break;
1260 case 24:
1261 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1262 break;
1263 case 25:
1264 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1265 memcpy(&u.info25.password.data[516], confounder, 16);
1266 break;
1267 case 26:
1268 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1269 memcpy(&u.info26.password.data[516], confounder, 16);
1270 break;
1273 if (use_setinfo2) {
1274 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1275 } else {
1276 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 if (fields_present == 0) {
1281 expected_error = NT_STATUS_INVALID_PARAMETER;
1283 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1284 expected_error = NT_STATUS_ACCESS_DENIED;
1288 if (!NT_STATUS_IS_OK(expected_error)) {
1289 if (use_setinfo2) {
1290 torture_assert_ntstatus_equal(tctx,
1291 s2.out.result,
1292 expected_error, "SetUserInfo2 failed");
1293 } else {
1294 torture_assert_ntstatus_equal(tctx,
1295 s.out.result,
1296 expected_error, "SetUserInfo failed");
1298 *matched_expected_error = true;
1299 return true;
1302 if (!NT_STATUS_IS_OK(status)) {
1303 printf("SetUserInfo%s level %u failed - %s\n",
1304 use_setinfo2 ? "2":"", level, nt_errstr(status));
1305 ret = false;
1306 } else {
1307 *password = newpass;
1310 return ret;
1313 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1314 struct policy_handle *handle)
1316 NTSTATUS status;
1317 struct samr_SetAliasInfo r;
1318 struct samr_QueryAliasInfo q;
1319 union samr_AliasInfo *info;
1320 uint16_t levels[] = {2, 3};
1321 int i;
1322 bool ret = true;
1324 /* Ignoring switch level 1, as that includes the number of members for the alias
1325 * and setting this to a wrong value might have negative consequences
1328 for (i=0;i<ARRAY_SIZE(levels);i++) {
1329 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1331 r.in.alias_handle = handle;
1332 r.in.level = levels[i];
1333 r.in.info = talloc(tctx, union samr_AliasInfo);
1334 switch (r.in.level) {
1335 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1336 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1337 "Test Description, should test I18N as well"); break;
1338 case ALIASINFOALL: printf("ALIASINFOALL ignored\n"); break;
1341 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1342 if (!NT_STATUS_IS_OK(status)) {
1343 printf("SetAliasInfo level %u failed - %s\n",
1344 levels[i], nt_errstr(status));
1345 ret = false;
1348 q.in.alias_handle = handle;
1349 q.in.level = levels[i];
1350 q.out.info = &info;
1352 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1353 if (!NT_STATUS_IS_OK(status)) {
1354 printf("QueryAliasInfo level %u failed - %s\n",
1355 levels[i], nt_errstr(status));
1356 ret = false;
1360 return ret;
1363 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1364 struct policy_handle *user_handle)
1366 struct samr_GetGroupsForUser r;
1367 struct samr_RidWithAttributeArray *rids = NULL;
1368 NTSTATUS status;
1370 torture_comment(tctx, "testing GetGroupsForUser\n");
1372 r.in.user_handle = user_handle;
1373 r.out.rids = &rids;
1375 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1376 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1378 return true;
1382 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1383 struct lsa_String *domain_name)
1385 NTSTATUS status;
1386 struct samr_GetDomPwInfo r;
1387 struct samr_PwInfo info;
1389 r.in.domain_name = domain_name;
1390 r.out.info = &info;
1392 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1394 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1395 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1397 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1398 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1400 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1401 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1403 r.in.domain_name->string = "\\\\__NONAME__";
1404 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1406 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1407 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1409 r.in.domain_name->string = "\\\\Builtin";
1410 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1412 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1413 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1415 return true;
1418 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1419 struct policy_handle *handle)
1421 NTSTATUS status;
1422 struct samr_GetUserPwInfo r;
1423 struct samr_PwInfo info;
1425 torture_comment(tctx, "Testing GetUserPwInfo\n");
1427 r.in.user_handle = handle;
1428 r.out.info = &info;
1430 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1431 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1433 return true;
1436 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1437 struct policy_handle *domain_handle, const char *name,
1438 uint32_t *rid)
1440 NTSTATUS status;
1441 struct samr_LookupNames n;
1442 struct lsa_String sname[2];
1443 struct samr_Ids rids, types;
1445 init_lsa_String(&sname[0], name);
1447 n.in.domain_handle = domain_handle;
1448 n.in.num_names = 1;
1449 n.in.names = sname;
1450 n.out.rids = &rids;
1451 n.out.types = &types;
1452 status = dcerpc_samr_LookupNames(p, tctx, &n);
1453 if (NT_STATUS_IS_OK(status)) {
1454 *rid = n.out.rids->ids[0];
1455 } else {
1456 return status;
1459 init_lsa_String(&sname[1], "xxNONAMExx");
1460 n.in.num_names = 2;
1461 status = dcerpc_samr_LookupNames(p, tctx, &n);
1462 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1463 printf("LookupNames[2] failed - %s\n", nt_errstr(status));
1464 if (NT_STATUS_IS_OK(status)) {
1465 return NT_STATUS_UNSUCCESSFUL;
1467 return status;
1470 n.in.num_names = 0;
1471 status = dcerpc_samr_LookupNames(p, tctx, &n);
1472 if (!NT_STATUS_IS_OK(status)) {
1473 printf("LookupNames[0] failed - %s\n", nt_errstr(status));
1474 return status;
1477 init_lsa_String(&sname[0], "xxNONAMExx");
1478 n.in.num_names = 1;
1479 status = dcerpc_samr_LookupNames(p, tctx, &n);
1480 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1481 printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1482 if (NT_STATUS_IS_OK(status)) {
1483 return NT_STATUS_UNSUCCESSFUL;
1485 return status;
1488 init_lsa_String(&sname[0], "xxNONAMExx");
1489 init_lsa_String(&sname[1], "xxNONAME2xx");
1490 n.in.num_names = 2;
1491 status = dcerpc_samr_LookupNames(p, tctx, &n);
1492 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1493 printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1494 if (NT_STATUS_IS_OK(status)) {
1495 return NT_STATUS_UNSUCCESSFUL;
1497 return status;
1500 return NT_STATUS_OK;
1503 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
1504 struct torture_context *tctx,
1505 struct policy_handle *domain_handle,
1506 const char *name, struct policy_handle *user_handle)
1508 NTSTATUS status;
1509 struct samr_OpenUser r;
1510 uint32_t rid;
1512 status = test_LookupName(p, tctx, domain_handle, name, &rid);
1513 if (!NT_STATUS_IS_OK(status)) {
1514 return status;
1517 r.in.domain_handle = domain_handle;
1518 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1519 r.in.rid = rid;
1520 r.out.user_handle = user_handle;
1521 status = dcerpc_samr_OpenUser(p, tctx, &r);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1526 return status;
1529 #if 0
1530 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1531 struct torture_context *tctx,
1532 struct policy_handle *handle)
1534 NTSTATUS status;
1535 struct samr_ChangePasswordUser r;
1536 bool ret = true;
1537 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1538 struct policy_handle user_handle;
1539 char *oldpass = "test";
1540 char *newpass = "test2";
1541 uint8_t old_nt_hash[16], new_nt_hash[16];
1542 uint8_t old_lm_hash[16], new_lm_hash[16];
1544 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1545 if (!NT_STATUS_IS_OK(status)) {
1546 return false;
1549 printf("Testing ChangePasswordUser for user 'testuser'\n");
1551 printf("old password: %s\n", oldpass);
1552 printf("new password: %s\n", newpass);
1554 E_md4hash(oldpass, old_nt_hash);
1555 E_md4hash(newpass, new_nt_hash);
1556 E_deshash(oldpass, old_lm_hash);
1557 E_deshash(newpass, new_lm_hash);
1559 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1560 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1561 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1562 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1563 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1564 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1566 r.in.handle = &user_handle;
1567 r.in.lm_present = 1;
1568 r.in.old_lm_crypted = &hash1;
1569 r.in.new_lm_crypted = &hash2;
1570 r.in.nt_present = 1;
1571 r.in.old_nt_crypted = &hash3;
1572 r.in.new_nt_crypted = &hash4;
1573 r.in.cross1_present = 1;
1574 r.in.nt_cross = &hash5;
1575 r.in.cross2_present = 1;
1576 r.in.lm_cross = &hash6;
1578 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1579 if (!NT_STATUS_IS_OK(status)) {
1580 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1581 ret = false;
1584 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1585 ret = false;
1588 return ret;
1590 #endif
1592 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1593 const char *acct_name,
1594 struct policy_handle *handle, char **password)
1596 NTSTATUS status;
1597 struct samr_ChangePasswordUser r;
1598 bool ret = true;
1599 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1600 struct policy_handle user_handle;
1601 char *oldpass;
1602 uint8_t old_nt_hash[16], new_nt_hash[16];
1603 uint8_t old_lm_hash[16], new_lm_hash[16];
1604 bool changed = true;
1606 char *newpass;
1607 struct samr_GetUserPwInfo pwp;
1608 struct samr_PwInfo info;
1609 int policy_min_pw_len = 0;
1611 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1612 if (!NT_STATUS_IS_OK(status)) {
1613 return false;
1615 pwp.in.user_handle = &user_handle;
1616 pwp.out.info = &info;
1618 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1619 if (NT_STATUS_IS_OK(status)) {
1620 policy_min_pw_len = pwp.out.info->min_password_length;
1622 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1624 torture_comment(tctx, "Testing ChangePasswordUser\n");
1626 torture_assert(tctx, *password != NULL,
1627 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1629 oldpass = *password;
1631 E_md4hash(oldpass, old_nt_hash);
1632 E_md4hash(newpass, new_nt_hash);
1633 E_deshash(oldpass, old_lm_hash);
1634 E_deshash(newpass, new_lm_hash);
1636 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1637 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1638 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1639 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1640 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1641 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1643 r.in.user_handle = &user_handle;
1644 r.in.lm_present = 1;
1645 /* Break the LM hash */
1646 hash1.hash[0]++;
1647 r.in.old_lm_crypted = &hash1;
1648 r.in.new_lm_crypted = &hash2;
1649 r.in.nt_present = 1;
1650 r.in.old_nt_crypted = &hash3;
1651 r.in.new_nt_crypted = &hash4;
1652 r.in.cross1_present = 1;
1653 r.in.nt_cross = &hash5;
1654 r.in.cross2_present = 1;
1655 r.in.lm_cross = &hash6;
1657 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1658 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1659 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1661 /* Unbreak the LM hash */
1662 hash1.hash[0]--;
1664 r.in.user_handle = &user_handle;
1665 r.in.lm_present = 1;
1666 r.in.old_lm_crypted = &hash1;
1667 r.in.new_lm_crypted = &hash2;
1668 /* Break the NT hash */
1669 hash3.hash[0]--;
1670 r.in.nt_present = 1;
1671 r.in.old_nt_crypted = &hash3;
1672 r.in.new_nt_crypted = &hash4;
1673 r.in.cross1_present = 1;
1674 r.in.nt_cross = &hash5;
1675 r.in.cross2_present = 1;
1676 r.in.lm_cross = &hash6;
1678 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1679 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1680 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1682 /* Unbreak the NT hash */
1683 hash3.hash[0]--;
1685 r.in.user_handle = &user_handle;
1686 r.in.lm_present = 1;
1687 r.in.old_lm_crypted = &hash1;
1688 r.in.new_lm_crypted = &hash2;
1689 r.in.nt_present = 1;
1690 r.in.old_nt_crypted = &hash3;
1691 r.in.new_nt_crypted = &hash4;
1692 r.in.cross1_present = 1;
1693 r.in.nt_cross = &hash5;
1694 r.in.cross2_present = 1;
1695 /* Break the LM cross */
1696 hash6.hash[0]++;
1697 r.in.lm_cross = &hash6;
1699 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1700 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1701 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1702 ret = false;
1705 /* Unbreak the LM cross */
1706 hash6.hash[0]--;
1708 r.in.user_handle = &user_handle;
1709 r.in.lm_present = 1;
1710 r.in.old_lm_crypted = &hash1;
1711 r.in.new_lm_crypted = &hash2;
1712 r.in.nt_present = 1;
1713 r.in.old_nt_crypted = &hash3;
1714 r.in.new_nt_crypted = &hash4;
1715 r.in.cross1_present = 1;
1716 /* Break the NT cross */
1717 hash5.hash[0]++;
1718 r.in.nt_cross = &hash5;
1719 r.in.cross2_present = 1;
1720 r.in.lm_cross = &hash6;
1722 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1723 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1724 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1725 ret = false;
1728 /* Unbreak the NT cross */
1729 hash5.hash[0]--;
1732 /* Reset the hashes to not broken values */
1733 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1734 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1735 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1736 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1737 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1738 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1740 r.in.user_handle = &user_handle;
1741 r.in.lm_present = 1;
1742 r.in.old_lm_crypted = &hash1;
1743 r.in.new_lm_crypted = &hash2;
1744 r.in.nt_present = 1;
1745 r.in.old_nt_crypted = &hash3;
1746 r.in.new_nt_crypted = &hash4;
1747 r.in.cross1_present = 1;
1748 r.in.nt_cross = &hash5;
1749 r.in.cross2_present = 0;
1750 r.in.lm_cross = NULL;
1752 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1753 if (NT_STATUS_IS_OK(status)) {
1754 changed = true;
1755 *password = newpass;
1756 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1757 printf("ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1758 ret = false;
1761 oldpass = newpass;
1762 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1764 E_md4hash(oldpass, old_nt_hash);
1765 E_md4hash(newpass, new_nt_hash);
1766 E_deshash(oldpass, old_lm_hash);
1767 E_deshash(newpass, new_lm_hash);
1770 /* Reset the hashes to not broken values */
1771 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1772 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1773 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1774 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1775 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1776 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1778 r.in.user_handle = &user_handle;
1779 r.in.lm_present = 1;
1780 r.in.old_lm_crypted = &hash1;
1781 r.in.new_lm_crypted = &hash2;
1782 r.in.nt_present = 1;
1783 r.in.old_nt_crypted = &hash3;
1784 r.in.new_nt_crypted = &hash4;
1785 r.in.cross1_present = 0;
1786 r.in.nt_cross = NULL;
1787 r.in.cross2_present = 1;
1788 r.in.lm_cross = &hash6;
1790 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1791 if (NT_STATUS_IS_OK(status)) {
1792 changed = true;
1793 *password = newpass;
1794 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1795 printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1796 ret = false;
1799 oldpass = newpass;
1800 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1802 E_md4hash(oldpass, old_nt_hash);
1803 E_md4hash(newpass, new_nt_hash);
1804 E_deshash(oldpass, old_lm_hash);
1805 E_deshash(newpass, new_lm_hash);
1808 /* Reset the hashes to not broken values */
1809 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1810 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1811 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1812 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1813 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1814 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1816 r.in.user_handle = &user_handle;
1817 r.in.lm_present = 1;
1818 r.in.old_lm_crypted = &hash1;
1819 r.in.new_lm_crypted = &hash2;
1820 r.in.nt_present = 1;
1821 r.in.old_nt_crypted = &hash3;
1822 r.in.new_nt_crypted = &hash4;
1823 r.in.cross1_present = 1;
1824 r.in.nt_cross = &hash5;
1825 r.in.cross2_present = 1;
1826 r.in.lm_cross = &hash6;
1828 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1829 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1830 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1831 } else if (!NT_STATUS_IS_OK(status)) {
1832 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1833 ret = false;
1834 } else {
1835 changed = true;
1836 *password = newpass;
1839 r.in.user_handle = &user_handle;
1840 r.in.lm_present = 1;
1841 r.in.old_lm_crypted = &hash1;
1842 r.in.new_lm_crypted = &hash2;
1843 r.in.nt_present = 1;
1844 r.in.old_nt_crypted = &hash3;
1845 r.in.new_nt_crypted = &hash4;
1846 r.in.cross1_present = 1;
1847 r.in.nt_cross = &hash5;
1848 r.in.cross2_present = 1;
1849 r.in.lm_cross = &hash6;
1851 if (changed) {
1852 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1853 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1854 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1855 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1856 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1857 ret = false;
1862 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1863 ret = false;
1866 return ret;
1870 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1871 const char *acct_name,
1872 struct policy_handle *handle, char **password)
1874 NTSTATUS status;
1875 struct samr_OemChangePasswordUser2 r;
1876 bool ret = true;
1877 struct samr_Password lm_verifier;
1878 struct samr_CryptPassword lm_pass;
1879 struct lsa_AsciiString server, account, account_bad;
1880 char *oldpass;
1881 char *newpass;
1882 uint8_t old_lm_hash[16], new_lm_hash[16];
1884 struct samr_GetDomPwInfo dom_pw_info;
1885 struct samr_PwInfo info;
1886 int policy_min_pw_len = 0;
1888 struct lsa_String domain_name;
1890 domain_name.string = "";
1891 dom_pw_info.in.domain_name = &domain_name;
1892 dom_pw_info.out.info = &info;
1894 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1896 torture_assert(tctx, *password != NULL,
1897 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1899 oldpass = *password;
1901 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1902 if (NT_STATUS_IS_OK(status)) {
1903 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1906 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1908 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1909 account.string = acct_name;
1911 E_deshash(oldpass, old_lm_hash);
1912 E_deshash(newpass, new_lm_hash);
1914 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1915 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1916 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1918 r.in.server = &server;
1919 r.in.account = &account;
1920 r.in.password = &lm_pass;
1921 r.in.hash = &lm_verifier;
1923 /* Break the verification */
1924 lm_verifier.hash[0]++;
1926 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1928 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1929 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1930 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1931 nt_errstr(status));
1932 ret = false;
1935 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1936 /* Break the old password */
1937 old_lm_hash[0]++;
1938 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1939 /* unbreak it for the next operation */
1940 old_lm_hash[0]--;
1941 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1943 r.in.server = &server;
1944 r.in.account = &account;
1945 r.in.password = &lm_pass;
1946 r.in.hash = &lm_verifier;
1948 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1950 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1951 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1952 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1953 nt_errstr(status));
1954 ret = false;
1957 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1958 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1960 r.in.server = &server;
1961 r.in.account = &account;
1962 r.in.password = &lm_pass;
1963 r.in.hash = NULL;
1965 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1967 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1968 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1969 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1970 nt_errstr(status));
1971 ret = false;
1974 /* This shouldn't be a valid name */
1975 account_bad.string = TEST_ACCOUNT_NAME "XX";
1976 r.in.account = &account_bad;
1978 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1980 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1981 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1982 nt_errstr(status));
1983 ret = false;
1986 /* This shouldn't be a valid name */
1987 account_bad.string = TEST_ACCOUNT_NAME "XX";
1988 r.in.account = &account_bad;
1989 r.in.password = &lm_pass;
1990 r.in.hash = &lm_verifier;
1992 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1994 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1995 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1996 nt_errstr(status));
1997 ret = false;
2000 /* This shouldn't be a valid name */
2001 account_bad.string = TEST_ACCOUNT_NAME "XX";
2002 r.in.account = &account_bad;
2003 r.in.password = NULL;
2004 r.in.hash = &lm_verifier;
2006 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2008 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
2009 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2010 nt_errstr(status));
2011 ret = false;
2014 E_deshash(oldpass, old_lm_hash);
2015 E_deshash(newpass, new_lm_hash);
2017 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2018 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2019 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2021 r.in.server = &server;
2022 r.in.account = &account;
2023 r.in.password = &lm_pass;
2024 r.in.hash = &lm_verifier;
2026 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2027 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2028 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2029 } else if (!NT_STATUS_IS_OK(status)) {
2030 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
2031 ret = false;
2032 } else {
2033 *password = newpass;
2036 return ret;
2040 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2041 const char *acct_name,
2042 char **password,
2043 char *newpass, bool allow_password_restriction)
2045 NTSTATUS status;
2046 struct samr_ChangePasswordUser2 r;
2047 bool ret = true;
2048 struct lsa_String server, account;
2049 struct samr_CryptPassword nt_pass, lm_pass;
2050 struct samr_Password nt_verifier, lm_verifier;
2051 char *oldpass;
2052 uint8_t old_nt_hash[16], new_nt_hash[16];
2053 uint8_t old_lm_hash[16], new_lm_hash[16];
2055 struct samr_GetDomPwInfo dom_pw_info;
2056 struct samr_PwInfo info;
2058 struct lsa_String domain_name;
2060 domain_name.string = "";
2061 dom_pw_info.in.domain_name = &domain_name;
2062 dom_pw_info.out.info = &info;
2064 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2066 torture_assert(tctx, *password != NULL,
2067 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2068 oldpass = *password;
2070 if (!newpass) {
2071 int policy_min_pw_len = 0;
2072 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
2073 if (NT_STATUS_IS_OK(status)) {
2074 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2077 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2080 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2081 init_lsa_String(&account, acct_name);
2083 E_md4hash(oldpass, old_nt_hash);
2084 E_md4hash(newpass, new_nt_hash);
2086 E_deshash(oldpass, old_lm_hash);
2087 E_deshash(newpass, new_lm_hash);
2089 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2090 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2091 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2093 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2094 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2095 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2097 r.in.server = &server;
2098 r.in.account = &account;
2099 r.in.nt_password = &nt_pass;
2100 r.in.nt_verifier = &nt_verifier;
2101 r.in.lm_change = 1;
2102 r.in.lm_password = &lm_pass;
2103 r.in.lm_verifier = &lm_verifier;
2105 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
2106 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2107 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2108 } else if (!NT_STATUS_IS_OK(status)) {
2109 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2110 ret = false;
2111 } else {
2112 *password = newpass;
2115 return ret;
2119 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2120 const char *account_string,
2121 int policy_min_pw_len,
2122 char **password,
2123 const char *newpass,
2124 NTTIME last_password_change,
2125 bool handle_reject_reason)
2127 NTSTATUS status;
2128 struct samr_ChangePasswordUser3 r;
2129 bool ret = true;
2130 struct lsa_String server, account, account_bad;
2131 struct samr_CryptPassword nt_pass, lm_pass;
2132 struct samr_Password nt_verifier, lm_verifier;
2133 char *oldpass;
2134 uint8_t old_nt_hash[16], new_nt_hash[16];
2135 uint8_t old_lm_hash[16], new_lm_hash[16];
2136 NTTIME t;
2137 struct samr_DomInfo1 *dominfo = NULL;
2138 struct samr_ChangeReject *reject = NULL;
2140 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2142 if (newpass == NULL) {
2143 do {
2144 if (policy_min_pw_len == 0) {
2145 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2146 } else {
2147 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2149 } while (check_password_quality(newpass) == false);
2150 } else {
2151 torture_comment(tctx, "Using password '%s'\n", newpass);
2154 torture_assert(tctx, *password != NULL,
2155 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2157 oldpass = *password;
2158 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2159 init_lsa_String(&account, account_string);
2161 E_md4hash(oldpass, old_nt_hash);
2162 E_md4hash(newpass, new_nt_hash);
2164 E_deshash(oldpass, old_lm_hash);
2165 E_deshash(newpass, new_lm_hash);
2167 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2168 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2169 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2171 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2172 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2173 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2175 /* Break the verification */
2176 nt_verifier.hash[0]++;
2178 r.in.server = &server;
2179 r.in.account = &account;
2180 r.in.nt_password = &nt_pass;
2181 r.in.nt_verifier = &nt_verifier;
2182 r.in.lm_change = 1;
2183 r.in.lm_password = &lm_pass;
2184 r.in.lm_verifier = &lm_verifier;
2185 r.in.password3 = NULL;
2186 r.out.dominfo = &dominfo;
2187 r.out.reject = &reject;
2189 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2190 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2191 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2192 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2193 nt_errstr(status));
2194 ret = false;
2197 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2198 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2199 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2201 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2202 /* Break the NT hash */
2203 old_nt_hash[0]++;
2204 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2205 /* Unbreak it again */
2206 old_nt_hash[0]--;
2207 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2209 r.in.server = &server;
2210 r.in.account = &account;
2211 r.in.nt_password = &nt_pass;
2212 r.in.nt_verifier = &nt_verifier;
2213 r.in.lm_change = 1;
2214 r.in.lm_password = &lm_pass;
2215 r.in.lm_verifier = &lm_verifier;
2216 r.in.password3 = NULL;
2217 r.out.dominfo = &dominfo;
2218 r.out.reject = &reject;
2220 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2221 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2222 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2223 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2224 nt_errstr(status));
2225 ret = false;
2228 /* This shouldn't be a valid name */
2229 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2231 r.in.account = &account_bad;
2232 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2233 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2234 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2235 nt_errstr(status));
2236 ret = false;
2239 E_md4hash(oldpass, old_nt_hash);
2240 E_md4hash(newpass, new_nt_hash);
2242 E_deshash(oldpass, old_lm_hash);
2243 E_deshash(newpass, new_lm_hash);
2245 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2246 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2247 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2249 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2250 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2251 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2253 r.in.server = &server;
2254 r.in.account = &account;
2255 r.in.nt_password = &nt_pass;
2256 r.in.nt_verifier = &nt_verifier;
2257 r.in.lm_change = 1;
2258 r.in.lm_password = &lm_pass;
2259 r.in.lm_verifier = &lm_verifier;
2260 r.in.password3 = NULL;
2261 r.out.dominfo = &dominfo;
2262 r.out.reject = &reject;
2264 unix_to_nt_time(&t, time(NULL));
2266 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2268 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2269 && dominfo
2270 && reject
2271 && handle_reject_reason
2272 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2273 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2275 if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
2276 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2277 SAMR_REJECT_OTHER, reject->reason);
2278 return false;
2282 /* We tested the order of precendence which is as follows:
2284 * pwd min_age
2285 * pwd length
2286 * pwd complexity
2287 * pwd history
2289 Guenther */
2291 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2292 (last_password_change + dominfo->min_password_age > t)) {
2294 if (reject->reason != SAMR_REJECT_OTHER) {
2295 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2296 SAMR_REJECT_OTHER, reject->reason);
2297 return false;
2300 } else if ((dominfo->min_password_length > 0) &&
2301 (strlen(newpass) < dominfo->min_password_length)) {
2303 if (reject->reason != SAMR_REJECT_TOO_SHORT) {
2304 printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
2305 SAMR_REJECT_TOO_SHORT, reject->reason);
2306 return false;
2309 } else if ((dominfo->password_history_length > 0) &&
2310 strequal(oldpass, newpass)) {
2312 if (reject->reason != SAMR_REJECT_IN_HISTORY) {
2313 printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
2314 SAMR_REJECT_IN_HISTORY, reject->reason);
2315 return false;
2317 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2319 if (reject->reason != SAMR_REJECT_COMPLEXITY) {
2320 printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
2321 SAMR_REJECT_COMPLEXITY, reject->reason);
2322 return false;
2327 if (reject->reason == SAMR_REJECT_TOO_SHORT) {
2328 /* retry with adjusted size */
2329 return test_ChangePasswordUser3(p, tctx, account_string,
2330 dominfo->min_password_length,
2331 password, NULL, 0, false);
2335 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2336 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2337 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2338 SAMR_REJECT_OTHER, reject->reason);
2339 return false;
2341 /* Perhaps the server has a 'min password age' set? */
2343 } else {
2344 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2345 *password = talloc_strdup(tctx, newpass);
2348 return ret;
2351 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2352 const char *account_string,
2353 struct policy_handle *handle,
2354 char **password)
2356 NTSTATUS status;
2357 struct samr_ChangePasswordUser3 r;
2358 struct samr_SetUserInfo s;
2359 union samr_UserInfo u;
2360 DATA_BLOB session_key;
2361 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2362 uint8_t confounder[16];
2363 struct MD5Context ctx;
2365 bool ret = true;
2366 struct lsa_String server, account;
2367 struct samr_CryptPassword nt_pass;
2368 struct samr_Password nt_verifier;
2369 DATA_BLOB new_random_pass;
2370 char *newpass;
2371 char *oldpass;
2372 uint8_t old_nt_hash[16], new_nt_hash[16];
2373 NTTIME t;
2374 struct samr_DomInfo1 *dominfo = NULL;
2375 struct samr_ChangeReject *reject = NULL;
2377 new_random_pass = samr_very_rand_pass(tctx, 128);
2379 torture_assert(tctx, *password != NULL,
2380 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2382 oldpass = *password;
2383 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2384 init_lsa_String(&account, account_string);
2386 s.in.user_handle = handle;
2387 s.in.info = &u;
2388 s.in.level = 25;
2390 ZERO_STRUCT(u);
2392 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2394 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2396 status = dcerpc_fetch_session_key(p, &session_key);
2397 if (!NT_STATUS_IS_OK(status)) {
2398 printf("SetUserInfo level %u - no session key - %s\n",
2399 s.in.level, nt_errstr(status));
2400 return false;
2403 generate_random_buffer((uint8_t *)confounder, 16);
2405 MD5Init(&ctx);
2406 MD5Update(&ctx, confounder, 16);
2407 MD5Update(&ctx, session_key.data, session_key.length);
2408 MD5Final(confounded_session_key.data, &ctx);
2410 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2411 memcpy(&u.info25.password.data[516], confounder, 16);
2413 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2415 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2416 if (!NT_STATUS_IS_OK(status)) {
2417 printf("SetUserInfo level %u failed - %s\n",
2418 s.in.level, nt_errstr(status));
2419 ret = false;
2422 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2424 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2426 new_random_pass = samr_very_rand_pass(tctx, 128);
2428 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2430 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2431 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2432 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2434 r.in.server = &server;
2435 r.in.account = &account;
2436 r.in.nt_password = &nt_pass;
2437 r.in.nt_verifier = &nt_verifier;
2438 r.in.lm_change = 0;
2439 r.in.lm_password = NULL;
2440 r.in.lm_verifier = NULL;
2441 r.in.password3 = NULL;
2442 r.out.dominfo = &dominfo;
2443 r.out.reject = &reject;
2445 unix_to_nt_time(&t, time(NULL));
2447 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2449 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2450 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2451 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2452 SAMR_REJECT_OTHER, reject->reason);
2453 return false;
2455 /* Perhaps the server has a 'min password age' set? */
2457 } else if (!NT_STATUS_IS_OK(status)) {
2458 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2459 ret = false;
2462 newpass = samr_rand_pass(tctx, 128);
2464 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2466 E_md4hash(newpass, new_nt_hash);
2468 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2469 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2470 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2472 r.in.server = &server;
2473 r.in.account = &account;
2474 r.in.nt_password = &nt_pass;
2475 r.in.nt_verifier = &nt_verifier;
2476 r.in.lm_change = 0;
2477 r.in.lm_password = NULL;
2478 r.in.lm_verifier = NULL;
2479 r.in.password3 = NULL;
2480 r.out.dominfo = &dominfo;
2481 r.out.reject = &reject;
2483 unix_to_nt_time(&t, time(NULL));
2485 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2487 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2488 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2489 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2490 SAMR_REJECT_OTHER, reject->reason);
2491 return false;
2493 /* Perhaps the server has a 'min password age' set? */
2495 } else {
2496 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2497 *password = talloc_strdup(tctx, newpass);
2500 return ret;
2504 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2505 struct policy_handle *alias_handle)
2507 struct samr_GetMembersInAlias r;
2508 struct lsa_SidArray sids;
2509 NTSTATUS status;
2511 torture_comment(tctx, "Testing GetMembersInAlias\n");
2513 r.in.alias_handle = alias_handle;
2514 r.out.sids = &sids;
2516 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2517 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2519 return true;
2522 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2523 struct policy_handle *alias_handle,
2524 const struct dom_sid *domain_sid)
2526 struct samr_AddAliasMember r;
2527 struct samr_DeleteAliasMember d;
2528 NTSTATUS status;
2529 struct dom_sid *sid;
2531 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2533 torture_comment(tctx, "testing AddAliasMember\n");
2534 r.in.alias_handle = alias_handle;
2535 r.in.sid = sid;
2537 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2538 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2540 d.in.alias_handle = alias_handle;
2541 d.in.sid = sid;
2543 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2544 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2546 return true;
2549 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2550 struct policy_handle *alias_handle)
2552 struct samr_AddMultipleMembersToAlias a;
2553 struct samr_RemoveMultipleMembersFromAlias r;
2554 NTSTATUS status;
2555 struct lsa_SidArray sids;
2557 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2558 a.in.alias_handle = alias_handle;
2559 a.in.sids = &sids;
2561 sids.num_sids = 3;
2562 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2564 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2565 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2566 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2568 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2569 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2572 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2573 r.in.alias_handle = alias_handle;
2574 r.in.sids = &sids;
2576 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2577 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2579 /* strange! removing twice doesn't give any error */
2580 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2581 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2583 /* but removing an alias that isn't there does */
2584 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2586 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2587 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2589 return true;
2592 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2593 struct policy_handle *user_handle)
2595 struct samr_TestPrivateFunctionsUser r;
2596 NTSTATUS status;
2598 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2600 r.in.user_handle = user_handle;
2602 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2603 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2605 return true;
2608 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2609 struct torture_context *tctx,
2610 struct policy_handle *handle,
2611 bool use_info2,
2612 NTTIME *pwdlastset)
2614 NTSTATUS status;
2615 uint16_t levels[] = { /* 3, */ 5, 21 };
2616 int i;
2617 NTTIME pwdlastset3 = 0;
2618 NTTIME pwdlastset5 = 0;
2619 NTTIME pwdlastset21 = 0;
2621 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2622 use_info2 ? "2":"");
2624 for (i=0; i<ARRAY_SIZE(levels); i++) {
2626 struct samr_QueryUserInfo r;
2627 struct samr_QueryUserInfo2 r2;
2628 union samr_UserInfo *info;
2630 if (use_info2) {
2631 r2.in.user_handle = handle;
2632 r2.in.level = levels[i];
2633 r2.out.info = &info;
2634 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2636 } else {
2637 r.in.user_handle = handle;
2638 r.in.level = levels[i];
2639 r.out.info = &info;
2640 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2643 if (!NT_STATUS_IS_OK(status) &&
2644 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2645 printf("QueryUserInfo%s level %u failed - %s\n",
2646 use_info2 ? "2":"", levels[i], nt_errstr(status));
2647 return false;
2650 switch (levels[i]) {
2651 case 3:
2652 pwdlastset3 = info->info3.last_password_change;
2653 break;
2654 case 5:
2655 pwdlastset5 = info->info5.last_password_change;
2656 break;
2657 case 21:
2658 pwdlastset21 = info->info21.last_password_change;
2659 break;
2660 default:
2661 return false;
2664 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2665 "pwdlastset mixup"); */
2666 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2667 "pwdlastset mixup");
2669 *pwdlastset = pwdlastset21;
2671 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2673 return true;
2676 static bool test_SamLogon(struct torture_context *tctx,
2677 struct dcerpc_pipe *p,
2678 struct cli_credentials *test_credentials,
2679 NTSTATUS expected_result)
2681 NTSTATUS status;
2682 struct netr_LogonSamLogonEx r;
2683 union netr_LogonLevel logon;
2684 union netr_Validation validation;
2685 uint8_t authoritative;
2686 struct netr_NetworkInfo ninfo;
2687 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2688 int flags = CLI_CRED_NTLM_AUTH;
2689 uint32_t samlogon_flags = 0;
2691 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2692 flags |= CLI_CRED_LANMAN_AUTH;
2695 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2696 flags |= CLI_CRED_NTLMv2_AUTH;
2699 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2700 &ninfo.identity_info.account_name.string,
2701 &ninfo.identity_info.domain_name.string);
2703 generate_random_buffer(ninfo.challenge,
2704 sizeof(ninfo.challenge));
2705 chal = data_blob_const(ninfo.challenge,
2706 sizeof(ninfo.challenge));
2708 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2709 cli_credentials_get_domain(test_credentials));
2711 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2712 &flags,
2713 chal,
2714 names_blob,
2715 &lm_resp, &nt_resp,
2716 NULL, NULL);
2717 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2719 ninfo.lm.data = lm_resp.data;
2720 ninfo.lm.length = lm_resp.length;
2722 ninfo.nt.data = nt_resp.data;
2723 ninfo.nt.length = nt_resp.length;
2725 ninfo.identity_info.parameter_control =
2726 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2727 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2728 ninfo.identity_info.logon_id_low = 0;
2729 ninfo.identity_info.logon_id_high = 0;
2730 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(test_credentials);
2732 logon.network = &ninfo;
2734 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2735 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2736 r.in.logon_level = NetlogonNetworkInformation;
2737 r.in.logon = &logon;
2738 r.in.flags = &samlogon_flags;
2739 r.out.flags = &samlogon_flags;
2740 r.out.validation = &validation;
2741 r.out.authoritative = &authoritative;
2743 d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
2745 r.in.validation_level = 6;
2747 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2748 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2749 r.in.validation_level = 3;
2750 status = dcerpc_netr_LogonSamLogonEx(p, tctx, &r);
2752 if (!NT_STATUS_IS_OK(status)) {
2753 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed");
2754 return true;
2755 } else {
2756 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogonEx failed");
2759 return true;
2762 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2763 struct dcerpc_pipe *p,
2764 struct cli_credentials *machine_creds,
2765 const char *acct_name,
2766 char *password,
2767 NTSTATUS expected_samlogon_result)
2769 bool ret = true;
2770 struct cli_credentials *test_credentials;
2772 test_credentials = cli_credentials_init(tctx);
2774 cli_credentials_set_workstation(test_credentials,
2775 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2776 cli_credentials_set_domain(test_credentials,
2777 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2778 cli_credentials_set_username(test_credentials,
2779 acct_name, CRED_SPECIFIED);
2780 cli_credentials_set_password(test_credentials,
2781 password, CRED_SPECIFIED);
2783 printf("testing samlogon as %s password: %s\n",
2784 acct_name, password);
2786 if (!test_SamLogon(tctx, p, test_credentials,
2787 expected_samlogon_result)) {
2788 torture_warning(tctx, "new password did not work\n");
2789 ret = false;
2792 return ret;
2795 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2796 struct dcerpc_pipe *np,
2797 struct torture_context *tctx,
2798 struct policy_handle *handle,
2799 uint16_t level,
2800 uint32_t fields_present,
2801 uint8_t password_expired,
2802 bool *matched_expected_error,
2803 bool use_setinfo2,
2804 const char *acct_name,
2805 char **password,
2806 struct cli_credentials *machine_creds,
2807 bool use_queryinfo2,
2808 NTTIME *pwdlastset,
2809 NTSTATUS expected_samlogon_result)
2811 const char *fields = NULL;
2812 bool ret = true;
2814 switch (level) {
2815 case 21:
2816 case 23:
2817 case 25:
2818 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2819 fields_present);
2820 break;
2821 default:
2822 break;
2825 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2826 "(password_expired: %d) %s\n",
2827 use_setinfo2 ? "2":"", level, password_expired,
2828 fields ? fields : "");
2830 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2831 fields_present,
2832 password,
2833 password_expired,
2834 use_setinfo2,
2835 matched_expected_error)) {
2836 ret = false;
2839 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2840 use_queryinfo2,
2841 pwdlastset)) {
2842 ret = false;
2845 if (*matched_expected_error == true) {
2846 return ret;
2849 if (!test_SamLogon_with_creds(tctx, np,
2850 machine_creds,
2851 acct_name,
2852 *password,
2853 expected_samlogon_result)) {
2854 ret = false;
2857 return ret;
2860 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2861 struct torture_context *tctx,
2862 uint32_t acct_flags,
2863 const char *acct_name,
2864 struct policy_handle *handle,
2865 char **password,
2866 struct cli_credentials *machine_credentials)
2868 int s = 0, q = 0, f = 0, l = 0, z = 0;
2869 struct dcerpc_binding *b;
2870 bool ret = true;
2871 int delay = 50000;
2872 bool set_levels[] = { false, true };
2873 bool query_levels[] = { false, true };
2874 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
2875 uint32_t nonzeros[] = { 1, 24 };
2876 uint32_t fields_present[] = {
2878 SAMR_FIELD_EXPIRED_FLAG,
2879 SAMR_FIELD_LAST_PWD_CHANGE,
2880 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2881 SAMR_FIELD_COMMENT,
2882 SAMR_FIELD_NT_PASSWORD_PRESENT,
2883 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2884 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2885 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2886 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2887 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2888 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2890 NTSTATUS status;
2891 struct dcerpc_pipe *np = NULL;
2893 if (torture_setting_bool(tctx, "samba3", false)) {
2894 delay = 999999;
2895 printf("Samba3 has second granularity, setting delay to: %d\n",
2896 delay);
2899 status = torture_rpc_binding(tctx, &b);
2900 if (!NT_STATUS_IS_OK(status)) {
2901 ret = false;
2902 return ret;
2905 /* We have to use schannel, otherwise the SamLogonEx fails
2906 * with INTERNAL_ERROR */
2908 b->flags &= ~DCERPC_AUTH_OPTIONS;
2909 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
2911 status = dcerpc_pipe_connect_b(tctx, &np, b,
2912 &ndr_table_netlogon,
2913 machine_credentials, tctx->ev, tctx->lp_ctx);
2915 if (!NT_STATUS_IS_OK(status)) {
2916 d_printf("RPC pipe connect as domain member failed: %s\n", nt_errstr(status));
2917 ret = false;
2918 return ret;
2921 /* set to 1 to enable testing for all possible opcode
2922 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2923 combinations */
2924 #if 0
2925 #define TEST_ALL_LEVELS 1
2926 #define TEST_SET_LEVELS 1
2927 #define TEST_QUERY_LEVELS 1
2928 #endif
2929 #ifdef TEST_ALL_LEVELS
2930 for (l=0; l<ARRAY_SIZE(levels); l++) {
2931 #else
2932 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
2933 #endif
2934 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
2935 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2936 #ifdef TEST_SET_LEVELS
2937 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2938 #endif
2939 #ifdef TEST_QUERY_LEVELS
2940 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2941 #endif
2942 NTTIME pwdlastset_old = 0;
2943 NTTIME pwdlastset_new = 0;
2944 bool matched_expected_error = false;
2945 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
2947 torture_comment(tctx, "------------------------------\n"
2948 "Testing pwdLastSet attribute for flags: 0x%08x "
2949 "(s: %d (l: %d), q: %d)\n",
2950 acct_flags, s, levels[l], q);
2952 switch (levels[l]) {
2953 case 21:
2954 case 23:
2955 case 25:
2956 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2957 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
2958 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
2960 break;
2964 /* set #1 */
2966 /* set a password and force password change (pwdlastset 0) by
2967 * setting the password expired flag to a non-0 value */
2969 if (!test_SetPassword_level(p, np, tctx, handle,
2970 levels[l],
2971 fields_present[f],
2972 nonzeros[z],
2973 &matched_expected_error,
2974 set_levels[s],
2975 acct_name,
2976 password,
2977 machine_credentials,
2978 query_levels[q],
2979 &pwdlastset_old,
2980 expected_samlogon_result)) {
2981 ret = false;
2984 if (matched_expected_error == true) {
2985 /* skipping on expected failure */
2986 continue;
2989 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2990 * set without the SAMR_FIELD_EXPIRED_FLAG */
2992 switch (levels[l]) {
2993 case 21:
2994 case 23:
2995 case 25:
2996 if ((pwdlastset_new != 0) &&
2997 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
2998 torture_comment(tctx, "not considering a non-0 "
2999 "pwdLastSet as a an error as the "
3000 "SAMR_FIELD_EXPIRED_FLAG has not "
3001 "been set\n");
3002 break;
3004 default:
3005 if (pwdlastset_new != 0) {
3006 torture_warning(tctx, "pwdLastSet test failed: "
3007 "expected pwdLastSet 0 but got %lld\n",
3008 pwdlastset_old);
3009 ret = false;
3011 break;
3014 switch (levels[l]) {
3015 case 21:
3016 case 23:
3017 case 25:
3018 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3019 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3020 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3021 (pwdlastset_old >= pwdlastset_new)) {
3022 torture_warning(tctx, "pwdlastset not increasing\n");
3023 ret = false;
3025 break;
3026 default:
3027 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3028 (pwdlastset_old >= pwdlastset_new)) {
3029 torture_warning(tctx, "pwdlastset not increasing\n");
3030 ret = false;
3032 break;
3035 usleep(delay);
3037 /* set #2 */
3039 /* set a password, pwdlastset needs to get updated (increased
3040 * value), password_expired value used here is 0 */
3042 if (!test_SetPassword_level(p, np, tctx, handle,
3043 levels[l],
3044 fields_present[f],
3046 &matched_expected_error,
3047 set_levels[s],
3048 acct_name,
3049 password,
3050 machine_credentials,
3051 query_levels[q],
3052 &pwdlastset_new,
3053 expected_samlogon_result)) {
3054 ret = false;
3057 /* when a password has been changed, pwdlastset must not be 0 afterwards
3058 * and must be larger then the old value */
3060 switch (levels[l]) {
3061 case 21:
3062 case 23:
3063 case 25:
3065 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3066 * password has been changed, old and new pwdlastset
3067 * need to be the same value */
3069 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3070 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3071 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3073 torture_assert_int_equal(tctx, pwdlastset_old,
3074 pwdlastset_new, "pwdlastset must be equal");
3075 break;
3077 default:
3078 if (pwdlastset_old >= pwdlastset_new) {
3079 torture_warning(tctx, "pwdLastSet test failed: "
3080 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3081 pwdlastset_old, pwdlastset_new);
3082 ret = false;
3084 if (pwdlastset_new == 0) {
3085 torture_warning(tctx, "pwdLastSet test failed: "
3086 "expected non-0 pwdlastset, got: %lld\n",
3087 pwdlastset_new);
3088 ret = false;
3092 switch (levels[l]) {
3093 case 21:
3094 case 23:
3095 case 25:
3096 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3097 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3098 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3099 (pwdlastset_old >= pwdlastset_new)) {
3100 torture_warning(tctx, "pwdlastset not increasing\n");
3101 ret = false;
3103 break;
3104 default:
3105 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3106 (pwdlastset_old >= pwdlastset_new)) {
3107 torture_warning(tctx, "pwdlastset not increasing\n");
3108 ret = false;
3110 break;
3113 pwdlastset_old = pwdlastset_new;
3115 usleep(delay);
3117 /* set #2b */
3119 /* set a password, pwdlastset needs to get updated (increased
3120 * value), password_expired value used here is 0 */
3122 if (!test_SetPassword_level(p, np, tctx, handle,
3123 levels[l],
3124 fields_present[f],
3126 &matched_expected_error,
3127 set_levels[s],
3128 acct_name,
3129 password,
3130 machine_credentials,
3131 query_levels[q],
3132 &pwdlastset_new,
3133 expected_samlogon_result)) {
3134 ret = false;
3137 /* when a password has been changed, pwdlastset must not be 0 afterwards
3138 * and must be larger then the old value */
3140 switch (levels[l]) {
3141 case 21:
3142 case 23:
3143 case 25:
3145 /* if no password has been changed, old and new pwdlastset
3146 * need to be the same value */
3148 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3149 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3151 torture_assert_int_equal(tctx, pwdlastset_old,
3152 pwdlastset_new, "pwdlastset must be equal");
3153 break;
3155 default:
3156 if (pwdlastset_old >= pwdlastset_new) {
3157 torture_warning(tctx, "pwdLastSet test failed: "
3158 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3159 pwdlastset_old, pwdlastset_new);
3160 ret = false;
3162 if (pwdlastset_new == 0) {
3163 torture_warning(tctx, "pwdLastSet test failed: "
3164 "expected non-0 pwdlastset, got: %lld\n",
3165 pwdlastset_new);
3166 ret = false;
3170 /* set #3 */
3172 /* set a password and force password change (pwdlastset 0) by
3173 * setting the password expired flag to a non-0 value */
3175 if (!test_SetPassword_level(p, np, tctx, handle,
3176 levels[l],
3177 fields_present[f],
3178 nonzeros[z],
3179 &matched_expected_error,
3180 set_levels[s],
3181 acct_name,
3182 password,
3183 machine_credentials,
3184 query_levels[q],
3185 &pwdlastset_new,
3186 expected_samlogon_result)) {
3187 ret = false;
3190 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3191 * set without the SAMR_FIELD_EXPIRED_FLAG */
3193 switch (levels[l]) {
3194 case 21:
3195 case 23:
3196 case 25:
3197 if ((pwdlastset_new != 0) &&
3198 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3199 torture_comment(tctx, "not considering a non-0 "
3200 "pwdLastSet as a an error as the "
3201 "SAMR_FIELD_EXPIRED_FLAG has not "
3202 "been set\n");
3203 break;
3206 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3207 * password has been changed, old and new pwdlastset
3208 * need to be the same value */
3210 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3211 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3212 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3214 torture_assert_int_equal(tctx, pwdlastset_old,
3215 pwdlastset_new, "pwdlastset must be equal");
3216 break;
3218 default:
3220 if (pwdlastset_old == pwdlastset_new) {
3221 torture_warning(tctx, "pwdLastSet test failed: "
3222 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3223 pwdlastset_old, pwdlastset_new);
3224 ret = false;
3227 if (pwdlastset_new != 0) {
3228 torture_warning(tctx, "pwdLastSet test failed: "
3229 "expected pwdLastSet 0, got %lld\n",
3230 pwdlastset_old);
3231 ret = false;
3233 break;
3236 switch (levels[l]) {
3237 case 21:
3238 case 23:
3239 case 25:
3240 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3241 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3242 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3243 (pwdlastset_old >= pwdlastset_new)) {
3244 torture_warning(tctx, "pwdlastset not increasing\n");
3245 ret = false;
3247 break;
3248 default:
3249 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3250 (pwdlastset_old >= pwdlastset_new)) {
3251 torture_warning(tctx, "pwdlastset not increasing\n");
3252 ret = false;
3254 break;
3257 /* if the level we are testing does not have a fields_present
3258 * field, skip all fields present tests by setting f to to
3259 * arraysize */
3260 switch (levels[l]) {
3261 case 18:
3262 case 24:
3263 case 26:
3264 f = ARRAY_SIZE(fields_present);
3265 break;
3268 #ifdef TEST_QUERY_LEVELS
3270 #endif
3271 #ifdef TEST_SET_LEVELS
3273 #endif
3274 } /* fields present */
3275 } /* nonzeros */
3276 } /* levels */
3278 #undef TEST_SET_LEVELS
3279 #undef TEST_QUERY_LEVELS
3281 return ret;
3284 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
3285 struct dcerpc_pipe *lp,
3286 struct torture_context *tctx,
3287 struct policy_handle *domain_handle,
3288 struct policy_handle *lsa_handle,
3289 struct policy_handle *user_handle,
3290 const struct dom_sid *domain_sid,
3291 uint32_t rid,
3292 struct cli_credentials *machine_credentials)
3294 NTSTATUS status;
3295 bool ret = true;
3297 struct policy_handle lsa_acct_handle;
3298 struct dom_sid *user_sid;
3300 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
3303 struct lsa_EnumAccountRights r;
3304 struct lsa_RightSet rights;
3306 printf("Testing LSA EnumAccountRights\n");
3308 r.in.handle = lsa_handle;
3309 r.in.sid = user_sid;
3310 r.out.rights = &rights;
3312 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3313 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3314 "Expected enum rights for account to fail");
3318 struct lsa_RightSet rights;
3319 struct lsa_StringLarge names[2];
3320 struct lsa_AddAccountRights r;
3322 printf("Testing LSA AddAccountRights\n");
3324 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
3325 init_lsa_StringLarge(&names[1], NULL);
3327 rights.count = 1;
3328 rights.names = names;
3330 r.in.handle = lsa_handle;
3331 r.in.sid = user_sid;
3332 r.in.rights = &rights;
3334 status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
3335 torture_assert_ntstatus_ok(tctx, status,
3336 "Failed to add privileges");
3340 struct lsa_EnumAccounts r;
3341 uint32_t resume_handle = 0;
3342 struct lsa_SidArray lsa_sid_array;
3343 int i;
3344 bool found_sid = false;
3346 printf("Testing LSA EnumAccounts\n");
3348 r.in.handle = lsa_handle;
3349 r.in.num_entries = 0x1000;
3350 r.in.resume_handle = &resume_handle;
3351 r.out.sids = &lsa_sid_array;
3352 r.out.resume_handle = &resume_handle;
3354 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3355 torture_assert_ntstatus_ok(tctx, status,
3356 "Failed to enum accounts");
3358 for (i=0; i < lsa_sid_array.num_sids; i++) {
3359 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3360 found_sid = true;
3364 torture_assert(tctx, found_sid,
3365 "failed to list privileged account");
3369 struct lsa_EnumAccountRights r;
3370 struct lsa_RightSet user_rights;
3372 printf("Testing LSA EnumAccountRights\n");
3374 r.in.handle = lsa_handle;
3375 r.in.sid = user_sid;
3376 r.out.rights = &user_rights;
3378 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3379 torture_assert_ntstatus_ok(tctx, status,
3380 "Failed to enum rights for account");
3382 if (user_rights.count < 1) {
3383 torture_warning(tctx, "failed to find newly added rights");
3384 return false;
3389 struct lsa_OpenAccount r;
3391 printf("Testing LSA OpenAccount\n");
3393 r.in.handle = lsa_handle;
3394 r.in.sid = user_sid;
3395 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3396 r.out.acct_handle = &lsa_acct_handle;
3398 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
3399 torture_assert_ntstatus_ok(tctx, status,
3400 "Failed to open lsa account");
3404 struct lsa_GetSystemAccessAccount r;
3405 uint32_t access_mask;
3407 printf("Testing LSA GetSystemAccessAccount\n");
3409 r.in.handle = &lsa_acct_handle;
3410 r.out.access_mask = &access_mask;
3412 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
3413 torture_assert_ntstatus_ok(tctx, status,
3414 "Failed to get lsa system access account");
3418 struct lsa_Close r;
3420 printf("Testing LSA Close\n");
3422 r.in.handle = &lsa_acct_handle;
3423 r.out.handle = &lsa_acct_handle;
3425 status = dcerpc_lsa_Close(lp, tctx, &r);
3426 torture_assert_ntstatus_ok(tctx, status,
3427 "Failed to close lsa");
3431 struct samr_DeleteUser r;
3433 printf("Testing SAMR DeleteUser\n");
3435 r.in.user_handle = user_handle;
3436 r.out.user_handle = user_handle;
3438 status = dcerpc_samr_DeleteUser(p, tctx, &r);
3439 torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
3443 struct lsa_EnumAccounts r;
3444 uint32_t resume_handle = 0;
3445 struct lsa_SidArray lsa_sid_array;
3446 int i;
3447 bool found_sid = false;
3449 printf("Testing LSA EnumAccounts\n");
3451 r.in.handle = lsa_handle;
3452 r.in.num_entries = 0x1000;
3453 r.in.resume_handle = &resume_handle;
3454 r.out.sids = &lsa_sid_array;
3455 r.out.resume_handle = &resume_handle;
3457 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3458 torture_assert_ntstatus_ok(tctx, status,
3459 "Failed to enum accounts");
3461 for (i=0; i < lsa_sid_array.num_sids; i++) {
3462 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3463 found_sid = true;
3467 torture_assert(tctx, found_sid,
3468 "failed to list privileged account");
3472 struct lsa_EnumAccountRights r;
3473 struct lsa_RightSet user_rights;
3475 printf("Testing LSA EnumAccountRights\n");
3477 r.in.handle = lsa_handle;
3478 r.in.sid = user_sid;
3479 r.out.rights = &user_rights;
3481 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3482 torture_assert_ntstatus_ok(tctx, status,
3483 "Failed to enum rights for account");
3485 if (user_rights.count < 1) {
3486 torture_warning(tctx, "failed to find newly added rights");
3487 return false;
3492 struct lsa_OpenAccount r;
3494 printf("Testing LSA OpenAccount\n");
3496 r.in.handle = lsa_handle;
3497 r.in.sid = user_sid;
3498 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3499 r.out.acct_handle = &lsa_acct_handle;
3501 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
3502 torture_assert_ntstatus_ok(tctx, status,
3503 "Failed to open lsa account");
3507 struct lsa_GetSystemAccessAccount r;
3508 uint32_t access_mask;
3510 printf("Testing LSA GetSystemAccessAccount\n");
3512 r.in.handle = &lsa_acct_handle;
3513 r.out.access_mask = &access_mask;
3515 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
3516 torture_assert_ntstatus_ok(tctx, status,
3517 "Failed to get lsa system access account");
3521 struct lsa_DeleteObject r;
3523 printf("Testing LSA DeleteObject\n");
3525 r.in.handle = &lsa_acct_handle;
3526 r.out.handle = &lsa_acct_handle;
3528 status = dcerpc_lsa_DeleteObject(lp, tctx, &r);
3529 torture_assert_ntstatus_ok(tctx, status,
3530 "Failed to delete object");
3534 struct lsa_EnumAccounts r;
3535 uint32_t resume_handle = 0;
3536 struct lsa_SidArray lsa_sid_array;
3537 int i;
3538 bool found_sid = false;
3540 printf("Testing LSA EnumAccounts\n");
3542 r.in.handle = lsa_handle;
3543 r.in.num_entries = 0x1000;
3544 r.in.resume_handle = &resume_handle;
3545 r.out.sids = &lsa_sid_array;
3546 r.out.resume_handle = &resume_handle;
3548 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
3549 torture_assert_ntstatus_ok(tctx, status,
3550 "Failed to enum accounts");
3552 for (i=0; i < lsa_sid_array.num_sids; i++) {
3553 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
3554 found_sid = true;
3558 torture_assert(tctx, !found_sid,
3559 "should not have listed privileged account");
3563 struct lsa_EnumAccountRights r;
3564 struct lsa_RightSet user_rights;
3566 printf("Testing LSA EnumAccountRights\n");
3568 r.in.handle = lsa_handle;
3569 r.in.sid = user_sid;
3570 r.out.rights = &user_rights;
3572 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
3573 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
3574 "Failed to enum rights for account");
3577 return ret;
3580 static bool test_user_ops(struct dcerpc_pipe *p,
3581 struct torture_context *tctx,
3582 struct policy_handle *user_handle,
3583 struct policy_handle *domain_handle,
3584 const struct dom_sid *domain_sid,
3585 uint32_t base_acct_flags,
3586 const char *base_acct_name, enum torture_samr_choice which_ops,
3587 struct cli_credentials *machine_credentials)
3589 char *password = NULL;
3590 struct samr_QueryUserInfo q;
3591 union samr_UserInfo *info;
3592 NTSTATUS status;
3594 bool ret = true;
3595 int i;
3596 uint32_t rid;
3597 const uint32_t password_fields[] = {
3598 SAMR_FIELD_NT_PASSWORD_PRESENT,
3599 SAMR_FIELD_LM_PASSWORD_PRESENT,
3600 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3604 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3605 if (!NT_STATUS_IS_OK(status)) {
3606 ret = false;
3609 switch (which_ops) {
3610 case TORTURE_SAMR_USER_ATTRIBUTES:
3611 if (!test_QuerySecurity(p, tctx, user_handle)) {
3612 ret = false;
3615 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3616 ret = false;
3619 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3620 ret = false;
3623 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3624 base_acct_name)) {
3625 ret = false;
3628 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3629 ret = false;
3632 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3633 ret = false;
3636 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3637 ret = false;
3639 break;
3640 case TORTURE_SAMR_PASSWORDS:
3641 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3642 char simple_pass[9];
3643 char *v = generate_random_str(tctx, 1);
3645 ZERO_STRUCT(simple_pass);
3646 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3648 printf("Testing machine account password policy rules\n");
3650 /* Workstation trust accounts don't seem to need to honour password quality policy */
3651 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3652 ret = false;
3655 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3656 ret = false;
3659 /* reset again, to allow another 'user' password change */
3660 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3661 ret = false;
3664 /* Try a 'short' password */
3665 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3666 ret = false;
3669 /* Try a compleatly random password */
3670 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3671 ret = false;
3675 for (i = 0; password_fields[i]; i++) {
3676 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3677 ret = false;
3680 /* check it was set right */
3681 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3682 ret = false;
3686 for (i = 0; password_fields[i]; i++) {
3687 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3688 ret = false;
3691 /* check it was set right */
3692 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3693 ret = false;
3697 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
3698 ret = false;
3701 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
3702 ret = false;
3705 if (torture_setting_bool(tctx, "samba4", false)) {
3706 printf("skipping Set Password level 18 and 21 against Samba4\n");
3707 } else {
3709 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
3710 ret = false;
3713 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3714 ret = false;
3717 for (i = 0; password_fields[i]; i++) {
3719 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
3720 /* we need to skip as that would break
3721 * the ChangePasswordUser3 verify */
3722 continue;
3725 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
3726 ret = false;
3729 /* check it was set right */
3730 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3731 ret = false;
3736 q.in.user_handle = user_handle;
3737 q.in.level = 5;
3738 q.out.info = &info;
3740 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3741 if (!NT_STATUS_IS_OK(status)) {
3742 printf("QueryUserInfo level %u failed - %s\n",
3743 q.in.level, nt_errstr(status));
3744 ret = false;
3745 } else {
3746 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
3747 if ((info->info5.acct_flags) != expected_flags) {
3748 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3749 info->info5.acct_flags,
3750 expected_flags);
3751 /* FIXME: GD */
3752 if (!torture_setting_bool(tctx, "samba3", false)) {
3753 ret = false;
3756 if (info->info5.rid != rid) {
3757 printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3758 info->info5.rid, rid);
3763 break;
3765 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
3767 /* test last password change timestamp behaviour */
3768 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
3769 base_acct_name,
3770 user_handle, &password,
3771 machine_credentials)) {
3772 ret = false;
3775 if (ret == true) {
3776 torture_comment(tctx, "pwdLastSet test succeeded\n");
3777 } else {
3778 torture_warning(tctx, "pwdLastSet test failed\n");
3781 break;
3783 case TORTURE_SAMR_USER_PRIVILEGES: {
3785 struct dcerpc_pipe *lp;
3786 struct policy_handle *lsa_handle;
3788 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
3789 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
3791 if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
3792 ret = false;
3795 if (!test_DeleteUser_with_privs(p, lp, tctx,
3796 domain_handle, lsa_handle, user_handle,
3797 domain_sid, rid,
3798 machine_credentials)) {
3799 ret = false;
3802 if (!test_lsa_Close(lp, tctx, lsa_handle)) {
3803 ret = false;
3806 if (!ret) {
3807 torture_warning(tctx, "privileged user delete test failed\n");
3810 break;
3812 case TORTURE_SAMR_OTHER:
3813 /* We just need the account to exist */
3814 break;
3816 return ret;
3819 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
3820 struct policy_handle *alias_handle,
3821 const struct dom_sid *domain_sid)
3823 bool ret = true;
3825 if (!torture_setting_bool(tctx, "samba3", false)) {
3826 if (!test_QuerySecurity(p, tctx, alias_handle)) {
3827 ret = false;
3831 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
3832 ret = false;
3835 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
3836 ret = false;
3839 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
3840 ret = false;
3843 if (torture_setting_bool(tctx, "samba4", false)) {
3844 printf("skipping MultipleMembers Alias tests against Samba4\n");
3845 return ret;
3848 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
3849 ret = false;
3852 return ret;
3856 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3857 struct policy_handle *user_handle)
3859 struct samr_DeleteUser d;
3860 NTSTATUS status;
3861 torture_comment(tctx, "Testing DeleteUser\n");
3863 d.in.user_handle = user_handle;
3864 d.out.user_handle = user_handle;
3866 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3867 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
3869 return true;
3872 bool test_DeleteUser_byname(struct dcerpc_pipe *p,
3873 struct torture_context *tctx,
3874 struct policy_handle *handle, const char *name)
3876 NTSTATUS status;
3877 struct samr_DeleteUser d;
3878 struct policy_handle user_handle;
3879 uint32_t rid;
3881 status = test_LookupName(p, tctx, handle, name, &rid);
3882 if (!NT_STATUS_IS_OK(status)) {
3883 goto failed;
3886 status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
3887 if (!NT_STATUS_IS_OK(status)) {
3888 goto failed;
3891 d.in.user_handle = &user_handle;
3892 d.out.user_handle = &user_handle;
3893 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 goto failed;
3898 return true;
3900 failed:
3901 printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
3902 return false;
3906 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
3907 struct torture_context *tctx,
3908 struct policy_handle *handle, const char *name)
3910 NTSTATUS status;
3911 struct samr_OpenGroup r;
3912 struct samr_DeleteDomainGroup d;
3913 struct policy_handle group_handle;
3914 uint32_t rid;
3916 status = test_LookupName(p, tctx, handle, name, &rid);
3917 if (!NT_STATUS_IS_OK(status)) {
3918 goto failed;
3921 r.in.domain_handle = handle;
3922 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3923 r.in.rid = rid;
3924 r.out.group_handle = &group_handle;
3925 status = dcerpc_samr_OpenGroup(p, tctx, &r);
3926 if (!NT_STATUS_IS_OK(status)) {
3927 goto failed;
3930 d.in.group_handle = &group_handle;
3931 d.out.group_handle = &group_handle;
3932 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
3933 if (!NT_STATUS_IS_OK(status)) {
3934 goto failed;
3937 return true;
3939 failed:
3940 printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
3941 return false;
3945 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
3946 struct torture_context *tctx,
3947 struct policy_handle *domain_handle,
3948 const char *name)
3950 NTSTATUS status;
3951 struct samr_OpenAlias r;
3952 struct samr_DeleteDomAlias d;
3953 struct policy_handle alias_handle;
3954 uint32_t rid;
3956 printf("testing DeleteAlias_byname\n");
3958 status = test_LookupName(p, tctx, domain_handle, name, &rid);
3959 if (!NT_STATUS_IS_OK(status)) {
3960 goto failed;
3963 r.in.domain_handle = domain_handle;
3964 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3965 r.in.rid = rid;
3966 r.out.alias_handle = &alias_handle;
3967 status = dcerpc_samr_OpenAlias(p, tctx, &r);
3968 if (!NT_STATUS_IS_OK(status)) {
3969 goto failed;
3972 d.in.alias_handle = &alias_handle;
3973 d.out.alias_handle = &alias_handle;
3974 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
3975 if (!NT_STATUS_IS_OK(status)) {
3976 goto failed;
3979 return true;
3981 failed:
3982 printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
3983 return false;
3986 static bool test_DeleteAlias(struct dcerpc_pipe *p,
3987 struct torture_context *tctx,
3988 struct policy_handle *alias_handle)
3990 struct samr_DeleteDomAlias d;
3991 NTSTATUS status;
3992 bool ret = true;
3993 printf("Testing DeleteAlias\n");
3995 d.in.alias_handle = alias_handle;
3996 d.out.alias_handle = alias_handle;
3998 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
3999 if (!NT_STATUS_IS_OK(status)) {
4000 printf("DeleteAlias failed - %s\n", nt_errstr(status));
4001 ret = false;
4004 return ret;
4007 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4008 struct policy_handle *domain_handle,
4009 const char *alias_name,
4010 struct policy_handle *alias_handle,
4011 const struct dom_sid *domain_sid,
4012 bool test_alias)
4014 NTSTATUS status;
4015 struct samr_CreateDomAlias r;
4016 struct lsa_String name;
4017 uint32_t rid;
4018 bool ret = true;
4020 init_lsa_String(&name, alias_name);
4021 r.in.domain_handle = domain_handle;
4022 r.in.alias_name = &name;
4023 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4024 r.out.alias_handle = alias_handle;
4025 r.out.rid = &rid;
4027 printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
4029 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4031 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4032 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4033 printf("Server correctly refused create of '%s'\n", r.in.alias_name->string);
4034 return true;
4035 } else {
4036 printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
4037 nt_errstr(status));
4038 return false;
4042 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
4043 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
4044 return false;
4046 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4049 if (!NT_STATUS_IS_OK(status)) {
4050 printf("CreateAlias failed - %s\n", nt_errstr(status));
4051 return false;
4054 if (!test_alias) {
4055 return ret;
4058 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
4059 ret = false;
4062 return ret;
4065 static bool test_ChangePassword(struct dcerpc_pipe *p,
4066 struct torture_context *tctx,
4067 const char *acct_name,
4068 struct policy_handle *domain_handle, char **password)
4070 bool ret = true;
4072 if (!*password) {
4073 return false;
4076 if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
4077 ret = false;
4080 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
4081 ret = false;
4084 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
4085 ret = false;
4088 /* test what happens when setting the old password again */
4089 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
4090 ret = false;
4094 char simple_pass[9];
4095 char *v = generate_random_str(tctx, 1);
4097 ZERO_STRUCT(simple_pass);
4098 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4100 /* test what happens when picking a simple password */
4101 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
4102 ret = false;
4106 /* set samr_SetDomainInfo level 1 with min_length 5 */
4108 struct samr_QueryDomainInfo r;
4109 union samr_DomainInfo *info = NULL;
4110 struct samr_SetDomainInfo s;
4111 uint16_t len_old, len;
4112 uint32_t pwd_prop_old;
4113 int64_t min_pwd_age_old;
4114 NTSTATUS status;
4116 len = 5;
4118 r.in.domain_handle = domain_handle;
4119 r.in.level = 1;
4120 r.out.info = &info;
4122 printf("testing samr_QueryDomainInfo level 1\n");
4123 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
4124 if (!NT_STATUS_IS_OK(status)) {
4125 return false;
4128 s.in.domain_handle = domain_handle;
4129 s.in.level = 1;
4130 s.in.info = info;
4132 /* remember the old min length, so we can reset it */
4133 len_old = s.in.info->info1.min_password_length;
4134 s.in.info->info1.min_password_length = len;
4135 pwd_prop_old = s.in.info->info1.password_properties;
4136 /* turn off password complexity checks for this test */
4137 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
4139 min_pwd_age_old = s.in.info->info1.min_password_age;
4140 s.in.info->info1.min_password_age = 0;
4142 printf("testing samr_SetDomainInfo level 1\n");
4143 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4144 if (!NT_STATUS_IS_OK(status)) {
4145 return false;
4148 printf("calling test_ChangePasswordUser3 with too short password\n");
4150 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
4151 ret = false;
4154 s.in.info->info1.min_password_length = len_old;
4155 s.in.info->info1.password_properties = pwd_prop_old;
4156 s.in.info->info1.min_password_age = min_pwd_age_old;
4158 printf("testing samr_SetDomainInfo level 1\n");
4159 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4160 if (!NT_STATUS_IS_OK(status)) {
4161 return false;
4167 NTSTATUS status;
4168 struct samr_OpenUser r;
4169 struct samr_QueryUserInfo q;
4170 union samr_UserInfo *info;
4171 struct samr_LookupNames n;
4172 struct policy_handle user_handle;
4173 struct samr_Ids rids, types;
4175 n.in.domain_handle = domain_handle;
4176 n.in.num_names = 1;
4177 n.in.names = talloc_array(tctx, struct lsa_String, 1);
4178 n.in.names[0].string = acct_name;
4179 n.out.rids = &rids;
4180 n.out.types = &types;
4182 status = dcerpc_samr_LookupNames(p, tctx, &n);
4183 if (!NT_STATUS_IS_OK(status)) {
4184 printf("LookupNames failed - %s\n", nt_errstr(status));
4185 return false;
4188 r.in.domain_handle = domain_handle;
4189 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4190 r.in.rid = n.out.rids->ids[0];
4191 r.out.user_handle = &user_handle;
4193 status = dcerpc_samr_OpenUser(p, tctx, &r);
4194 if (!NT_STATUS_IS_OK(status)) {
4195 printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
4196 return false;
4199 q.in.user_handle = &user_handle;
4200 q.in.level = 5;
4201 q.out.info = &info;
4203 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4204 if (!NT_STATUS_IS_OK(status)) {
4205 printf("QueryUserInfo failed - %s\n", nt_errstr(status));
4206 return false;
4209 printf("calling test_ChangePasswordUser3 with too early password change\n");
4211 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
4212 info->info5.last_password_change, true)) {
4213 ret = false;
4217 /* we change passwords twice - this has the effect of verifying
4218 they were changed correctly for the final call */
4219 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
4220 ret = false;
4223 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
4224 ret = false;
4227 return ret;
4230 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
4231 struct policy_handle *domain_handle,
4232 const char *user_name,
4233 struct policy_handle *user_handle_out,
4234 struct dom_sid *domain_sid,
4235 enum torture_samr_choice which_ops,
4236 struct cli_credentials *machine_credentials,
4237 bool test_user)
4240 TALLOC_CTX *user_ctx;
4242 NTSTATUS status;
4243 struct samr_CreateUser r;
4244 struct samr_QueryUserInfo q;
4245 union samr_UserInfo *info;
4246 struct samr_DeleteUser d;
4247 uint32_t rid;
4249 /* This call creates a 'normal' account - check that it really does */
4250 const uint32_t acct_flags = ACB_NORMAL;
4251 struct lsa_String name;
4252 bool ret = true;
4254 struct policy_handle user_handle;
4255 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4256 init_lsa_String(&name, user_name);
4258 r.in.domain_handle = domain_handle;
4259 r.in.account_name = &name;
4260 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4261 r.out.user_handle = &user_handle;
4262 r.out.rid = &rid;
4264 printf("Testing CreateUser(%s)\n", r.in.account_name->string);
4266 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
4268 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4269 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4270 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
4271 return true;
4272 } else {
4273 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4274 nt_errstr(status));
4275 return false;
4279 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4280 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4281 talloc_free(user_ctx);
4282 return false;
4284 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
4287 if (!NT_STATUS_IS_OK(status)) {
4288 talloc_free(user_ctx);
4289 printf("CreateUser failed - %s\n", nt_errstr(status));
4290 return false;
4293 if (!test_user) {
4294 if (user_handle_out) {
4295 *user_handle_out = user_handle;
4297 return ret;
4301 q.in.user_handle = &user_handle;
4302 q.in.level = 16;
4303 q.out.info = &info;
4305 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4306 if (!NT_STATUS_IS_OK(status)) {
4307 printf("QueryUserInfo level %u failed - %s\n",
4308 q.in.level, nt_errstr(status));
4309 ret = false;
4310 } else {
4311 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
4312 printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4313 info->info16.acct_flags,
4314 acct_flags);
4315 ret = false;
4319 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4320 domain_sid, acct_flags, name.string, which_ops,
4321 machine_credentials)) {
4322 ret = false;
4325 if (user_handle_out) {
4326 *user_handle_out = user_handle;
4327 } else {
4328 printf("Testing DeleteUser (createuser test)\n");
4330 d.in.user_handle = &user_handle;
4331 d.out.user_handle = &user_handle;
4333 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4334 if (!NT_STATUS_IS_OK(status)) {
4335 printf("DeleteUser failed - %s\n", nt_errstr(status));
4336 ret = false;
4342 talloc_free(user_ctx);
4344 return ret;
4348 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
4349 struct policy_handle *domain_handle,
4350 struct dom_sid *domain_sid,
4351 enum torture_samr_choice which_ops,
4352 struct cli_credentials *machine_credentials)
4354 NTSTATUS status;
4355 struct samr_CreateUser2 r;
4356 struct samr_QueryUserInfo q;
4357 union samr_UserInfo *info;
4358 struct samr_DeleteUser d;
4359 struct policy_handle user_handle;
4360 uint32_t rid;
4361 struct lsa_String name;
4362 bool ret = true;
4363 int i;
4365 struct {
4366 uint32_t acct_flags;
4367 const char *account_name;
4368 NTSTATUS nt_status;
4369 } account_types[] = {
4370 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
4371 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4372 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4373 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4374 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4375 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4376 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4377 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4378 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4379 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
4380 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4381 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4382 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4383 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4384 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
4387 for (i = 0; account_types[i].account_name; i++) {
4388 TALLOC_CTX *user_ctx;
4389 uint32_t acct_flags = account_types[i].acct_flags;
4390 uint32_t access_granted;
4391 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4392 init_lsa_String(&name, account_types[i].account_name);
4394 r.in.domain_handle = domain_handle;
4395 r.in.account_name = &name;
4396 r.in.acct_flags = acct_flags;
4397 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4398 r.out.user_handle = &user_handle;
4399 r.out.access_granted = &access_granted;
4400 r.out.rid = &rid;
4402 printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
4404 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4406 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4407 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4408 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
4409 continue;
4410 } else {
4411 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4412 nt_errstr(status));
4413 ret = false;
4414 continue;
4418 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4419 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4420 talloc_free(user_ctx);
4421 ret = false;
4422 continue;
4424 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4427 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
4428 printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4429 nt_errstr(status), nt_errstr(account_types[i].nt_status));
4430 ret = false;
4433 if (NT_STATUS_IS_OK(status)) {
4434 q.in.user_handle = &user_handle;
4435 q.in.level = 5;
4436 q.out.info = &info;
4438 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4439 if (!NT_STATUS_IS_OK(status)) {
4440 printf("QueryUserInfo level %u failed - %s\n",
4441 q.in.level, nt_errstr(status));
4442 ret = false;
4443 } else {
4444 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4445 if (acct_flags == ACB_NORMAL) {
4446 expected_flags |= ACB_PW_EXPIRED;
4448 if ((info->info5.acct_flags) != expected_flags) {
4449 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4450 info->info5.acct_flags,
4451 expected_flags);
4452 ret = false;
4454 switch (acct_flags) {
4455 case ACB_SVRTRUST:
4456 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
4457 printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4458 DOMAIN_RID_DCS, info->info5.primary_gid);
4459 ret = false;
4461 break;
4462 case ACB_WSTRUST:
4463 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
4464 printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4465 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
4466 ret = false;
4468 break;
4469 case ACB_NORMAL:
4470 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
4471 printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4472 DOMAIN_RID_USERS, info->info5.primary_gid);
4473 ret = false;
4475 break;
4479 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4480 domain_sid, acct_flags, name.string, which_ops,
4481 machine_credentials)) {
4482 ret = false;
4485 if (!policy_handle_empty(&user_handle)) {
4486 printf("Testing DeleteUser (createuser2 test)\n");
4488 d.in.user_handle = &user_handle;
4489 d.out.user_handle = &user_handle;
4491 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4492 if (!NT_STATUS_IS_OK(status)) {
4493 printf("DeleteUser failed - %s\n", nt_errstr(status));
4494 ret = false;
4498 talloc_free(user_ctx);
4501 return ret;
4504 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
4505 struct torture_context *tctx,
4506 struct policy_handle *handle)
4508 NTSTATUS status;
4509 struct samr_QueryAliasInfo r;
4510 union samr_AliasInfo *info;
4511 uint16_t levels[] = {1, 2, 3};
4512 int i;
4513 bool ret = true;
4515 for (i=0;i<ARRAY_SIZE(levels);i++) {
4516 printf("Testing QueryAliasInfo level %u\n", levels[i]);
4518 r.in.alias_handle = handle;
4519 r.in.level = levels[i];
4520 r.out.info = &info;
4522 status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
4523 if (!NT_STATUS_IS_OK(status)) {
4524 printf("QueryAliasInfo level %u failed - %s\n",
4525 levels[i], nt_errstr(status));
4526 ret = false;
4530 return ret;
4533 static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
4534 struct torture_context *tctx,
4535 struct policy_handle *handle)
4537 NTSTATUS status;
4538 struct samr_QueryGroupInfo r;
4539 union samr_GroupInfo *info;
4540 uint16_t levels[] = {1, 2, 3, 4, 5};
4541 int i;
4542 bool ret = true;
4544 for (i=0;i<ARRAY_SIZE(levels);i++) {
4545 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4547 r.in.group_handle = handle;
4548 r.in.level = levels[i];
4549 r.out.info = &info;
4551 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4552 if (!NT_STATUS_IS_OK(status)) {
4553 printf("QueryGroupInfo level %u failed - %s\n",
4554 levels[i], nt_errstr(status));
4555 ret = false;
4559 return ret;
4562 static bool test_QueryGroupMember(struct dcerpc_pipe *p,
4563 struct torture_context *tctx,
4564 struct policy_handle *handle)
4566 NTSTATUS status;
4567 struct samr_QueryGroupMember r;
4568 struct samr_RidTypeArray *rids = NULL;
4569 bool ret = true;
4571 printf("Testing QueryGroupMember\n");
4573 r.in.group_handle = handle;
4574 r.out.rids = &rids;
4576 status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
4577 if (!NT_STATUS_IS_OK(status)) {
4578 printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
4579 ret = false;
4582 return ret;
4586 static bool test_SetGroupInfo(struct dcerpc_pipe *p,
4587 struct torture_context *tctx,
4588 struct policy_handle *handle)
4590 NTSTATUS status;
4591 struct samr_QueryGroupInfo r;
4592 union samr_GroupInfo *info;
4593 struct samr_SetGroupInfo s;
4594 uint16_t levels[] = {1, 2, 3, 4};
4595 uint16_t set_ok[] = {0, 1, 1, 1};
4596 int i;
4597 bool ret = true;
4599 for (i=0;i<ARRAY_SIZE(levels);i++) {
4600 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4602 r.in.group_handle = handle;
4603 r.in.level = levels[i];
4604 r.out.info = &info;
4606 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4607 if (!NT_STATUS_IS_OK(status)) {
4608 printf("QueryGroupInfo level %u failed - %s\n",
4609 levels[i], nt_errstr(status));
4610 ret = false;
4613 printf("Testing SetGroupInfo level %u\n", levels[i]);
4615 s.in.group_handle = handle;
4616 s.in.level = levels[i];
4617 s.in.info = *r.out.info;
4619 #if 0
4620 /* disabled this, as it changes the name only from the point of view of samr,
4621 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4622 the name is still reserved, so creating the old name fails, but deleting by the old name
4623 also fails */
4624 if (s.in.level == 2) {
4625 init_lsa_String(&s.in.info->string, "NewName");
4627 #endif
4629 if (s.in.level == 4) {
4630 init_lsa_String(&s.in.info->description, "test description");
4633 status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
4634 if (set_ok[i]) {
4635 if (!NT_STATUS_IS_OK(status)) {
4636 printf("SetGroupInfo level %u failed - %s\n",
4637 r.in.level, nt_errstr(status));
4638 ret = false;
4639 continue;
4641 } else {
4642 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4643 printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4644 r.in.level, nt_errstr(status));
4645 ret = false;
4646 continue;
4651 return ret;
4654 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
4655 struct torture_context *tctx,
4656 struct policy_handle *handle)
4658 NTSTATUS status;
4659 struct samr_QueryUserInfo r;
4660 union samr_UserInfo *info;
4661 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4662 11, 12, 13, 14, 16, 17, 20, 21};
4663 int i;
4664 bool ret = true;
4666 for (i=0;i<ARRAY_SIZE(levels);i++) {
4667 printf("Testing QueryUserInfo level %u\n", levels[i]);
4669 r.in.user_handle = handle;
4670 r.in.level = levels[i];
4671 r.out.info = &info;
4673 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
4674 if (!NT_STATUS_IS_OK(status)) {
4675 printf("QueryUserInfo level %u failed - %s\n",
4676 levels[i], nt_errstr(status));
4677 ret = false;
4681 return ret;
4684 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
4685 struct torture_context *tctx,
4686 struct policy_handle *handle)
4688 NTSTATUS status;
4689 struct samr_QueryUserInfo2 r;
4690 union samr_UserInfo *info;
4691 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4692 11, 12, 13, 14, 16, 17, 20, 21};
4693 int i;
4694 bool ret = true;
4696 for (i=0;i<ARRAY_SIZE(levels);i++) {
4697 printf("Testing QueryUserInfo2 level %u\n", levels[i]);
4699 r.in.user_handle = handle;
4700 r.in.level = levels[i];
4701 r.out.info = &info;
4703 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
4704 if (!NT_STATUS_IS_OK(status)) {
4705 printf("QueryUserInfo2 level %u failed - %s\n",
4706 levels[i], nt_errstr(status));
4707 ret = false;
4711 return ret;
4714 static bool test_OpenUser(struct dcerpc_pipe *p,
4715 struct torture_context *tctx,
4716 struct policy_handle *handle, uint32_t rid)
4718 NTSTATUS status;
4719 struct samr_OpenUser r;
4720 struct policy_handle user_handle;
4721 bool ret = true;
4723 printf("Testing OpenUser(%u)\n", rid);
4725 r.in.domain_handle = handle;
4726 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4727 r.in.rid = rid;
4728 r.out.user_handle = &user_handle;
4730 status = dcerpc_samr_OpenUser(p, tctx, &r);
4731 if (!NT_STATUS_IS_OK(status)) {
4732 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4733 return false;
4736 if (!test_QuerySecurity(p, tctx, &user_handle)) {
4737 ret = false;
4740 if (!test_QueryUserInfo(p, tctx, &user_handle)) {
4741 ret = false;
4744 if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
4745 ret = false;
4748 if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
4749 ret = false;
4752 if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
4753 ret = false;
4756 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4757 ret = false;
4760 return ret;
4763 static bool test_OpenGroup(struct dcerpc_pipe *p,
4764 struct torture_context *tctx,
4765 struct policy_handle *handle, uint32_t rid)
4767 NTSTATUS status;
4768 struct samr_OpenGroup r;
4769 struct policy_handle group_handle;
4770 bool ret = true;
4772 printf("Testing OpenGroup(%u)\n", rid);
4774 r.in.domain_handle = handle;
4775 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4776 r.in.rid = rid;
4777 r.out.group_handle = &group_handle;
4779 status = dcerpc_samr_OpenGroup(p, tctx, &r);
4780 if (!NT_STATUS_IS_OK(status)) {
4781 printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
4782 return false;
4785 if (!torture_setting_bool(tctx, "samba3", false)) {
4786 if (!test_QuerySecurity(p, tctx, &group_handle)) {
4787 ret = false;
4791 if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
4792 ret = false;
4795 if (!test_QueryGroupMember(p, tctx, &group_handle)) {
4796 ret = false;
4799 if (!test_samr_handle_Close(p, tctx, &group_handle)) {
4800 ret = false;
4803 return ret;
4806 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4807 struct policy_handle *handle, uint32_t rid)
4809 NTSTATUS status;
4810 struct samr_OpenAlias r;
4811 struct policy_handle alias_handle;
4812 bool ret = true;
4814 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
4816 r.in.domain_handle = handle;
4817 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4818 r.in.rid = rid;
4819 r.out.alias_handle = &alias_handle;
4821 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4822 if (!NT_STATUS_IS_OK(status)) {
4823 printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
4824 return false;
4827 if (!torture_setting_bool(tctx, "samba3", false)) {
4828 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
4829 ret = false;
4833 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
4834 ret = false;
4837 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
4838 ret = false;
4841 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
4842 ret = false;
4845 return ret;
4848 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
4849 struct policy_handle *handle, uint32_t rid,
4850 uint32_t acct_flag_mask)
4852 NTSTATUS status;
4853 struct samr_OpenUser r;
4854 struct samr_QueryUserInfo q;
4855 union samr_UserInfo *info;
4856 struct policy_handle user_handle;
4857 bool ret = true;
4859 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4861 r.in.domain_handle = handle;
4862 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4863 r.in.rid = rid;
4864 r.out.user_handle = &user_handle;
4866 status = dcerpc_samr_OpenUser(p, tctx, &r);
4867 if (!NT_STATUS_IS_OK(status)) {
4868 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4869 return false;
4872 q.in.user_handle = &user_handle;
4873 q.in.level = 16;
4874 q.out.info = &info;
4876 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4877 if (!NT_STATUS_IS_OK(status)) {
4878 printf("QueryUserInfo level 16 failed - %s\n",
4879 nt_errstr(status));
4880 ret = false;
4881 } else {
4882 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
4883 printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4884 acct_flag_mask, info->info16.acct_flags, rid);
4885 ret = false;
4889 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4890 ret = false;
4893 return ret;
4896 static bool test_EnumDomainUsers_all(struct dcerpc_pipe *p,
4897 struct torture_context *tctx,
4898 struct policy_handle *handle)
4900 NTSTATUS status = STATUS_MORE_ENTRIES;
4901 struct samr_EnumDomainUsers r;
4902 uint32_t mask, resume_handle=0;
4903 int i, mask_idx;
4904 bool ret = true;
4905 struct samr_LookupNames n;
4906 struct samr_LookupRids lr ;
4907 struct lsa_Strings names;
4908 struct samr_Ids rids, types;
4909 struct samr_SamArray *sam = NULL;
4910 uint32_t num_entries = 0;
4912 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
4913 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
4914 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
4915 ACB_PWNOEXP, 0};
4917 printf("Testing EnumDomainUsers\n");
4919 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
4920 r.in.domain_handle = handle;
4921 r.in.resume_handle = &resume_handle;
4922 r.in.acct_flags = mask = masks[mask_idx];
4923 r.in.max_size = (uint32_t)-1;
4924 r.out.resume_handle = &resume_handle;
4925 r.out.num_entries = &num_entries;
4926 r.out.sam = &sam;
4928 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
4929 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
4930 !NT_STATUS_IS_OK(status)) {
4931 printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
4932 return false;
4935 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4937 if (sam->count == 0) {
4938 continue;
4941 for (i=0;i<sam->count;i++) {
4942 if (mask) {
4943 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
4944 ret = false;
4946 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
4947 ret = false;
4952 printf("Testing LookupNames\n");
4953 n.in.domain_handle = handle;
4954 n.in.num_names = sam->count;
4955 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
4956 n.out.rids = &rids;
4957 n.out.types = &types;
4958 for (i=0;i<sam->count;i++) {
4959 n.in.names[i].string = sam->entries[i].name.string;
4961 status = dcerpc_samr_LookupNames(p, tctx, &n);
4962 if (!NT_STATUS_IS_OK(status)) {
4963 printf("LookupNames failed - %s\n", nt_errstr(status));
4964 ret = false;
4968 printf("Testing LookupRids\n");
4969 lr.in.domain_handle = handle;
4970 lr.in.num_rids = sam->count;
4971 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
4972 lr.out.names = &names;
4973 lr.out.types = &types;
4974 for (i=0;i<sam->count;i++) {
4975 lr.in.rids[i] = sam->entries[i].idx;
4977 status = dcerpc_samr_LookupRids(p, tctx, &lr);
4978 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
4980 return ret;
4984 try blasting the server with a bunch of sync requests
4986 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
4987 struct policy_handle *handle)
4989 NTSTATUS status;
4990 struct samr_EnumDomainUsers r;
4991 uint32_t resume_handle=0;
4992 int i;
4993 #define ASYNC_COUNT 100
4994 struct rpc_request *req[ASYNC_COUNT];
4996 if (!torture_setting_bool(tctx, "dangerous", false)) {
4997 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
5000 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
5002 r.in.domain_handle = handle;
5003 r.in.resume_handle = &resume_handle;
5004 r.in.acct_flags = 0;
5005 r.in.max_size = (uint32_t)-1;
5006 r.out.resume_handle = &resume_handle;
5008 for (i=0;i<ASYNC_COUNT;i++) {
5009 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
5012 for (i=0;i<ASYNC_COUNT;i++) {
5013 status = dcerpc_ndr_request_recv(req[i]);
5014 if (!NT_STATUS_IS_OK(status)) {
5015 printf("EnumDomainUsers[%d] failed - %s\n",
5016 i, nt_errstr(status));
5017 return false;
5021 torture_comment(tctx, "%d async requests OK\n", i);
5023 return true;
5026 static bool test_EnumDomainGroups_all(struct dcerpc_pipe *p,
5027 struct torture_context *tctx,
5028 struct policy_handle *handle)
5030 NTSTATUS status;
5031 struct samr_EnumDomainGroups r;
5032 uint32_t resume_handle=0;
5033 struct samr_SamArray *sam = NULL;
5034 uint32_t num_entries = 0;
5035 int i;
5036 bool ret = true;
5038 printf("Testing EnumDomainGroups\n");
5040 r.in.domain_handle = handle;
5041 r.in.resume_handle = &resume_handle;
5042 r.in.max_size = (uint32_t)-1;
5043 r.out.resume_handle = &resume_handle;
5044 r.out.num_entries = &num_entries;
5045 r.out.sam = &sam;
5047 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
5048 if (!NT_STATUS_IS_OK(status)) {
5049 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
5050 return false;
5053 if (!sam) {
5054 return false;
5057 for (i=0;i<sam->count;i++) {
5058 if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
5059 ret = false;
5063 return ret;
5066 static bool test_EnumDomainAliases_all(struct dcerpc_pipe *p,
5067 struct torture_context *tctx,
5068 struct policy_handle *handle)
5070 NTSTATUS status;
5071 struct samr_EnumDomainAliases r;
5072 uint32_t resume_handle=0;
5073 struct samr_SamArray *sam = NULL;
5074 uint32_t num_entries = 0;
5075 int i;
5076 bool ret = true;
5078 printf("Testing EnumDomainAliases\n");
5080 r.in.domain_handle = handle;
5081 r.in.resume_handle = &resume_handle;
5082 r.in.max_size = (uint32_t)-1;
5083 r.out.sam = &sam;
5084 r.out.num_entries = &num_entries;
5085 r.out.resume_handle = &resume_handle;
5087 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
5088 if (!NT_STATUS_IS_OK(status)) {
5089 printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
5090 return false;
5093 if (!sam) {
5094 return false;
5097 for (i=0;i<sam->count;i++) {
5098 if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
5099 ret = false;
5103 return ret;
5106 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
5107 struct torture_context *tctx,
5108 struct policy_handle *handle)
5110 NTSTATUS status;
5111 struct samr_GetDisplayEnumerationIndex r;
5112 bool ret = true;
5113 uint16_t levels[] = {1, 2, 3, 4, 5};
5114 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
5115 struct lsa_String name;
5116 uint32_t idx = 0;
5117 int i;
5119 for (i=0;i<ARRAY_SIZE(levels);i++) {
5120 printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
5122 init_lsa_String(&name, TEST_ACCOUNT_NAME);
5124 r.in.domain_handle = handle;
5125 r.in.level = levels[i];
5126 r.in.name = &name;
5127 r.out.idx = &idx;
5129 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
5131 if (ok_lvl[i] &&
5132 !NT_STATUS_IS_OK(status) &&
5133 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5134 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
5135 levels[i], nt_errstr(status));
5136 ret = false;
5139 init_lsa_String(&name, "zzzzzzzz");
5141 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
5143 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5144 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
5145 levels[i], nt_errstr(status));
5146 ret = false;
5150 return ret;
5153 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
5154 struct torture_context *tctx,
5155 struct policy_handle *handle)
5157 NTSTATUS status;
5158 struct samr_GetDisplayEnumerationIndex2 r;
5159 bool ret = true;
5160 uint16_t levels[] = {1, 2, 3, 4, 5};
5161 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
5162 struct lsa_String name;
5163 uint32_t idx = 0;
5164 int i;
5166 for (i=0;i<ARRAY_SIZE(levels);i++) {
5167 printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
5169 init_lsa_String(&name, TEST_ACCOUNT_NAME);
5171 r.in.domain_handle = handle;
5172 r.in.level = levels[i];
5173 r.in.name = &name;
5174 r.out.idx = &idx;
5176 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
5177 if (ok_lvl[i] &&
5178 !NT_STATUS_IS_OK(status) &&
5179 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5180 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
5181 levels[i], nt_errstr(status));
5182 ret = false;
5185 init_lsa_String(&name, "zzzzzzzz");
5187 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
5188 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
5189 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
5190 levels[i], nt_errstr(status));
5191 ret = false;
5195 return ret;
5198 #define STRING_EQUAL_QUERY(s1, s2, user) \
5199 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
5200 /* odd, but valid */ \
5201 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
5202 printf("%s mismatch for %s: %s != %s (%s)\n", \
5203 #s1, user.string, s1.string, s2.string, __location__); \
5204 ret = false; \
5206 #define INT_EQUAL_QUERY(s1, s2, user) \
5207 if (s1 != s2) { \
5208 printf("%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
5209 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
5210 ret = false; \
5213 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
5214 struct torture_context *tctx,
5215 struct samr_QueryDisplayInfo *querydisplayinfo,
5216 bool *seen_testuser)
5218 struct samr_OpenUser r;
5219 struct samr_QueryUserInfo q;
5220 union samr_UserInfo *info;
5221 struct policy_handle user_handle;
5222 int i, ret = true;
5223 NTSTATUS status;
5224 r.in.domain_handle = querydisplayinfo->in.domain_handle;
5225 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5226 for (i = 0; ; i++) {
5227 switch (querydisplayinfo->in.level) {
5228 case 1:
5229 if (i >= querydisplayinfo->out.info->info1.count) {
5230 return ret;
5232 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
5233 break;
5234 case 2:
5235 if (i >= querydisplayinfo->out.info->info2.count) {
5236 return ret;
5238 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
5239 break;
5240 case 3:
5241 /* Groups */
5242 case 4:
5243 case 5:
5244 /* Not interested in validating just the account name */
5245 return true;
5248 r.out.user_handle = &user_handle;
5250 switch (querydisplayinfo->in.level) {
5251 case 1:
5252 case 2:
5253 status = dcerpc_samr_OpenUser(p, tctx, &r);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
5256 return false;
5260 q.in.user_handle = &user_handle;
5261 q.in.level = 21;
5262 q.out.info = &info;
5263 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5264 if (!NT_STATUS_IS_OK(status)) {
5265 printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
5266 return false;
5269 switch (querydisplayinfo->in.level) {
5270 case 1:
5271 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
5272 *seen_testuser = true;
5274 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
5275 info->info21.full_name, info->info21.account_name);
5276 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
5277 info->info21.account_name, info->info21.account_name);
5278 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
5279 info->info21.description, info->info21.account_name);
5280 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
5281 info->info21.rid, info->info21.account_name);
5282 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
5283 info->info21.acct_flags, info->info21.account_name);
5285 break;
5286 case 2:
5287 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
5288 info->info21.account_name, info->info21.account_name);
5289 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
5290 info->info21.description, info->info21.account_name);
5291 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
5292 info->info21.rid, info->info21.account_name);
5293 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
5294 info->info21.acct_flags, info->info21.account_name);
5296 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
5297 printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
5298 info->info21.account_name.string);
5301 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
5302 printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
5303 info->info21.account_name.string,
5304 querydisplayinfo->out.info->info2.entries[i].acct_flags,
5305 info->info21.acct_flags);
5306 return false;
5309 break;
5312 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5313 return false;
5316 return ret;
5319 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
5320 struct torture_context *tctx,
5321 struct policy_handle *handle)
5323 NTSTATUS status;
5324 struct samr_QueryDisplayInfo r;
5325 struct samr_QueryDomainInfo dom_info;
5326 union samr_DomainInfo *info = NULL;
5327 bool ret = true;
5328 uint16_t levels[] = {1, 2, 3, 4, 5};
5329 int i;
5330 bool seen_testuser = false;
5331 uint32_t total_size;
5332 uint32_t returned_size;
5333 union samr_DispInfo disp_info;
5336 for (i=0;i<ARRAY_SIZE(levels);i++) {
5337 printf("Testing QueryDisplayInfo level %u\n", levels[i]);
5339 r.in.start_idx = 0;
5340 status = STATUS_MORE_ENTRIES;
5341 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5342 r.in.domain_handle = handle;
5343 r.in.level = levels[i];
5344 r.in.max_entries = 2;
5345 r.in.buf_size = (uint32_t)-1;
5346 r.out.total_size = &total_size;
5347 r.out.returned_size = &returned_size;
5348 r.out.info = &disp_info;
5350 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5351 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
5352 printf("QueryDisplayInfo level %u failed - %s\n",
5353 levels[i], nt_errstr(status));
5354 ret = false;
5356 switch (r.in.level) {
5357 case 1:
5358 if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
5359 ret = false;
5361 r.in.start_idx += r.out.info->info1.count;
5362 break;
5363 case 2:
5364 if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
5365 ret = false;
5367 r.in.start_idx += r.out.info->info2.count;
5368 break;
5369 case 3:
5370 r.in.start_idx += r.out.info->info3.count;
5371 break;
5372 case 4:
5373 r.in.start_idx += r.out.info->info4.count;
5374 break;
5375 case 5:
5376 r.in.start_idx += r.out.info->info5.count;
5377 break;
5380 dom_info.in.domain_handle = handle;
5381 dom_info.in.level = 2;
5382 dom_info.out.info = &info;
5384 /* Check number of users returned is correct */
5385 status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
5386 if (!NT_STATUS_IS_OK(status)) {
5387 printf("QueryDomainInfo level %u failed - %s\n",
5388 r.in.level, nt_errstr(status));
5389 ret = false;
5390 break;
5392 switch (r.in.level) {
5393 case 1:
5394 case 4:
5395 if (info->general.num_users < r.in.start_idx) {
5396 printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
5397 r.in.start_idx, info->general.num_groups,
5398 info->general.domain_name.string);
5399 ret = false;
5401 if (!seen_testuser) {
5402 struct policy_handle user_handle;
5403 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
5404 printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
5405 info->general.domain_name.string);
5406 ret = false;
5407 test_samr_handle_Close(p, tctx, &user_handle);
5410 break;
5411 case 3:
5412 case 5:
5413 if (info->general.num_groups != r.in.start_idx) {
5414 printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
5415 r.in.start_idx, info->general.num_groups,
5416 info->general.domain_name.string);
5417 ret = false;
5420 break;
5425 return ret;
5428 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
5429 struct torture_context *tctx,
5430 struct policy_handle *handle)
5432 NTSTATUS status;
5433 struct samr_QueryDisplayInfo2 r;
5434 bool ret = true;
5435 uint16_t levels[] = {1, 2, 3, 4, 5};
5436 int i;
5437 uint32_t total_size;
5438 uint32_t returned_size;
5439 union samr_DispInfo info;
5441 for (i=0;i<ARRAY_SIZE(levels);i++) {
5442 printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
5444 r.in.domain_handle = handle;
5445 r.in.level = levels[i];
5446 r.in.start_idx = 0;
5447 r.in.max_entries = 1000;
5448 r.in.buf_size = (uint32_t)-1;
5449 r.out.total_size = &total_size;
5450 r.out.returned_size = &returned_size;
5451 r.out.info = &info;
5453 status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
5454 if (!NT_STATUS_IS_OK(status)) {
5455 printf("QueryDisplayInfo2 level %u failed - %s\n",
5456 levels[i], nt_errstr(status));
5457 ret = false;
5461 return ret;
5464 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
5465 struct policy_handle *handle)
5467 NTSTATUS status;
5468 struct samr_QueryDisplayInfo3 r;
5469 bool ret = true;
5470 uint16_t levels[] = {1, 2, 3, 4, 5};
5471 int i;
5472 uint32_t total_size;
5473 uint32_t returned_size;
5474 union samr_DispInfo info;
5476 for (i=0;i<ARRAY_SIZE(levels);i++) {
5477 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
5479 r.in.domain_handle = handle;
5480 r.in.level = levels[i];
5481 r.in.start_idx = 0;
5482 r.in.max_entries = 1000;
5483 r.in.buf_size = (uint32_t)-1;
5484 r.out.total_size = &total_size;
5485 r.out.returned_size = &returned_size;
5486 r.out.info = &info;
5488 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
5489 if (!NT_STATUS_IS_OK(status)) {
5490 printf("QueryDisplayInfo3 level %u failed - %s\n",
5491 levels[i], nt_errstr(status));
5492 ret = false;
5496 return ret;
5500 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
5501 struct torture_context *tctx,
5502 struct policy_handle *handle)
5504 NTSTATUS status;
5505 struct samr_QueryDisplayInfo r;
5506 bool ret = true;
5507 uint32_t total_size;
5508 uint32_t returned_size;
5509 union samr_DispInfo info;
5511 printf("Testing QueryDisplayInfo continuation\n");
5513 r.in.domain_handle = handle;
5514 r.in.level = 1;
5515 r.in.start_idx = 0;
5516 r.in.max_entries = 1;
5517 r.in.buf_size = (uint32_t)-1;
5518 r.out.total_size = &total_size;
5519 r.out.returned_size = &returned_size;
5520 r.out.info = &info;
5522 do {
5523 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5524 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
5525 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
5526 printf("expected idx %d but got %d\n",
5527 r.in.start_idx + 1,
5528 r.out.info->info1.entries[0].idx);
5529 break;
5532 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5533 !NT_STATUS_IS_OK(status)) {
5534 printf("QueryDisplayInfo level %u failed - %s\n",
5535 r.in.level, nt_errstr(status));
5536 ret = false;
5537 break;
5539 r.in.start_idx++;
5540 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
5541 NT_STATUS_IS_OK(status)) &&
5542 *r.out.returned_size != 0);
5544 return ret;
5547 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
5548 struct policy_handle *handle)
5550 NTSTATUS status;
5551 struct samr_QueryDomainInfo r;
5552 union samr_DomainInfo *info = NULL;
5553 struct samr_SetDomainInfo s;
5554 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5555 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5556 int i;
5557 bool ret = true;
5558 const char *domain_comment = talloc_asprintf(tctx,
5559 "Tortured by Samba4 RPC-SAMR: %s",
5560 timestring(tctx, time(NULL)));
5562 s.in.domain_handle = handle;
5563 s.in.level = 4;
5564 s.in.info = talloc(tctx, union samr_DomainInfo);
5566 s.in.info->oem.oem_information.string = domain_comment;
5567 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5568 if (!NT_STATUS_IS_OK(status)) {
5569 printf("SetDomainInfo level %u (set comment) failed - %s\n",
5570 s.in.level, nt_errstr(status));
5571 return false;
5574 for (i=0;i<ARRAY_SIZE(levels);i++) {
5575 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
5577 r.in.domain_handle = handle;
5578 r.in.level = levels[i];
5579 r.out.info = &info;
5581 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5582 if (!NT_STATUS_IS_OK(status)) {
5583 printf("QueryDomainInfo level %u failed - %s\n",
5584 r.in.level, nt_errstr(status));
5585 ret = false;
5586 continue;
5589 switch (levels[i]) {
5590 case 2:
5591 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
5592 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5593 levels[i], info->general.oem_information.string, domain_comment);
5594 ret = false;
5596 if (!info->general.primary.string) {
5597 printf("QueryDomainInfo level %u returned no PDC name\n",
5598 levels[i]);
5599 ret = false;
5600 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
5601 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
5602 printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5603 levels[i], info->general.primary.string, dcerpc_server_name(p));
5606 break;
5607 case 4:
5608 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
5609 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5610 levels[i], info->oem.oem_information.string, domain_comment);
5611 ret = false;
5613 break;
5614 case 6:
5615 if (!info->info6.primary.string) {
5616 printf("QueryDomainInfo level %u returned no PDC name\n",
5617 levels[i]);
5618 ret = false;
5620 break;
5621 case 11:
5622 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
5623 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5624 levels[i], info->general2.general.oem_information.string, domain_comment);
5625 ret = false;
5627 break;
5630 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
5632 s.in.domain_handle = handle;
5633 s.in.level = levels[i];
5634 s.in.info = info;
5636 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5637 if (set_ok[i]) {
5638 if (!NT_STATUS_IS_OK(status)) {
5639 printf("SetDomainInfo level %u failed - %s\n",
5640 r.in.level, nt_errstr(status));
5641 ret = false;
5642 continue;
5644 } else {
5645 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5646 printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5647 r.in.level, nt_errstr(status));
5648 ret = false;
5649 continue;
5653 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5654 if (!NT_STATUS_IS_OK(status)) {
5655 printf("QueryDomainInfo level %u failed - %s\n",
5656 r.in.level, nt_errstr(status));
5657 ret = false;
5658 continue;
5662 return ret;
5666 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
5667 struct policy_handle *handle)
5669 NTSTATUS status;
5670 struct samr_QueryDomainInfo2 r;
5671 union samr_DomainInfo *info = NULL;
5672 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5673 int i;
5674 bool ret = true;
5676 for (i=0;i<ARRAY_SIZE(levels);i++) {
5677 printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
5679 r.in.domain_handle = handle;
5680 r.in.level = levels[i];
5681 r.out.info = &info;
5683 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
5684 if (!NT_STATUS_IS_OK(status)) {
5685 printf("QueryDomainInfo2 level %u failed - %s\n",
5686 r.in.level, nt_errstr(status));
5687 ret = false;
5688 continue;
5692 return true;
5695 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5696 set of group names. */
5697 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
5698 struct policy_handle *handle)
5700 struct samr_EnumDomainGroups q1;
5701 struct samr_QueryDisplayInfo q2;
5702 NTSTATUS status;
5703 uint32_t resume_handle=0;
5704 struct samr_SamArray *sam = NULL;
5705 uint32_t num_entries = 0;
5706 int i;
5707 bool ret = true;
5708 uint32_t total_size;
5709 uint32_t returned_size;
5710 union samr_DispInfo info;
5712 int num_names = 0;
5713 const char **names = NULL;
5715 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
5717 q1.in.domain_handle = handle;
5718 q1.in.resume_handle = &resume_handle;
5719 q1.in.max_size = 5;
5720 q1.out.resume_handle = &resume_handle;
5721 q1.out.num_entries = &num_entries;
5722 q1.out.sam = &sam;
5724 status = STATUS_MORE_ENTRIES;
5725 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5726 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
5728 if (!NT_STATUS_IS_OK(status) &&
5729 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5730 break;
5732 for (i=0; i<*q1.out.num_entries; i++) {
5733 add_string_to_array(tctx,
5734 sam->entries[i].name.string,
5735 &names, &num_names);
5739 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
5741 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
5743 q2.in.domain_handle = handle;
5744 q2.in.level = 5;
5745 q2.in.start_idx = 0;
5746 q2.in.max_entries = 5;
5747 q2.in.buf_size = (uint32_t)-1;
5748 q2.out.total_size = &total_size;
5749 q2.out.returned_size = &returned_size;
5750 q2.out.info = &info;
5752 status = STATUS_MORE_ENTRIES;
5753 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5754 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
5756 if (!NT_STATUS_IS_OK(status) &&
5757 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5758 break;
5760 for (i=0; i<q2.out.info->info5.count; i++) {
5761 int j;
5762 const char *name = q2.out.info->info5.entries[i].account_name.string;
5763 bool found = false;
5764 for (j=0; j<num_names; j++) {
5765 if (names[j] == NULL)
5766 continue;
5767 if (strequal(names[j], name)) {
5768 names[j] = NULL;
5769 found = true;
5770 break;
5774 if (!found) {
5775 printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5776 name);
5777 ret = false;
5780 q2.in.start_idx += q2.out.info->info5.count;
5783 if (!NT_STATUS_IS_OK(status)) {
5784 printf("QueryDisplayInfo level 5 failed - %s\n",
5785 nt_errstr(status));
5786 ret = false;
5789 for (i=0; i<num_names; i++) {
5790 if (names[i] != NULL) {
5791 printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5792 names[i]);
5793 ret = false;
5797 return ret;
5800 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
5801 struct policy_handle *group_handle)
5803 struct samr_DeleteDomainGroup d;
5804 NTSTATUS status;
5806 torture_comment(tctx, "Testing DeleteDomainGroup\n");
5808 d.in.group_handle = group_handle;
5809 d.out.group_handle = group_handle;
5811 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
5812 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
5814 return true;
5817 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5818 struct policy_handle *domain_handle)
5820 struct samr_TestPrivateFunctionsDomain r;
5821 NTSTATUS status;
5822 bool ret = true;
5824 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
5826 r.in.domain_handle = domain_handle;
5828 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
5829 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
5831 return ret;
5834 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
5835 struct dom_sid *domain_sid,
5836 struct policy_handle *domain_handle)
5838 struct samr_RidToSid r;
5839 NTSTATUS status;
5840 bool ret = true;
5841 struct dom_sid *calc_sid, *out_sid;
5842 int rids[] = { 0, 42, 512, 10200 };
5843 int i;
5845 for (i=0;i<ARRAY_SIZE(rids);i++) {
5846 torture_comment(tctx, "Testing RidToSid\n");
5848 calc_sid = dom_sid_dup(tctx, domain_sid);
5849 r.in.domain_handle = domain_handle;
5850 r.in.rid = rids[i];
5851 r.out.sid = &out_sid;
5853 status = dcerpc_samr_RidToSid(p, tctx, &r);
5854 if (!NT_STATUS_IS_OK(status)) {
5855 printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
5856 ret = false;
5857 } else {
5858 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
5860 if (!dom_sid_equal(calc_sid, out_sid)) {
5861 printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
5862 dom_sid_string(tctx, out_sid),
5863 dom_sid_string(tctx, calc_sid));
5864 ret = false;
5869 return ret;
5872 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
5873 struct policy_handle *domain_handle)
5875 struct samr_GetBootKeyInformation r;
5876 NTSTATUS status;
5877 bool ret = true;
5878 uint32_t unknown = 0;
5880 torture_comment(tctx, "Testing GetBootKeyInformation\n");
5882 r.in.domain_handle = domain_handle;
5883 r.out.unknown = &unknown;
5885 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
5886 if (!NT_STATUS_IS_OK(status)) {
5887 /* w2k3 seems to fail this sometimes and pass it sometimes */
5888 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
5891 return ret;
5894 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
5895 struct policy_handle *domain_handle,
5896 struct policy_handle *group_handle)
5898 NTSTATUS status;
5899 struct samr_AddGroupMember r;
5900 struct samr_DeleteGroupMember d;
5901 struct samr_QueryGroupMember q;
5902 struct samr_RidTypeArray *rids = NULL;
5903 struct samr_SetMemberAttributesOfGroup s;
5904 uint32_t rid;
5906 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
5907 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
5909 r.in.group_handle = group_handle;
5910 r.in.rid = rid;
5911 r.in.flags = 0; /* ??? */
5913 torture_comment(tctx, "Testing AddGroupMember and DeleteGroupMember\n");
5915 d.in.group_handle = group_handle;
5916 d.in.rid = rid;
5918 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5919 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
5921 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5922 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5924 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5925 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
5927 if (torture_setting_bool(tctx, "samba4", false) ||
5928 torture_setting_bool(tctx, "samba3", false)) {
5929 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba4\n");
5930 } else {
5931 /* this one is quite strange. I am using random inputs in the
5932 hope of triggering an error that might give us a clue */
5934 s.in.group_handle = group_handle;
5935 s.in.unknown1 = random();
5936 s.in.unknown2 = random();
5938 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
5939 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
5942 q.in.group_handle = group_handle;
5943 q.out.rids = &rids;
5945 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5946 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5948 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5949 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
5951 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5952 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5954 return true;
5958 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
5959 struct torture_context *tctx,
5960 struct policy_handle *domain_handle,
5961 const char *group_name,
5962 struct policy_handle *group_handle,
5963 struct dom_sid *domain_sid,
5964 bool test_group)
5966 NTSTATUS status;
5967 struct samr_CreateDomainGroup r;
5968 uint32_t rid;
5969 struct lsa_String name;
5970 bool ret = true;
5972 init_lsa_String(&name, group_name);
5974 r.in.domain_handle = domain_handle;
5975 r.in.name = &name;
5976 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5977 r.out.group_handle = group_handle;
5978 r.out.rid = &rid;
5980 printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
5982 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5984 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5985 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5986 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
5987 return true;
5988 } else {
5989 printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
5990 nt_errstr(status));
5991 return false;
5995 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
5996 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
5997 printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
5998 nt_errstr(status));
5999 return false;
6001 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6003 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
6004 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
6006 printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
6007 nt_errstr(status));
6008 return false;
6010 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6012 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
6014 if (!test_group) {
6015 return ret;
6018 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
6019 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
6020 ret = false;
6023 if (!test_SetGroupInfo(p, tctx, group_handle)) {
6024 ret = false;
6027 return ret;
6032 its not totally clear what this does. It seems to accept any sid you like.
6034 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
6035 struct torture_context *tctx,
6036 struct policy_handle *domain_handle)
6038 NTSTATUS status;
6039 struct samr_RemoveMemberFromForeignDomain r;
6041 r.in.domain_handle = domain_handle;
6042 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
6044 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
6045 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
6047 return true;
6050 static bool test_EnumDomainUsers(struct dcerpc_pipe *p,
6051 struct torture_context *tctx,
6052 struct policy_handle *domain_handle,
6053 uint32_t *total_num_entries_p)
6055 NTSTATUS status;
6056 struct samr_EnumDomainUsers r;
6057 uint32_t resume_handle = 0;
6058 uint32_t num_entries = 0;
6059 uint32_t total_num_entries = 0;
6060 struct samr_SamArray *sam;
6062 r.in.domain_handle = domain_handle;
6063 r.in.acct_flags = ACB_NORMAL;
6064 r.in.max_size = (uint32_t)-1;
6065 r.in.resume_handle = &resume_handle;
6067 r.out.sam = &sam;
6068 r.out.num_entries = &num_entries;
6069 r.out.resume_handle = &resume_handle;
6071 printf("Testing EnumDomainUsers\n");
6073 do {
6074 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
6075 if (NT_STATUS_IS_ERR(status)) {
6076 torture_assert_ntstatus_ok(tctx, status,
6077 "failed to enumerate users");
6080 total_num_entries += num_entries;
6081 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6083 if (total_num_entries_p) {
6084 *total_num_entries_p = total_num_entries;
6087 return true;
6090 static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
6091 struct torture_context *tctx,
6092 struct policy_handle *domain_handle,
6093 uint32_t *total_num_entries_p)
6095 NTSTATUS status;
6096 struct samr_EnumDomainGroups r;
6097 uint32_t resume_handle = 0;
6098 uint32_t num_entries = 0;
6099 uint32_t total_num_entries = 0;
6100 struct samr_SamArray *sam;
6102 r.in.domain_handle = domain_handle;
6103 r.in.max_size = (uint32_t)-1;
6104 r.in.resume_handle = &resume_handle;
6106 r.out.sam = &sam;
6107 r.out.num_entries = &num_entries;
6108 r.out.resume_handle = &resume_handle;
6110 printf("Testing EnumDomainGroups\n");
6112 do {
6113 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
6114 if (NT_STATUS_IS_ERR(status)) {
6115 torture_assert_ntstatus_ok(tctx, status,
6116 "failed to enumerate groups");
6119 total_num_entries += num_entries;
6120 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6122 if (total_num_entries_p) {
6123 *total_num_entries_p = total_num_entries;
6126 return true;
6129 static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
6130 struct torture_context *tctx,
6131 struct policy_handle *domain_handle,
6132 uint32_t *total_num_entries_p)
6134 NTSTATUS status;
6135 struct samr_EnumDomainAliases r;
6136 uint32_t resume_handle = 0;
6137 uint32_t num_entries = 0;
6138 uint32_t total_num_entries = 0;
6139 struct samr_SamArray *sam;
6141 r.in.domain_handle = domain_handle;
6142 r.in.max_size = (uint32_t)-1;
6143 r.in.resume_handle = &resume_handle;
6145 r.out.sam = &sam;
6146 r.out.num_entries = &num_entries;
6147 r.out.resume_handle = &resume_handle;
6149 printf("Testing EnumDomainAliases\n");
6151 do {
6152 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
6153 if (NT_STATUS_IS_ERR(status)) {
6154 torture_assert_ntstatus_ok(tctx, status,
6155 "failed to enumerate aliases");
6158 total_num_entries += num_entries;
6159 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
6161 if (total_num_entries_p) {
6162 *total_num_entries_p = total_num_entries;
6165 return true;
6168 static bool test_ManyObjects(struct dcerpc_pipe *p,
6169 struct torture_context *tctx,
6170 struct policy_handle *domain_handle,
6171 struct dom_sid *domain_sid,
6172 enum torture_samr_choice which_ops)
6174 uint32_t num_total = 1500;
6175 uint32_t num_enum = 0;
6176 uint32_t num_disp = 0;
6177 uint32_t num_created = 0;
6178 uint32_t num_anounced = 0;
6179 bool ret = true;
6180 NTSTATUS status;
6181 uint32_t i;
6183 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
6185 /* query */
6188 struct samr_QueryDomainInfo2 r;
6189 union samr_DomainInfo *info;
6190 r.in.domain_handle = domain_handle;
6191 r.in.level = 2;
6192 r.out.info = &info;
6194 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
6195 torture_assert_ntstatus_ok(tctx, status,
6196 "failed to query domain info");
6198 switch (which_ops) {
6199 case TORTURE_SAMR_MANY_ACCOUNTS:
6200 num_anounced = info->general.num_users;
6201 break;
6202 case TORTURE_SAMR_MANY_GROUPS:
6203 num_anounced = info->general.num_groups;
6204 break;
6205 case TORTURE_SAMR_MANY_ALIASES:
6206 num_anounced = info->general.num_aliases;
6207 break;
6208 default:
6209 return false;
6213 /* create */
6215 for (i=0; i < num_total; i++) {
6217 const char *name = NULL;
6219 switch (which_ops) {
6220 case TORTURE_SAMR_MANY_ACCOUNTS:
6221 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
6222 ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
6223 break;
6224 case TORTURE_SAMR_MANY_GROUPS:
6225 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
6226 ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
6227 break;
6228 case TORTURE_SAMR_MANY_ALIASES:
6229 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
6230 ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
6231 break;
6232 default:
6233 return false;
6235 if (!policy_handle_empty(&handles[i])) {
6236 num_created++;
6240 /* enum */
6242 switch (which_ops) {
6243 case TORTURE_SAMR_MANY_ACCOUNTS:
6244 ret &= test_EnumDomainUsers(p, tctx, domain_handle, &num_enum);
6245 break;
6246 case TORTURE_SAMR_MANY_GROUPS:
6247 ret &= test_EnumDomainGroups(p, tctx, domain_handle, &num_enum);
6248 break;
6249 case TORTURE_SAMR_MANY_ALIASES:
6250 ret &= test_EnumDomainAliases(p, tctx, domain_handle, &num_enum);
6251 break;
6252 default:
6253 return false;
6256 /* TODO: dispinfo */
6258 switch (which_ops) {
6259 case TORTURE_SAMR_MANY_ACCOUNTS:
6260 break;
6261 case TORTURE_SAMR_MANY_GROUPS:
6262 break;
6263 case TORTURE_SAMR_MANY_ALIASES:
6264 break;
6265 default:
6266 return false;
6270 /* delete */
6272 for (i=0; i < num_total; i++) {
6274 if (policy_handle_empty(&handles[i])) {
6275 continue;
6278 switch (which_ops) {
6279 case TORTURE_SAMR_MANY_ACCOUNTS:
6280 ret &= test_DeleteUser(p, tctx, &handles[i]);
6281 break;
6282 case TORTURE_SAMR_MANY_GROUPS:
6283 ret &= test_DeleteDomainGroup(p, tctx, &handles[i]);
6284 break;
6285 case TORTURE_SAMR_MANY_ALIASES:
6286 ret &= test_DeleteAlias(p, tctx, &handles[i]);
6287 break;
6288 default:
6289 return false;
6293 talloc_free(handles);
6295 #if 0
6296 torture_assert_int_equal(tctx, num_disp, num_anounced + num_created,
6297 "unexpected number of results returned in dispinfo call");
6298 #endif
6299 torture_assert_int_equal(tctx, num_enum, num_anounced + num_created,
6300 "unexpected number of results returned in enum call");
6301 return ret;
6304 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
6305 struct policy_handle *handle);
6307 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6308 struct policy_handle *handle, struct dom_sid *sid,
6309 enum torture_samr_choice which_ops,
6310 struct cli_credentials *machine_credentials)
6312 NTSTATUS status;
6313 struct samr_OpenDomain r;
6314 struct policy_handle domain_handle;
6315 struct policy_handle alias_handle;
6316 struct policy_handle user_handle;
6317 struct policy_handle group_handle;
6318 bool ret = true;
6320 ZERO_STRUCT(alias_handle);
6321 ZERO_STRUCT(user_handle);
6322 ZERO_STRUCT(group_handle);
6323 ZERO_STRUCT(domain_handle);
6325 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
6327 r.in.connect_handle = handle;
6328 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6329 r.in.sid = sid;
6330 r.out.domain_handle = &domain_handle;
6332 status = dcerpc_samr_OpenDomain(p, tctx, &r);
6333 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
6335 /* run the domain tests with the main handle closed - this tests
6336 the servers reference counting */
6337 ret &= test_samr_handle_Close(p, tctx, handle);
6339 switch (which_ops) {
6340 case TORTURE_SAMR_PASSWORDS:
6341 case TORTURE_SAMR_USER_PRIVILEGES:
6342 if (!torture_setting_bool(tctx, "samba3", false)) {
6343 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
6345 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true);
6346 break;
6347 case TORTURE_SAMR_USER_ATTRIBUTES:
6348 if (!torture_setting_bool(tctx, "samba3", false)) {
6349 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
6351 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true);
6352 /* This test needs 'complex' users to validate */
6353 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
6354 if (!ret) {
6355 printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
6357 break;
6358 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
6359 if (!torture_setting_bool(tctx, "samba3", false)) {
6360 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, machine_credentials);
6362 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, machine_credentials, true);
6363 if (!ret) {
6364 printf("Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
6366 break;
6367 case TORTURE_SAMR_MANY_ACCOUNTS:
6368 case TORTURE_SAMR_MANY_GROUPS:
6369 case TORTURE_SAMR_MANY_ALIASES:
6370 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, which_ops);
6371 break;
6372 case TORTURE_SAMR_OTHER:
6373 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, which_ops, NULL, true);
6374 if (!ret) {
6375 printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
6377 if (!torture_setting_bool(tctx, "samba3", false)) {
6378 ret &= test_QuerySecurity(p, tctx, &domain_handle);
6380 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
6381 ret &= test_CreateAlias(p, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
6382 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
6383 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
6384 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
6385 ret &= test_EnumDomainUsers_all(p, tctx, &domain_handle);
6386 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
6387 ret &= test_EnumDomainGroups_all(p, tctx, &domain_handle);
6388 ret &= test_EnumDomainAliases_all(p, tctx, &domain_handle);
6389 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
6390 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
6391 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
6393 if (torture_setting_bool(tctx, "samba4", false)) {
6394 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
6395 } else {
6396 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
6397 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
6399 ret &= test_GroupList(p, tctx, &domain_handle);
6400 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
6401 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
6402 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
6403 if (!ret) {
6404 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
6406 break;
6409 if (!policy_handle_empty(&user_handle) &&
6410 !test_DeleteUser(p, tctx, &user_handle)) {
6411 ret = false;
6414 if (!policy_handle_empty(&alias_handle) &&
6415 !test_DeleteAlias(p, tctx, &alias_handle)) {
6416 ret = false;
6419 if (!policy_handle_empty(&group_handle) &&
6420 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
6421 ret = false;
6424 ret &= test_samr_handle_Close(p, tctx, &domain_handle);
6426 /* reconnect the main handle */
6427 ret &= test_Connect(p, tctx, handle);
6429 if (!ret) {
6430 printf("Testing domain %s failed!\n", dom_sid_string(tctx, sid));
6433 return ret;
6436 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6437 struct policy_handle *handle, const char *domain,
6438 enum torture_samr_choice which_ops,
6439 struct cli_credentials *machine_credentials)
6441 NTSTATUS status;
6442 struct samr_LookupDomain r;
6443 struct dom_sid2 *sid = NULL;
6444 struct lsa_String n1;
6445 struct lsa_String n2;
6446 bool ret = true;
6448 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
6450 /* check for correct error codes */
6451 r.in.connect_handle = handle;
6452 r.in.domain_name = &n2;
6453 r.out.sid = &sid;
6454 n2.string = NULL;
6456 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6457 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
6459 init_lsa_String(&n2, "xxNODOMAINxx");
6461 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6462 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
6464 r.in.connect_handle = handle;
6466 init_lsa_String(&n1, domain);
6467 r.in.domain_name = &n1;
6469 status = dcerpc_samr_LookupDomain(p, tctx, &r);
6470 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
6472 if (!test_GetDomPwInfo(p, tctx, &n1)) {
6473 ret = false;
6476 if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops,
6477 machine_credentials)) {
6478 ret = false;
6481 return ret;
6485 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
6486 struct policy_handle *handle, enum torture_samr_choice which_ops,
6487 struct cli_credentials *machine_credentials)
6489 NTSTATUS status;
6490 struct samr_EnumDomains r;
6491 uint32_t resume_handle = 0;
6492 uint32_t num_entries = 0;
6493 struct samr_SamArray *sam = NULL;
6494 int i;
6495 bool ret = true;
6497 r.in.connect_handle = handle;
6498 r.in.resume_handle = &resume_handle;
6499 r.in.buf_size = (uint32_t)-1;
6500 r.out.resume_handle = &resume_handle;
6501 r.out.num_entries = &num_entries;
6502 r.out.sam = &sam;
6504 status = dcerpc_samr_EnumDomains(p, tctx, &r);
6505 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
6507 if (!*r.out.sam) {
6508 return false;
6511 for (i=0;i<sam->count;i++) {
6512 if (!test_LookupDomain(p, tctx, handle,
6513 sam->entries[i].name.string, which_ops,
6514 machine_credentials)) {
6515 ret = false;
6519 status = dcerpc_samr_EnumDomains(p, tctx, &r);
6520 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
6522 return ret;
6526 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
6527 struct policy_handle *handle)
6529 NTSTATUS status;
6530 struct samr_Connect r;
6531 struct samr_Connect2 r2;
6532 struct samr_Connect3 r3;
6533 struct samr_Connect4 r4;
6534 struct samr_Connect5 r5;
6535 union samr_ConnectInfo info;
6536 struct policy_handle h;
6537 uint32_t level_out = 0;
6538 bool ret = true, got_handle = false;
6540 torture_comment(tctx, "testing samr_Connect\n");
6542 r.in.system_name = 0;
6543 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6544 r.out.connect_handle = &h;
6546 status = dcerpc_samr_Connect(p, tctx, &r);
6547 if (!NT_STATUS_IS_OK(status)) {
6548 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
6549 ret = false;
6550 } else {
6551 got_handle = true;
6552 *handle = h;
6555 torture_comment(tctx, "testing samr_Connect2\n");
6557 r2.in.system_name = NULL;
6558 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6559 r2.out.connect_handle = &h;
6561 status = dcerpc_samr_Connect2(p, tctx, &r2);
6562 if (!NT_STATUS_IS_OK(status)) {
6563 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
6564 ret = false;
6565 } else {
6566 if (got_handle) {
6567 test_samr_handle_Close(p, tctx, handle);
6569 got_handle = true;
6570 *handle = h;
6573 torture_comment(tctx, "testing samr_Connect3\n");
6575 r3.in.system_name = NULL;
6576 r3.in.unknown = 0;
6577 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6578 r3.out.connect_handle = &h;
6580 status = dcerpc_samr_Connect3(p, tctx, &r3);
6581 if (!NT_STATUS_IS_OK(status)) {
6582 printf("Connect3 failed - %s\n", nt_errstr(status));
6583 ret = false;
6584 } else {
6585 if (got_handle) {
6586 test_samr_handle_Close(p, tctx, handle);
6588 got_handle = true;
6589 *handle = h;
6592 torture_comment(tctx, "testing samr_Connect4\n");
6594 r4.in.system_name = "";
6595 r4.in.client_version = 0;
6596 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6597 r4.out.connect_handle = &h;
6599 status = dcerpc_samr_Connect4(p, tctx, &r4);
6600 if (!NT_STATUS_IS_OK(status)) {
6601 printf("Connect4 failed - %s\n", nt_errstr(status));
6602 ret = false;
6603 } else {
6604 if (got_handle) {
6605 test_samr_handle_Close(p, tctx, handle);
6607 got_handle = true;
6608 *handle = h;
6611 torture_comment(tctx, "testing samr_Connect5\n");
6613 info.info1.client_version = 0;
6614 info.info1.unknown2 = 0;
6616 r5.in.system_name = "";
6617 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6618 r5.in.level_in = 1;
6619 r5.out.level_out = &level_out;
6620 r5.in.info_in = &info;
6621 r5.out.info_out = &info;
6622 r5.out.connect_handle = &h;
6624 status = dcerpc_samr_Connect5(p, tctx, &r5);
6625 if (!NT_STATUS_IS_OK(status)) {
6626 printf("Connect5 failed - %s\n", nt_errstr(status));
6627 ret = false;
6628 } else {
6629 if (got_handle) {
6630 test_samr_handle_Close(p, tctx, handle);
6632 got_handle = true;
6633 *handle = h;
6636 return ret;
6640 bool torture_rpc_samr(struct torture_context *torture)
6642 NTSTATUS status;
6643 struct dcerpc_pipe *p;
6644 bool ret = true;
6645 struct policy_handle handle;
6647 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6648 if (!NT_STATUS_IS_OK(status)) {
6649 return false;
6652 ret &= test_Connect(p, torture, &handle);
6654 if (!torture_setting_bool(torture, "samba3", false)) {
6655 ret &= test_QuerySecurity(p, torture, &handle);
6658 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
6660 ret &= test_SetDsrmPassword(p, torture, &handle);
6662 ret &= test_Shutdown(p, torture, &handle);
6664 ret &= test_samr_handle_Close(p, torture, &handle);
6666 return ret;
6670 bool torture_rpc_samr_users(struct torture_context *torture)
6672 NTSTATUS status;
6673 struct dcerpc_pipe *p;
6674 bool ret = true;
6675 struct policy_handle handle;
6677 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6678 if (!NT_STATUS_IS_OK(status)) {
6679 return false;
6682 ret &= test_Connect(p, torture, &handle);
6684 if (!torture_setting_bool(torture, "samba3", false)) {
6685 ret &= test_QuerySecurity(p, torture, &handle);
6688 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
6690 ret &= test_SetDsrmPassword(p, torture, &handle);
6692 ret &= test_Shutdown(p, torture, &handle);
6694 ret &= test_samr_handle_Close(p, torture, &handle);
6696 return ret;
6700 bool torture_rpc_samr_passwords(struct torture_context *torture)
6702 NTSTATUS status;
6703 struct dcerpc_pipe *p;
6704 bool ret = true;
6705 struct policy_handle handle;
6707 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6708 if (!NT_STATUS_IS_OK(status)) {
6709 return false;
6712 ret &= test_Connect(p, torture, &handle);
6714 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
6716 ret &= test_samr_handle_Close(p, torture, &handle);
6718 return ret;
6721 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
6722 struct dcerpc_pipe *p2,
6723 struct cli_credentials *machine_credentials)
6725 NTSTATUS status;
6726 struct dcerpc_pipe *p;
6727 bool ret = true;
6728 struct policy_handle handle;
6730 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6731 if (!NT_STATUS_IS_OK(status)) {
6732 return false;
6735 ret &= test_Connect(p, torture, &handle);
6737 ret &= test_EnumDomains(p, torture, &handle,
6738 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
6739 machine_credentials);
6741 ret &= test_samr_handle_Close(p, torture, &handle);
6743 return ret;
6746 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
6748 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
6749 struct torture_rpc_tcase *tcase;
6751 tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
6752 &ndr_table_samr,
6753 TEST_ACCOUNT_NAME_PWD);
6755 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
6756 torture_rpc_samr_pwdlastset);
6758 return suite;
6761 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
6762 struct dcerpc_pipe *p2,
6763 struct cli_credentials *machine_credentials)
6765 NTSTATUS status;
6766 struct dcerpc_pipe *p;
6767 bool ret = true;
6768 struct policy_handle handle;
6770 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6771 if (!NT_STATUS_IS_OK(status)) {
6772 return false;
6775 ret &= test_Connect(p, torture, &handle);
6777 ret &= test_EnumDomains(p, torture, &handle,
6778 TORTURE_SAMR_USER_PRIVILEGES,
6779 machine_credentials);
6781 ret &= test_samr_handle_Close(p, torture, &handle);
6783 return ret;
6786 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
6788 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
6789 struct torture_rpc_tcase *tcase;
6791 tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
6792 &ndr_table_samr,
6793 TEST_ACCOUNT_NAME_PWD);
6795 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
6796 torture_rpc_samr_users_privileges_delete_user);
6798 return suite;
6801 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
6802 struct dcerpc_pipe *p2,
6803 struct cli_credentials *machine_credentials)
6805 NTSTATUS status;
6806 struct dcerpc_pipe *p;
6807 bool ret = true;
6808 struct policy_handle handle;
6810 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6811 if (!NT_STATUS_IS_OK(status)) {
6812 return false;
6815 ret &= test_Connect(p, torture, &handle);
6817 ret &= test_EnumDomains(p, torture, &handle,
6818 TORTURE_SAMR_MANY_ACCOUNTS,
6819 machine_credentials);
6821 ret &= test_samr_handle_Close(p, torture, &handle);
6823 return ret;
6826 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
6827 struct dcerpc_pipe *p2,
6828 struct cli_credentials *machine_credentials)
6830 NTSTATUS status;
6831 struct dcerpc_pipe *p;
6832 bool ret = true;
6833 struct policy_handle handle;
6835 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6836 if (!NT_STATUS_IS_OK(status)) {
6837 return false;
6840 ret &= test_Connect(p, torture, &handle);
6842 ret &= test_EnumDomains(p, torture, &handle,
6843 TORTURE_SAMR_MANY_GROUPS,
6844 machine_credentials);
6846 ret &= test_samr_handle_Close(p, torture, &handle);
6848 return ret;
6851 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
6852 struct dcerpc_pipe *p2,
6853 struct cli_credentials *machine_credentials)
6855 NTSTATUS status;
6856 struct dcerpc_pipe *p;
6857 bool ret = true;
6858 struct policy_handle handle;
6860 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6861 if (!NT_STATUS_IS_OK(status)) {
6862 return false;
6865 ret &= test_Connect(p, torture, &handle);
6867 ret &= test_EnumDomains(p, torture, &handle,
6868 TORTURE_SAMR_MANY_ALIASES,
6869 machine_credentials);
6871 ret &= test_samr_handle_Close(p, torture, &handle);
6873 return ret;
6876 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
6878 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
6879 struct torture_rpc_tcase *tcase;
6881 tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
6882 &ndr_table_samr,
6883 TEST_ACCOUNT_NAME);
6885 torture_rpc_tcase_add_test_creds(tcase, "many_aliases",
6886 torture_rpc_samr_many_aliases);
6887 torture_rpc_tcase_add_test_creds(tcase, "many_groups",
6888 torture_rpc_samr_many_groups);
6889 torture_rpc_tcase_add_test_creds(tcase, "many_accounts",
6890 torture_rpc_samr_many_accounts);
6892 return suite;