Fix the developer O3 build
[Samba.git] / source4 / torture / rpc / samr.c
blob293b6722cc2ed424c3fec8595ba64252495ac96a
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for samr rpc operations
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7 Copyright (C) Jelmer Vernooij 2005-2007
8 Copyright (C) Guenther Deschner 2008-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include <tevent.h>
27 #include "system/time.h"
28 #include "system/network.h"
29 #include "librpc/gen_ndr/lsa.h"
30 #include "librpc/gen_ndr/ndr_netlogon.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
33 #include "librpc/gen_ndr/ndr_lsa_c.h"
34 #include "../lib/crypto/crypto.h"
35 #include "libcli/auth/libcli_auth.h"
36 #include "libcli/security/security.h"
37 #include "torture/rpc/torture_rpc.h"
38 #include "param/param.h"
39 #include "auth/gensec/gensec.h"
40 #include "auth/gensec/gensec_proto.h"
41 #include "../libcli/auth/schannel.h"
43 #define TEST_ACCOUNT_NAME "samrtorturetest"
44 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
45 #define TEST_ALIASNAME "samrtorturetestalias"
46 #define TEST_GROUPNAME "samrtorturetestgroup"
47 #define TEST_MACHINENAME "samrtestmach$"
48 #define TEST_DOMAINNAME "samrtestdom$"
50 enum torture_samr_choice {
51 TORTURE_SAMR_PASSWORDS,
52 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
53 TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
54 TORTURE_SAMR_PASSWORDS_LOCKOUT,
55 TORTURE_SAMR_USER_ATTRIBUTES,
56 TORTURE_SAMR_USER_PRIVILEGES,
57 TORTURE_SAMR_OTHER,
58 TORTURE_SAMR_MANY_ACCOUNTS,
59 TORTURE_SAMR_MANY_GROUPS,
60 TORTURE_SAMR_MANY_ALIASES
63 struct torture_samr_context {
64 struct policy_handle handle;
65 struct cli_credentials *machine_credentials;
66 enum torture_samr_choice choice;
67 uint32_t num_objects_large_dc;
70 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
71 struct torture_context *tctx,
72 struct policy_handle *handle);
74 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
75 struct torture_context *tctx,
76 struct policy_handle *handle);
78 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
79 struct torture_context *tctx,
80 struct policy_handle *handle);
82 static bool test_ChangePassword(struct dcerpc_pipe *p,
83 struct torture_context *tctx,
84 const char *acct_name,
85 struct policy_handle *domain_handle, char **password);
87 static void init_lsa_String(struct lsa_String *string, const char *s)
89 string->string = s;
92 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
94 string->string = s;
97 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
99 string->length = length;
100 string->size = length;
101 string->array = (uint16_t *)discard_const(s);
104 bool test_samr_handle_Close(struct dcerpc_binding_handle *b,
105 struct torture_context *tctx,
106 struct policy_handle *handle)
108 struct samr_Close r;
110 r.in.handle = handle;
111 r.out.handle = handle;
113 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Close_r(b, tctx, &r),
114 "Close failed");
115 torture_assert_ntstatus_ok(tctx, r.out.result, "Close failed");
117 return true;
120 static bool test_Shutdown(struct dcerpc_binding_handle *b,
121 struct torture_context *tctx,
122 struct policy_handle *handle)
124 struct samr_Shutdown r;
126 if (!torture_setting_bool(tctx, "dangerous", false)) {
127 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
128 return true;
131 r.in.connect_handle = handle;
133 torture_comment(tctx, "Testing samr_Shutdown\n");
135 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Shutdown_r(b, tctx, &r),
136 "Shutdown failed");
137 torture_assert_ntstatus_ok(tctx, r.out.result, "Shutdown failed");
139 return true;
142 static bool test_SetDsrmPassword(struct dcerpc_binding_handle *b,
143 struct torture_context *tctx,
144 struct policy_handle *handle)
146 struct samr_SetDsrmPassword r;
147 struct lsa_String string;
148 struct samr_Password hash;
150 if (!torture_setting_bool(tctx, "dangerous", false)) {
151 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
154 E_md4hash("TeSTDSRM123", hash.hash);
156 init_lsa_String(&string, "Administrator");
158 r.in.name = &string;
159 r.in.unknown = 0;
160 r.in.hash = &hash;
162 torture_comment(tctx, "Testing samr_SetDsrmPassword\n");
164 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDsrmPassword_r(b, tctx, &r),
165 "SetDsrmPassword failed");
166 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_SUPPORTED, "SetDsrmPassword failed");
168 return true;
172 static bool test_QuerySecurity(struct dcerpc_binding_handle *b,
173 struct torture_context *tctx,
174 struct policy_handle *handle)
176 struct samr_QuerySecurity r;
177 struct samr_SetSecurity s;
178 struct sec_desc_buf *sdbuf = NULL;
180 r.in.handle = handle;
181 r.in.sec_info = 7;
182 r.out.sdbuf = &sdbuf;
184 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
185 "QuerySecurity failed");
186 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
188 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
190 s.in.handle = handle;
191 s.in.sec_info = 7;
192 s.in.sdbuf = sdbuf;
194 if (torture_setting_bool(tctx, "samba4", false)) {
195 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
198 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetSecurity_r(b, tctx, &s),
199 "SetSecurity failed");
200 torture_assert_ntstatus_ok(tctx, r.out.result, "SetSecurity failed");
202 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
203 "QuerySecurity failed");
204 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
206 return true;
210 static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_context *tctx,
211 struct policy_handle *handle, uint32_t base_acct_flags,
212 const char *base_account_name)
214 struct samr_SetUserInfo s;
215 struct samr_SetUserInfo2 s2;
216 struct samr_QueryUserInfo q;
217 struct samr_QueryUserInfo q0;
218 union samr_UserInfo u;
219 union samr_UserInfo *info;
220 bool ret = true;
221 const char *test_account_name;
223 uint32_t user_extra_flags = 0;
225 if (!torture_setting_bool(tctx, "samba3", false)) {
226 if (base_acct_flags == ACB_NORMAL) {
227 /* When created, accounts are expired by default */
228 user_extra_flags = ACB_PW_EXPIRED;
232 s.in.user_handle = handle;
233 s.in.info = &u;
235 s2.in.user_handle = handle;
236 s2.in.info = &u;
238 q.in.user_handle = handle;
239 q.out.info = &info;
240 q0 = q;
242 #define TESTCALL(call, r) \
243 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ ##call## _r(b, tctx, &r),\
244 #call " failed"); \
245 if (!NT_STATUS_IS_OK(r.out.result)) { \
246 torture_result(tctx, TORTURE_FAIL, #call " level %u failed - %s (%s)\n", \
247 r.in.level, nt_errstr(r.out.result), __location__); \
248 ret = false; \
249 break; \
252 #define STRING_EQUAL(s1, s2, field) \
253 torture_assert_str_equal(tctx, s1, s2, "Failed to set " #field)
255 #define MEM_EQUAL(s1, s2, length, field) \
256 torture_assert_mem_equal(tctx, s1, s2, length, "Failed to set " #field)
258 #define INT_EQUAL(i1, i2, field) \
259 torture_assert_int_equal(tctx, i1, i2, "Failed to set " #field)
261 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
262 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
263 q.in.level = lvl1; \
264 TESTCALL(QueryUserInfo, q) \
265 s.in.level = lvl1; \
266 s2.in.level = lvl1; \
267 u = *info; \
268 if (lvl1 == 21) { \
269 ZERO_STRUCT(u.info21); \
270 u.info21.fields_present = fpval; \
272 init_lsa_String(&u.info ## lvl1.field1, value); \
273 TESTCALL(SetUserInfo, s) \
274 TESTCALL(SetUserInfo2, s2) \
275 init_lsa_String(&u.info ## lvl1.field1, ""); \
276 TESTCALL(QueryUserInfo, q); \
277 u = *info; \
278 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
279 q.in.level = lvl2; \
280 TESTCALL(QueryUserInfo, q) \
281 u = *info; \
282 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
283 } while (0)
285 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
286 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
287 q.in.level = lvl1; \
288 TESTCALL(QueryUserInfo, q) \
289 s.in.level = lvl1; \
290 s2.in.level = lvl1; \
291 u = *info; \
292 if (lvl1 == 21) { \
293 ZERO_STRUCT(u.info21); \
294 u.info21.fields_present = fpval; \
296 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
297 TESTCALL(SetUserInfo, s) \
298 TESTCALL(SetUserInfo2, s2) \
299 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
300 TESTCALL(QueryUserInfo, q); \
301 u = *info; \
302 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
303 q.in.level = lvl2; \
304 TESTCALL(QueryUserInfo, q) \
305 u = *info; \
306 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
307 } while (0)
309 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
310 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
311 q.in.level = lvl1; \
312 TESTCALL(QueryUserInfo, q) \
313 s.in.level = lvl1; \
314 s2.in.level = lvl1; \
315 u = *info; \
316 if (lvl1 == 21) { \
317 uint8_t *bits = u.info21.logon_hours.bits; \
318 ZERO_STRUCT(u.info21); \
319 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
320 u.info21.logon_hours.units_per_week = 168; \
321 u.info21.logon_hours.bits = bits; \
323 u.info21.fields_present = fpval; \
325 u.info ## lvl1.field1 = value; \
326 TESTCALL(SetUserInfo, s) \
327 TESTCALL(SetUserInfo2, s2) \
328 u.info ## lvl1.field1 = 0; \
329 TESTCALL(QueryUserInfo, q); \
330 u = *info; \
331 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
332 q.in.level = lvl2; \
333 TESTCALL(QueryUserInfo, q) \
334 u = *info; \
335 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
336 } while (0)
338 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
339 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
340 } while (0)
342 q0.in.level = 12;
343 do { TESTCALL(QueryUserInfo, q0) } while (0);
345 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
346 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
347 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
348 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, test_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, test_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, test_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, test_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, test_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, test_account_name, 0);
362 test_account_name = base_account_name;
363 TEST_USERINFO_STRING(21, account_name, 21, account_name, test_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 code_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);
569 char *s = generate_random_password(mem_ctx, len, len+6);
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_password(mem_ctx, len, 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 dcerpc_binding_handle *b = p->binding_handle;
619 struct samr_GetUserPwInfo pwp;
620 struct samr_PwInfo info;
621 int policy_min_pw_len = 0;
622 pwp.in.user_handle = handle;
623 pwp.out.info = &info;
625 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
626 "GetUserPwInfo failed");
627 if (NT_STATUS_IS_OK(pwp.out.result)) {
628 policy_min_pw_len = pwp.out.info->min_password_length;
630 newpass = samr_rand_pass(tctx, policy_min_pw_len);
632 s.in.user_handle = handle;
633 s.in.info = &u;
634 s.in.level = 24;
636 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
637 u.info24.password_expired = 0;
639 status = dcerpc_fetch_session_key(p, &session_key);
640 if (!NT_STATUS_IS_OK(status)) {
641 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
642 s.in.level, nt_errstr(status));
643 return false;
646 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
648 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
650 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
651 "SetUserInfo failed");
652 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
653 __location__, __FUNCTION__,
654 newpass, nt_errstr(s.out.result));
655 if (!NT_STATUS_IS_OK(s.out.result)) {
656 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
657 s.in.level, nt_errstr(s.out.result));
658 ret = false;
659 } else {
660 *password = newpass;
663 return ret;
667 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
668 struct policy_handle *handle, uint32_t fields_present,
669 char **password)
671 NTSTATUS status;
672 struct samr_SetUserInfo s;
673 union samr_UserInfo u;
674 bool ret = true;
675 DATA_BLOB session_key;
676 struct dcerpc_binding_handle *b = p->binding_handle;
677 char *newpass;
678 struct samr_GetUserPwInfo pwp;
679 struct samr_PwInfo info;
680 int policy_min_pw_len = 0;
681 pwp.in.user_handle = handle;
682 pwp.out.info = &info;
684 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
685 "GetUserPwInfo failed");
686 if (NT_STATUS_IS_OK(pwp.out.result)) {
687 policy_min_pw_len = pwp.out.info->min_password_length;
689 newpass = samr_rand_pass(tctx, policy_min_pw_len);
691 s.in.user_handle = handle;
692 s.in.info = &u;
693 s.in.level = 23;
695 ZERO_STRUCT(u);
697 u.info23.info.fields_present = fields_present;
699 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
701 status = dcerpc_fetch_session_key(p, &session_key);
702 if (!NT_STATUS_IS_OK(status)) {
703 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
704 s.in.level, nt_errstr(status));
705 return false;
708 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
710 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
712 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
713 "SetUserInfo failed");
714 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
715 __location__, __FUNCTION__,
716 newpass, nt_errstr(s.out.result));
717 if (!NT_STATUS_IS_OK(s.out.result)) {
718 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
719 s.in.level, nt_errstr(s.out.result));
720 ret = false;
721 } else {
722 *password = newpass;
725 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
727 status = dcerpc_fetch_session_key(p, &session_key);
728 if (!NT_STATUS_IS_OK(status)) {
729 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
730 s.in.level, nt_errstr(status));
731 return false;
734 /* This should break the key nicely */
735 session_key.length--;
736 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
738 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
740 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
741 "SetUserInfo failed");
742 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
743 __location__, __FUNCTION__,
744 newpass, nt_errstr(s.out.result));
745 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
746 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
747 s.in.level, nt_errstr(s.out.result));
748 ret = false;
751 return ret;
755 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
756 struct policy_handle *handle, bool makeshort,
757 char **password)
759 NTSTATUS status;
760 struct samr_SetUserInfo s;
761 union samr_UserInfo u;
762 bool ret = true;
763 DATA_BLOB session_key;
764 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
765 uint8_t confounder[16];
766 char *newpass;
767 struct dcerpc_binding_handle *b = p->binding_handle;
768 MD5_CTX ctx;
769 struct samr_GetUserPwInfo pwp;
770 struct samr_PwInfo info;
771 int policy_min_pw_len = 0;
772 pwp.in.user_handle = handle;
773 pwp.out.info = &info;
775 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
776 "GetUserPwInfo failed");
777 if (NT_STATUS_IS_OK(pwp.out.result)) {
778 policy_min_pw_len = pwp.out.info->min_password_length;
780 if (makeshort && policy_min_pw_len) {
781 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
782 } else {
783 newpass = samr_rand_pass(tctx, policy_min_pw_len);
786 s.in.user_handle = handle;
787 s.in.info = &u;
788 s.in.level = 26;
790 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
791 u.info26.password_expired = 0;
793 status = dcerpc_fetch_session_key(p, &session_key);
794 if (!NT_STATUS_IS_OK(status)) {
795 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
796 s.in.level, nt_errstr(status));
797 return false;
800 generate_random_buffer((uint8_t *)confounder, 16);
802 MD5Init(&ctx);
803 MD5Update(&ctx, confounder, 16);
804 MD5Update(&ctx, session_key.data, session_key.length);
805 MD5Final(confounded_session_key.data, &ctx);
807 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
808 memcpy(&u.info26.password.data[516], confounder, 16);
810 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
812 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
813 "SetUserInfo failed");
814 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
815 __location__, __FUNCTION__,
816 newpass, nt_errstr(s.out.result));
817 if (!NT_STATUS_IS_OK(s.out.result)) {
818 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
819 s.in.level, nt_errstr(s.out.result));
820 ret = false;
821 } else {
822 *password = newpass;
825 /* This should break the key nicely */
826 confounded_session_key.data[0]++;
828 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
829 memcpy(&u.info26.password.data[516], confounder, 16);
831 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
833 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
834 "SetUserInfo failed");
835 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
836 __location__, __FUNCTION__,
837 newpass, nt_errstr(s.out.result));
838 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
839 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
840 s.in.level, nt_errstr(s.out.result));
841 ret = false;
842 } else {
843 *password = newpass;
846 return ret;
849 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
850 struct policy_handle *handle, uint32_t fields_present,
851 char **password)
853 NTSTATUS status;
854 struct samr_SetUserInfo s;
855 union samr_UserInfo u;
856 bool ret = true;
857 DATA_BLOB session_key;
858 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
859 MD5_CTX ctx;
860 uint8_t confounder[16];
861 char *newpass;
862 struct dcerpc_binding_handle *b = p->binding_handle;
863 struct samr_GetUserPwInfo pwp;
864 struct samr_PwInfo info;
865 int policy_min_pw_len = 0;
866 pwp.in.user_handle = handle;
867 pwp.out.info = &info;
869 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
870 "GetUserPwInfo failed");
871 if (NT_STATUS_IS_OK(pwp.out.result)) {
872 policy_min_pw_len = pwp.out.info->min_password_length;
874 newpass = samr_rand_pass(tctx, policy_min_pw_len);
876 s.in.user_handle = handle;
877 s.in.info = &u;
878 s.in.level = 25;
880 ZERO_STRUCT(u);
882 u.info25.info.fields_present = fields_present;
884 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
886 status = dcerpc_fetch_session_key(p, &session_key);
887 if (!NT_STATUS_IS_OK(status)) {
888 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
889 s.in.level, nt_errstr(status));
890 return false;
893 generate_random_buffer((uint8_t *)confounder, 16);
895 MD5Init(&ctx);
896 MD5Update(&ctx, confounder, 16);
897 MD5Update(&ctx, session_key.data, session_key.length);
898 MD5Final(confounded_session_key.data, &ctx);
900 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
901 memcpy(&u.info25.password.data[516], confounder, 16);
903 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
905 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
906 "SetUserInfo failed");
907 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
908 __location__, __FUNCTION__,
909 newpass, nt_errstr(s.out.result));
910 if (!NT_STATUS_IS_OK(s.out.result)) {
911 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
912 s.in.level, nt_errstr(s.out.result));
913 ret = false;
914 } else {
915 *password = newpass;
918 /* This should break the key nicely */
919 confounded_session_key.data[0]++;
921 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
922 memcpy(&u.info25.password.data[516], confounder, 16);
924 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
926 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
927 "SetUserInfo failed");
928 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
929 __location__, __FUNCTION__,
930 newpass, nt_errstr(s.out.result));
931 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
932 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
933 s.in.level, nt_errstr(s.out.result));
934 ret = false;
937 return ret;
940 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
941 struct policy_handle *handle, char **password)
943 NTSTATUS status;
944 struct samr_SetUserInfo s;
945 union samr_UserInfo u;
946 bool ret = true;
947 DATA_BLOB session_key;
948 char *newpass;
949 struct dcerpc_binding_handle *b = p->binding_handle;
950 struct samr_GetUserPwInfo pwp;
951 struct samr_PwInfo info;
952 int policy_min_pw_len = 0;
953 uint8_t lm_hash[16], nt_hash[16];
955 pwp.in.user_handle = handle;
956 pwp.out.info = &info;
958 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
959 "GetUserPwInfo failed");
960 if (NT_STATUS_IS_OK(pwp.out.result)) {
961 policy_min_pw_len = pwp.out.info->min_password_length;
963 newpass = samr_rand_pass(tctx, policy_min_pw_len);
965 s.in.user_handle = handle;
966 s.in.info = &u;
967 s.in.level = 18;
969 ZERO_STRUCT(u);
971 u.info18.nt_pwd_active = true;
972 u.info18.lm_pwd_active = true;
974 E_md4hash(newpass, nt_hash);
975 E_deshash(newpass, lm_hash);
977 status = dcerpc_fetch_session_key(p, &session_key);
978 if (!NT_STATUS_IS_OK(status)) {
979 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
980 s.in.level, nt_errstr(status));
981 return false;
985 DATA_BLOB in,out;
986 in = data_blob_const(nt_hash, 16);
987 out = data_blob_talloc_zero(tctx, 16);
988 sess_crypt_blob(&out, &in, &session_key, true);
989 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
992 DATA_BLOB in,out;
993 in = data_blob_const(lm_hash, 16);
994 out = data_blob_talloc_zero(tctx, 16);
995 sess_crypt_blob(&out, &in, &session_key, true);
996 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
999 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
1001 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1002 "SetUserInfo failed");
1003 if (!NT_STATUS_IS_OK(s.out.result)) {
1004 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1005 s.in.level, nt_errstr(s.out.result));
1006 ret = false;
1007 } else {
1008 *password = newpass;
1011 return ret;
1014 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1015 struct policy_handle *handle, uint32_t fields_present,
1016 char **password)
1018 NTSTATUS status;
1019 struct samr_SetUserInfo s;
1020 union samr_UserInfo u;
1021 bool ret = true;
1022 DATA_BLOB session_key;
1023 char *newpass;
1024 struct dcerpc_binding_handle *b = p->binding_handle;
1025 struct samr_GetUserPwInfo pwp;
1026 struct samr_PwInfo info;
1027 int policy_min_pw_len = 0;
1028 uint8_t lm_hash[16], nt_hash[16];
1030 pwp.in.user_handle = handle;
1031 pwp.out.info = &info;
1033 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1034 "GetUserPwInfo failed");
1035 if (NT_STATUS_IS_OK(pwp.out.result)) {
1036 policy_min_pw_len = pwp.out.info->min_password_length;
1038 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1040 s.in.user_handle = handle;
1041 s.in.info = &u;
1042 s.in.level = 21;
1044 E_md4hash(newpass, nt_hash);
1045 E_deshash(newpass, lm_hash);
1047 ZERO_STRUCT(u);
1049 u.info21.fields_present = fields_present;
1051 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1052 u.info21.lm_owf_password.length = 16;
1053 u.info21.lm_owf_password.size = 16;
1054 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1055 u.info21.lm_password_set = true;
1058 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1059 u.info21.nt_owf_password.length = 16;
1060 u.info21.nt_owf_password.size = 16;
1061 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1062 u.info21.nt_password_set = true;
1065 status = dcerpc_fetch_session_key(p, &session_key);
1066 if (!NT_STATUS_IS_OK(status)) {
1067 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1068 s.in.level, nt_errstr(status));
1069 return false;
1072 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1073 DATA_BLOB in,out;
1074 in = data_blob_const(u.info21.lm_owf_password.array,
1075 u.info21.lm_owf_password.length);
1076 out = data_blob_talloc_zero(tctx, 16);
1077 sess_crypt_blob(&out, &in, &session_key, true);
1078 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1081 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1082 DATA_BLOB in,out;
1083 in = data_blob_const(u.info21.nt_owf_password.array,
1084 u.info21.nt_owf_password.length);
1085 out = data_blob_talloc_zero(tctx, 16);
1086 sess_crypt_blob(&out, &in, &session_key, true);
1087 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1090 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1092 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1093 "SetUserInfo failed");
1094 if (!NT_STATUS_IS_OK(s.out.result)) {
1095 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1096 s.in.level, nt_errstr(s.out.result));
1097 ret = false;
1098 } else {
1099 *password = newpass;
1102 /* try invalid length */
1103 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1105 u.info21.nt_owf_password.length++;
1107 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1108 "SetUserInfo failed");
1109 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1110 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1111 s.in.level, nt_errstr(s.out.result));
1112 ret = false;
1116 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1118 u.info21.lm_owf_password.length++;
1120 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1121 "SetUserInfo failed");
1122 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1123 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1124 s.in.level, nt_errstr(s.out.result));
1125 ret = false;
1129 return ret;
1132 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1133 struct torture_context *tctx,
1134 struct policy_handle *handle,
1135 uint16_t level,
1136 uint32_t fields_present,
1137 char **password, uint8_t password_expired,
1138 bool use_setinfo2,
1139 bool *matched_expected_error)
1141 NTSTATUS status;
1142 NTSTATUS expected_error = NT_STATUS_OK;
1143 struct samr_SetUserInfo s;
1144 struct samr_SetUserInfo2 s2;
1145 union samr_UserInfo u;
1146 bool ret = true;
1147 DATA_BLOB session_key;
1148 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1149 MD5_CTX ctx;
1150 uint8_t confounder[16];
1151 char *newpass;
1152 struct dcerpc_binding_handle *b = p->binding_handle;
1153 struct samr_GetUserPwInfo pwp;
1154 struct samr_PwInfo info;
1155 int policy_min_pw_len = 0;
1156 const char *comment = NULL;
1157 uint8_t lm_hash[16], nt_hash[16];
1159 pwp.in.user_handle = handle;
1160 pwp.out.info = &info;
1162 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1163 "GetUserPwInfo failed");
1164 if (NT_STATUS_IS_OK(pwp.out.result)) {
1165 policy_min_pw_len = pwp.out.info->min_password_length;
1167 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1169 if (use_setinfo2) {
1170 s2.in.user_handle = handle;
1171 s2.in.info = &u;
1172 s2.in.level = level;
1173 } else {
1174 s.in.user_handle = handle;
1175 s.in.info = &u;
1176 s.in.level = level;
1179 if (fields_present & SAMR_FIELD_COMMENT) {
1180 comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
1183 ZERO_STRUCT(u);
1185 switch (level) {
1186 case 18:
1187 E_md4hash(newpass, nt_hash);
1188 E_deshash(newpass, lm_hash);
1190 u.info18.nt_pwd_active = true;
1191 u.info18.lm_pwd_active = true;
1192 u.info18.password_expired = password_expired;
1194 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1195 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1197 break;
1198 case 21:
1199 E_md4hash(newpass, nt_hash);
1200 E_deshash(newpass, lm_hash);
1202 u.info21.fields_present = fields_present;
1203 u.info21.password_expired = password_expired;
1204 u.info21.comment.string = comment;
1206 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1207 u.info21.lm_owf_password.length = 16;
1208 u.info21.lm_owf_password.size = 16;
1209 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1210 u.info21.lm_password_set = true;
1213 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1214 u.info21.nt_owf_password.length = 16;
1215 u.info21.nt_owf_password.size = 16;
1216 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1217 u.info21.nt_password_set = true;
1220 break;
1221 case 23:
1222 u.info23.info.fields_present = fields_present;
1223 u.info23.info.password_expired = password_expired;
1224 u.info23.info.comment.string = comment;
1226 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1228 break;
1229 case 24:
1230 u.info24.password_expired = password_expired;
1232 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1234 break;
1235 case 25:
1236 u.info25.info.fields_present = fields_present;
1237 u.info25.info.password_expired = password_expired;
1238 u.info25.info.comment.string = comment;
1240 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1242 break;
1243 case 26:
1244 u.info26.password_expired = password_expired;
1246 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1248 break;
1251 status = dcerpc_fetch_session_key(p, &session_key);
1252 if (!NT_STATUS_IS_OK(status)) {
1253 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1254 s.in.level, nt_errstr(status));
1255 return false;
1258 generate_random_buffer((uint8_t *)confounder, 16);
1260 MD5Init(&ctx);
1261 MD5Update(&ctx, confounder, 16);
1262 MD5Update(&ctx, session_key.data, session_key.length);
1263 MD5Final(confounded_session_key.data, &ctx);
1265 switch (level) {
1266 case 18:
1268 DATA_BLOB in,out;
1269 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1270 out = data_blob_talloc_zero(tctx, 16);
1271 sess_crypt_blob(&out, &in, &session_key, true);
1272 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1275 DATA_BLOB in,out;
1276 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1277 out = data_blob_talloc_zero(tctx, 16);
1278 sess_crypt_blob(&out, &in, &session_key, true);
1279 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1282 break;
1283 case 21:
1284 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1285 DATA_BLOB in,out;
1286 in = data_blob_const(u.info21.lm_owf_password.array,
1287 u.info21.lm_owf_password.length);
1288 out = data_blob_talloc_zero(tctx, 16);
1289 sess_crypt_blob(&out, &in, &session_key, true);
1290 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1292 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1293 DATA_BLOB in,out;
1294 in = data_blob_const(u.info21.nt_owf_password.array,
1295 u.info21.nt_owf_password.length);
1296 out = data_blob_talloc_zero(tctx, 16);
1297 sess_crypt_blob(&out, &in, &session_key, true);
1298 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1300 break;
1301 case 23:
1302 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1303 break;
1304 case 24:
1305 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1306 break;
1307 case 25:
1308 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1309 memcpy(&u.info25.password.data[516], confounder, 16);
1310 break;
1311 case 26:
1312 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1313 memcpy(&u.info26.password.data[516], confounder, 16);
1314 break;
1317 if (use_setinfo2) {
1318 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1319 "SetUserInfo2 failed");
1320 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1321 __location__, __FUNCTION__,
1322 newpass, nt_errstr(s2.out.result));
1323 status = s2.out.result;
1324 } else {
1325 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1326 "SetUserInfo failed");
1327 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1328 __location__, __FUNCTION__,
1329 newpass, nt_errstr(s.out.result));
1330 status = s.out.result;
1333 if (!NT_STATUS_IS_OK(status)) {
1334 if (fields_present == 0) {
1335 expected_error = NT_STATUS_INVALID_PARAMETER;
1337 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1338 expected_error = NT_STATUS_ACCESS_DENIED;
1342 if (!NT_STATUS_IS_OK(expected_error)) {
1343 if (use_setinfo2) {
1344 torture_assert_ntstatus_equal(tctx,
1345 s2.out.result,
1346 expected_error, "SetUserInfo2 failed");
1347 } else {
1348 torture_assert_ntstatus_equal(tctx,
1349 s.out.result,
1350 expected_error, "SetUserInfo failed");
1352 *matched_expected_error = true;
1353 return true;
1356 if (!NT_STATUS_IS_OK(status)) {
1357 torture_result(tctx, TORTURE_FAIL, "SetUserInfo%s level %u failed - %s\n",
1358 use_setinfo2 ? "2":"", level, nt_errstr(status));
1359 ret = false;
1360 } else {
1361 *password = newpass;
1364 return ret;
1367 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1368 struct torture_context *tctx,
1369 struct policy_handle *handle)
1371 struct samr_SetAliasInfo r;
1372 struct samr_QueryAliasInfo q;
1373 union samr_AliasInfo *info;
1374 uint16_t levels[] = {2, 3};
1375 int i;
1376 bool ret = true;
1378 /* Ignoring switch level 1, as that includes the number of members for the alias
1379 * and setting this to a wrong value might have negative consequences
1382 for (i=0;i<ARRAY_SIZE(levels);i++) {
1383 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1385 r.in.alias_handle = handle;
1386 r.in.level = levels[i];
1387 r.in.info = talloc(tctx, union samr_AliasInfo);
1388 switch (r.in.level) {
1389 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1390 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1391 "Test Description, should test I18N as well"); break;
1392 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1395 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1396 "SetAliasInfo failed");
1397 if (!NT_STATUS_IS_OK(r.out.result)) {
1398 torture_result(tctx, TORTURE_FAIL, "SetAliasInfo level %u failed - %s\n",
1399 levels[i], nt_errstr(r.out.result));
1400 ret = false;
1403 q.in.alias_handle = handle;
1404 q.in.level = levels[i];
1405 q.out.info = &info;
1407 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1408 "QueryAliasInfo failed");
1409 if (!NT_STATUS_IS_OK(q.out.result)) {
1410 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
1411 levels[i], nt_errstr(q.out.result));
1412 ret = false;
1416 return ret;
1419 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1420 struct torture_context *tctx,
1421 struct policy_handle *user_handle)
1423 struct samr_GetGroupsForUser r;
1424 struct samr_RidWithAttributeArray *rids = NULL;
1426 torture_comment(tctx, "Testing GetGroupsForUser\n");
1428 r.in.user_handle = user_handle;
1429 r.out.rids = &rids;
1431 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1432 "GetGroupsForUser failed");
1433 torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1435 return true;
1439 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1440 struct lsa_String *domain_name)
1442 struct samr_GetDomPwInfo r;
1443 struct samr_PwInfo info;
1444 struct dcerpc_binding_handle *b = p->binding_handle;
1446 r.in.domain_name = domain_name;
1447 r.out.info = &info;
1449 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1451 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1452 "GetDomPwInfo failed");
1453 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1455 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1456 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1458 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1459 "GetDomPwInfo failed");
1460 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1462 r.in.domain_name->string = "\\\\__NONAME__";
1463 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1465 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1466 "GetDomPwInfo failed");
1467 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1469 r.in.domain_name->string = "\\\\Builtin";
1470 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1472 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1473 "GetDomPwInfo failed");
1474 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1476 return true;
1479 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1480 struct torture_context *tctx,
1481 struct policy_handle *handle)
1483 struct samr_GetUserPwInfo r;
1484 struct samr_PwInfo info;
1486 torture_comment(tctx, "Testing GetUserPwInfo\n");
1488 r.in.user_handle = handle;
1489 r.out.info = &info;
1491 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1492 "GetUserPwInfo failed");
1493 torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1495 return true;
1498 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1499 struct torture_context *tctx,
1500 struct policy_handle *domain_handle, const char *name,
1501 uint32_t *rid)
1503 NTSTATUS status;
1504 struct samr_LookupNames n;
1505 struct lsa_String sname[2];
1506 struct samr_Ids rids, types;
1508 init_lsa_String(&sname[0], name);
1510 n.in.domain_handle = domain_handle;
1511 n.in.num_names = 1;
1512 n.in.names = sname;
1513 n.out.rids = &rids;
1514 n.out.types = &types;
1515 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1516 if (!NT_STATUS_IS_OK(status)) {
1517 return status;
1519 if (NT_STATUS_IS_OK(n.out.result)) {
1520 *rid = n.out.rids->ids[0];
1521 } else {
1522 return n.out.result;
1525 init_lsa_String(&sname[1], "xxNONAMExx");
1526 n.in.num_names = 2;
1527 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 return status;
1531 if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1532 torture_result(tctx, TORTURE_FAIL, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1533 if (NT_STATUS_IS_OK(n.out.result)) {
1534 return NT_STATUS_UNSUCCESSFUL;
1536 return n.out.result;
1539 n.in.num_names = 0;
1540 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 return status;
1544 if (!NT_STATUS_IS_OK(n.out.result)) {
1545 torture_result(tctx, TORTURE_FAIL, "LookupNames[0] failed - %s\n", nt_errstr(status));
1546 return n.out.result;
1549 init_lsa_String(&sname[0], "xxNONAMExx");
1550 n.in.num_names = 1;
1551 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1552 if (!NT_STATUS_IS_OK(status)) {
1553 return status;
1555 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1556 torture_result(tctx, TORTURE_FAIL, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1557 if (NT_STATUS_IS_OK(n.out.result)) {
1558 return NT_STATUS_UNSUCCESSFUL;
1560 return n.out.result;
1563 init_lsa_String(&sname[0], "xxNONAMExx");
1564 init_lsa_String(&sname[1], "xxNONAME2xx");
1565 n.in.num_names = 2;
1566 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 return status;
1570 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1571 torture_result(tctx, TORTURE_FAIL, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1572 if (NT_STATUS_IS_OK(n.out.result)) {
1573 return NT_STATUS_UNSUCCESSFUL;
1575 return n.out.result;
1578 return NT_STATUS_OK;
1581 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1582 struct torture_context *tctx,
1583 struct policy_handle *domain_handle,
1584 const char *name, struct policy_handle *user_handle)
1586 NTSTATUS status;
1587 struct samr_OpenUser r;
1588 uint32_t rid;
1590 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 return status;
1595 r.in.domain_handle = domain_handle;
1596 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1597 r.in.rid = rid;
1598 r.out.user_handle = user_handle;
1599 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1600 if (!NT_STATUS_IS_OK(status)) {
1601 return status;
1603 if (!NT_STATUS_IS_OK(r.out.result)) {
1604 torture_result(tctx, TORTURE_FAIL, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1607 return r.out.result;
1610 #if 0
1611 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1612 struct torture_context *tctx,
1613 struct policy_handle *handle)
1615 NTSTATUS status;
1616 struct samr_ChangePasswordUser r;
1617 bool ret = true;
1618 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1619 struct policy_handle user_handle;
1620 char *oldpass = "test";
1621 char *newpass = "test2";
1622 uint8_t old_nt_hash[16], new_nt_hash[16];
1623 uint8_t old_lm_hash[16], new_lm_hash[16];
1625 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1626 if (!NT_STATUS_IS_OK(status)) {
1627 return false;
1630 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1632 torture_comment(tctx, "old password: %s\n", oldpass);
1633 torture_comment(tctx, "new password: %s\n", newpass);
1635 E_md4hash(oldpass, old_nt_hash);
1636 E_md4hash(newpass, new_nt_hash);
1637 E_deshash(oldpass, old_lm_hash);
1638 E_deshash(newpass, new_lm_hash);
1640 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1641 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1642 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1643 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1644 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1645 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1647 r.in.handle = &user_handle;
1648 r.in.lm_present = 1;
1649 r.in.old_lm_crypted = &hash1;
1650 r.in.new_lm_crypted = &hash2;
1651 r.in.nt_present = 1;
1652 r.in.old_nt_crypted = &hash3;
1653 r.in.new_nt_crypted = &hash4;
1654 r.in.cross1_present = 1;
1655 r.in.nt_cross = &hash5;
1656 r.in.cross2_present = 1;
1657 r.in.lm_cross = &hash6;
1659 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1660 "ChangePasswordUser failed");
1661 if (!NT_STATUS_IS_OK(r.out.result)) {
1662 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1663 ret = false;
1666 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1667 ret = false;
1670 return ret;
1672 #endif
1674 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1675 struct torture_context *tctx,
1676 const char *acct_name,
1677 struct policy_handle *handle, char **password)
1679 NTSTATUS status;
1680 struct samr_ChangePasswordUser r;
1681 bool ret = true;
1682 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1683 struct policy_handle user_handle;
1684 char *oldpass;
1685 uint8_t old_nt_hash[16], new_nt_hash[16];
1686 uint8_t old_lm_hash[16], new_lm_hash[16];
1687 bool changed = true;
1689 char *newpass;
1690 struct samr_GetUserPwInfo pwp;
1691 struct samr_PwInfo info;
1692 int policy_min_pw_len = 0;
1694 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1695 if (!NT_STATUS_IS_OK(status)) {
1696 return false;
1698 pwp.in.user_handle = &user_handle;
1699 pwp.out.info = &info;
1701 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1702 "GetUserPwInfo failed");
1703 if (NT_STATUS_IS_OK(pwp.out.result)) {
1704 policy_min_pw_len = pwp.out.info->min_password_length;
1706 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1708 torture_comment(tctx, "Testing ChangePasswordUser\n");
1710 torture_assert(tctx, *password != NULL,
1711 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1713 oldpass = *password;
1715 E_md4hash(oldpass, old_nt_hash);
1716 E_md4hash(newpass, new_nt_hash);
1717 E_deshash(oldpass, old_lm_hash);
1718 E_deshash(newpass, new_lm_hash);
1720 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1721 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1722 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1723 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1724 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1725 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1727 r.in.user_handle = &user_handle;
1728 r.in.lm_present = 1;
1729 /* Break the NT hash */
1730 hash3.hash[0]++;
1731 r.in.old_lm_crypted = &hash1;
1732 r.in.new_lm_crypted = &hash2;
1733 r.in.nt_present = 1;
1734 r.in.old_nt_crypted = &hash3;
1735 r.in.new_nt_crypted = &hash4;
1736 r.in.cross1_present = 1;
1737 r.in.nt_cross = &hash5;
1738 r.in.cross2_present = 1;
1739 r.in.lm_cross = &hash6;
1741 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1742 "ChangePasswordUser failed");
1743 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1744 __location__, __FUNCTION__,
1745 oldpass, newpass, nt_errstr(r.out.result));
1747 /* Do not proceed if this call has been removed */
1748 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
1749 torture_skip(tctx, "ValidatePassword not supported by server\n");
1752 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1753 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1754 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1757 /* Unbreak the NT hash */
1758 hash3.hash[0]--;
1760 r.in.user_handle = &user_handle;
1761 r.in.lm_present = 1;
1762 r.in.old_lm_crypted = &hash1;
1763 r.in.new_lm_crypted = &hash2;
1764 /* Break the LM hash */
1765 hash1.hash[0]--;
1766 r.in.nt_present = 1;
1767 r.in.old_nt_crypted = &hash3;
1768 r.in.new_nt_crypted = &hash4;
1769 r.in.cross1_present = 1;
1770 r.in.nt_cross = &hash5;
1771 r.in.cross2_present = 1;
1772 r.in.lm_cross = &hash6;
1774 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1775 "ChangePasswordUser failed");
1776 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1777 __location__, __FUNCTION__,
1778 oldpass, newpass, nt_errstr(r.out.result));
1779 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1780 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1781 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1784 /* Unbreak the NT hash */
1785 hash3.hash[0]--;
1787 r.in.user_handle = &user_handle;
1788 r.in.lm_present = 1;
1789 r.in.old_lm_crypted = &hash1;
1790 r.in.new_lm_crypted = &hash2;
1791 r.in.nt_present = 1;
1792 r.in.old_nt_crypted = &hash3;
1793 r.in.new_nt_crypted = &hash4;
1794 r.in.cross1_present = 1;
1795 r.in.nt_cross = &hash5;
1796 r.in.cross2_present = 1;
1797 /* Break the LM cross */
1798 hash6.hash[0]++;
1799 r.in.lm_cross = &hash6;
1801 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1802 "ChangePasswordUser failed");
1803 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1804 __location__, __FUNCTION__,
1805 oldpass, newpass, nt_errstr(r.out.result));
1806 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1807 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1809 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
1810 ret = false;
1813 /* Unbreak the LM cross */
1814 hash6.hash[0]--;
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 /* Break the NT cross */
1825 hash5.hash[0]++;
1826 r.in.nt_cross = &hash5;
1827 r.in.cross2_present = 1;
1828 r.in.lm_cross = &hash6;
1830 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1831 "ChangePasswordUser failed");
1832 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1833 __location__, __FUNCTION__,
1834 oldpass, newpass, nt_errstr(r.out.result));
1835 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1836 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1838 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
1839 ret = false;
1842 /* Unbreak the NT cross */
1843 hash5.hash[0]--;
1846 /* Reset the hashes to not broken values */
1847 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1848 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1849 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1850 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1851 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1852 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1854 r.in.user_handle = &user_handle;
1855 r.in.lm_present = 1;
1856 r.in.old_lm_crypted = &hash1;
1857 r.in.new_lm_crypted = &hash2;
1858 r.in.nt_present = 1;
1859 r.in.old_nt_crypted = &hash3;
1860 r.in.new_nt_crypted = &hash4;
1861 r.in.cross1_present = 1;
1862 r.in.nt_cross = &hash5;
1863 r.in.cross2_present = 0;
1864 r.in.lm_cross = NULL;
1866 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1867 "ChangePasswordUser failed");
1868 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1869 __location__, __FUNCTION__,
1870 oldpass, newpass, nt_errstr(r.out.result));
1871 if (NT_STATUS_IS_OK(r.out.result)) {
1872 changed = true;
1873 *password = newpass;
1874 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1875 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1876 ret = false;
1879 oldpass = newpass;
1880 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1882 E_md4hash(oldpass, old_nt_hash);
1883 E_md4hash(newpass, new_nt_hash);
1884 E_deshash(oldpass, old_lm_hash);
1885 E_deshash(newpass, new_lm_hash);
1888 /* Reset the hashes to not broken values */
1889 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1890 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1891 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1892 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1893 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1894 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1896 r.in.user_handle = &user_handle;
1897 r.in.lm_present = 1;
1898 r.in.old_lm_crypted = &hash1;
1899 r.in.new_lm_crypted = &hash2;
1900 r.in.nt_present = 1;
1901 r.in.old_nt_crypted = &hash3;
1902 r.in.new_nt_crypted = &hash4;
1903 r.in.cross1_present = 0;
1904 r.in.nt_cross = NULL;
1905 r.in.cross2_present = 1;
1906 r.in.lm_cross = &hash6;
1908 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1909 "ChangePasswordUser failed");
1910 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1911 __location__, __FUNCTION__,
1912 oldpass, newpass, nt_errstr(r.out.result));
1913 if (NT_STATUS_IS_OK(r.out.result)) {
1914 changed = true;
1915 *password = newpass;
1916 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1917 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1918 ret = false;
1921 oldpass = newpass;
1922 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1924 E_md4hash(oldpass, old_nt_hash);
1925 E_md4hash(newpass, new_nt_hash);
1926 E_deshash(oldpass, old_lm_hash);
1927 E_deshash(newpass, new_lm_hash);
1930 /* Reset the hashes to not broken values */
1931 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1932 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1933 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1934 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1935 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1936 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1938 r.in.user_handle = &user_handle;
1939 r.in.lm_present = 1;
1940 r.in.old_lm_crypted = &hash1;
1941 r.in.new_lm_crypted = &hash2;
1942 r.in.nt_present = 1;
1943 r.in.old_nt_crypted = &hash3;
1944 r.in.new_nt_crypted = &hash4;
1945 r.in.cross1_present = 1;
1946 r.in.nt_cross = &hash5;
1947 r.in.cross2_present = 1;
1948 r.in.lm_cross = &hash6;
1950 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1951 "ChangePasswordUser failed");
1952 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1953 __location__, __FUNCTION__,
1954 oldpass, newpass, nt_errstr(r.out.result));
1955 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1956 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1957 } else if (!NT_STATUS_IS_OK(r.out.result)) {
1958 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1959 ret = false;
1960 } else {
1961 changed = true;
1962 *password = newpass;
1965 r.in.user_handle = &user_handle;
1966 r.in.lm_present = 1;
1967 r.in.old_lm_crypted = &hash1;
1968 r.in.new_lm_crypted = &hash2;
1969 r.in.nt_present = 1;
1970 r.in.old_nt_crypted = &hash3;
1971 r.in.new_nt_crypted = &hash4;
1972 r.in.cross1_present = 1;
1973 r.in.nt_cross = &hash5;
1974 r.in.cross2_present = 1;
1975 r.in.lm_cross = &hash6;
1977 if (changed) {
1978 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1979 "ChangePasswordUser failed");
1980 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1981 __location__, __FUNCTION__,
1982 oldpass, newpass, nt_errstr(r.out.result));
1983 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1984 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1985 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1986 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
1987 ret = false;
1992 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
1993 ret = false;
1996 return ret;
2000 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
2001 struct torture_context *tctx,
2002 const char *acct_name,
2003 struct policy_handle *handle, char **password)
2005 struct samr_OemChangePasswordUser2 r;
2006 bool ret = true;
2007 struct samr_Password lm_verifier;
2008 struct samr_CryptPassword lm_pass;
2009 struct lsa_AsciiString server, account, account_bad;
2010 char *oldpass;
2011 char *newpass;
2012 struct dcerpc_binding_handle *b = p->binding_handle;
2013 uint8_t old_lm_hash[16], new_lm_hash[16];
2015 struct samr_GetDomPwInfo dom_pw_info;
2016 struct samr_PwInfo info;
2017 int policy_min_pw_len = 0;
2019 struct lsa_String domain_name;
2021 domain_name.string = "";
2022 dom_pw_info.in.domain_name = &domain_name;
2023 dom_pw_info.out.info = &info;
2025 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
2027 torture_assert(tctx, *password != NULL,
2028 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
2030 oldpass = *password;
2032 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2033 "GetDomPwInfo failed");
2034 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2035 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2038 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2040 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2041 account.string = acct_name;
2043 E_deshash(oldpass, old_lm_hash);
2044 E_deshash(newpass, new_lm_hash);
2046 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2047 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2048 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2050 r.in.server = &server;
2051 r.in.account = &account;
2052 r.in.password = &lm_pass;
2053 r.in.hash = &lm_verifier;
2055 /* Break the verification */
2056 lm_verifier.hash[0]++;
2058 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2059 "OemChangePasswordUser2 failed");
2060 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2061 __location__, __FUNCTION__,
2062 oldpass, newpass, nt_errstr(r.out.result));
2064 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2065 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2066 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2067 nt_errstr(r.out.result));
2068 ret = false;
2071 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2072 /* Break the old password */
2073 old_lm_hash[0]++;
2074 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2075 /* unbreak it for the next operation */
2076 old_lm_hash[0]--;
2077 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2079 r.in.server = &server;
2080 r.in.account = &account;
2081 r.in.password = &lm_pass;
2082 r.in.hash = &lm_verifier;
2084 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2085 "OemChangePasswordUser2 failed");
2086 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2087 __location__, __FUNCTION__,
2088 oldpass, newpass, nt_errstr(r.out.result));
2090 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2091 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2092 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2093 nt_errstr(r.out.result));
2094 ret = false;
2097 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2098 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2100 r.in.server = &server;
2101 r.in.account = &account;
2102 r.in.password = &lm_pass;
2103 r.in.hash = NULL;
2105 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2106 "OemChangePasswordUser2 failed");
2107 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2108 __location__, __FUNCTION__,
2109 oldpass, newpass, nt_errstr(r.out.result));
2111 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2112 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2113 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2114 nt_errstr(r.out.result));
2115 ret = false;
2118 /* This shouldn't be a valid name */
2119 account_bad.string = TEST_ACCOUNT_NAME "XX";
2120 r.in.account = &account_bad;
2122 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2123 "OemChangePasswordUser2 failed");
2124 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2125 __location__, __FUNCTION__,
2126 oldpass, newpass, nt_errstr(r.out.result));
2128 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2129 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2130 nt_errstr(r.out.result));
2131 ret = false;
2134 /* This shouldn't be a valid name */
2135 account_bad.string = TEST_ACCOUNT_NAME "XX";
2136 r.in.account = &account_bad;
2137 r.in.password = &lm_pass;
2138 r.in.hash = &lm_verifier;
2140 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2141 "OemChangePasswordUser2 failed");
2142 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2143 __location__, __FUNCTION__,
2144 oldpass, newpass, nt_errstr(r.out.result));
2146 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2147 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2148 nt_errstr(r.out.result));
2149 ret = false;
2152 /* This shouldn't be a valid name */
2153 account_bad.string = TEST_ACCOUNT_NAME "XX";
2154 r.in.account = &account_bad;
2155 r.in.password = NULL;
2156 r.in.hash = &lm_verifier;
2158 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2159 "OemChangePasswordUser2 failed");
2160 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2161 __location__, __FUNCTION__,
2162 oldpass, newpass, nt_errstr(r.out.result));
2164 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2165 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2166 nt_errstr(r.out.result));
2167 ret = false;
2170 E_deshash(oldpass, old_lm_hash);
2171 E_deshash(newpass, new_lm_hash);
2173 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2174 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2175 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2177 r.in.server = &server;
2178 r.in.account = &account;
2179 r.in.password = &lm_pass;
2180 r.in.hash = &lm_verifier;
2182 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2183 "OemChangePasswordUser2 failed");
2184 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2185 __location__, __FUNCTION__,
2186 oldpass, newpass, nt_errstr(r.out.result));
2188 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2189 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2190 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2191 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2192 ret = false;
2193 } else {
2194 *password = newpass;
2197 return ret;
2201 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2202 const char *acct_name,
2203 char **password,
2204 char *newpass, bool allow_password_restriction)
2206 struct samr_ChangePasswordUser2 r;
2207 bool ret = true;
2208 struct lsa_String server, account;
2209 struct samr_CryptPassword nt_pass, lm_pass;
2210 struct samr_Password nt_verifier, lm_verifier;
2211 char *oldpass;
2212 struct dcerpc_binding_handle *b = p->binding_handle;
2213 uint8_t old_nt_hash[16], new_nt_hash[16];
2214 uint8_t old_lm_hash[16], new_lm_hash[16];
2216 struct samr_GetDomPwInfo dom_pw_info;
2217 struct samr_PwInfo info;
2219 struct lsa_String domain_name;
2221 domain_name.string = "";
2222 dom_pw_info.in.domain_name = &domain_name;
2223 dom_pw_info.out.info = &info;
2225 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2227 torture_assert(tctx, *password != NULL,
2228 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2229 oldpass = *password;
2231 if (!newpass) {
2232 int policy_min_pw_len = 0;
2233 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2234 "GetDomPwInfo failed");
2235 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2236 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2239 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2242 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2243 init_lsa_String(&account, acct_name);
2245 E_md4hash(oldpass, old_nt_hash);
2246 E_md4hash(newpass, new_nt_hash);
2248 E_deshash(oldpass, old_lm_hash);
2249 E_deshash(newpass, new_lm_hash);
2251 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2252 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2253 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2255 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2256 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2257 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2259 r.in.server = &server;
2260 r.in.account = &account;
2261 r.in.nt_password = &nt_pass;
2262 r.in.nt_verifier = &nt_verifier;
2263 r.in.lm_change = 1;
2264 r.in.lm_password = &lm_pass;
2265 r.in.lm_verifier = &lm_verifier;
2267 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2268 "ChangePasswordUser2 failed");
2269 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2270 __location__, __FUNCTION__,
2271 oldpass, newpass, nt_errstr(r.out.result));
2273 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2274 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2275 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2276 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2277 ret = false;
2278 } else {
2279 *password = newpass;
2282 return ret;
2286 static bool test_ChangePasswordUser2_ntstatus(struct dcerpc_pipe *p, struct torture_context *tctx,
2287 const char *acct_name,
2288 const char *password, NTSTATUS status)
2290 struct samr_ChangePasswordUser2 r;
2291 struct lsa_String server, account;
2292 struct samr_CryptPassword nt_pass, lm_pass;
2293 struct samr_Password nt_verifier, lm_verifier;
2294 const char *oldpass;
2295 struct dcerpc_binding_handle *b = p->binding_handle;
2296 uint8_t old_nt_hash[16], new_nt_hash[16];
2297 uint8_t old_lm_hash[16], new_lm_hash[16];
2299 struct samr_GetDomPwInfo dom_pw_info;
2300 struct samr_PwInfo info;
2302 struct lsa_String domain_name;
2303 char *newpass;
2304 int policy_min_pw_len = 0;
2306 domain_name.string = "";
2307 dom_pw_info.in.domain_name = &domain_name;
2308 dom_pw_info.out.info = &info;
2310 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2312 oldpass = password;
2314 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2315 "GetDomPwInfo failed");
2316 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2317 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2320 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2322 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2323 init_lsa_String(&account, acct_name);
2325 E_md4hash(oldpass, old_nt_hash);
2326 E_md4hash(newpass, new_nt_hash);
2328 E_deshash(oldpass, old_lm_hash);
2329 E_deshash(newpass, new_lm_hash);
2331 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2332 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2333 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2335 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2336 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2337 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2339 r.in.server = &server;
2340 r.in.account = &account;
2341 r.in.nt_password = &nt_pass;
2342 r.in.nt_verifier = &nt_verifier;
2343 r.in.lm_change = 1;
2344 r.in.lm_password = &lm_pass;
2345 r.in.lm_verifier = &lm_verifier;
2347 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2348 "ChangePasswordUser2 failed");
2349 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2350 __location__, __FUNCTION__,
2351 oldpass, newpass, nt_errstr(r.out.result));
2353 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2354 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2355 } else {
2356 torture_assert_ntstatus_equal(tctx, r.out.result, status, "ChangePasswordUser2 returned unexpected value");
2359 return true;
2363 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2364 const char *account_string,
2365 int policy_min_pw_len,
2366 char **password,
2367 const char *newpass,
2368 NTTIME last_password_change,
2369 bool handle_reject_reason)
2371 struct samr_ChangePasswordUser3 r;
2372 bool ret = true;
2373 struct lsa_String server, account, account_bad;
2374 struct samr_CryptPassword nt_pass, lm_pass;
2375 struct samr_Password nt_verifier, lm_verifier;
2376 char *oldpass;
2377 struct dcerpc_binding_handle *b = p->binding_handle;
2378 uint8_t old_nt_hash[16], new_nt_hash[16];
2379 uint8_t old_lm_hash[16], new_lm_hash[16];
2380 NTTIME t;
2381 struct samr_DomInfo1 *dominfo = NULL;
2382 struct userPwdChangeFailureInformation *reject = NULL;
2384 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2386 if (newpass == NULL) {
2387 do {
2388 if (policy_min_pw_len == 0) {
2389 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2390 } else {
2391 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2393 } while (check_password_quality(newpass) == false);
2394 } else {
2395 torture_comment(tctx, "Using password '%s'\n", newpass);
2398 torture_assert(tctx, *password != NULL,
2399 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2401 oldpass = *password;
2402 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2403 init_lsa_String(&account, account_string);
2405 E_md4hash(oldpass, old_nt_hash);
2406 E_md4hash(newpass, new_nt_hash);
2408 E_deshash(oldpass, old_lm_hash);
2409 E_deshash(newpass, new_lm_hash);
2411 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2412 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2413 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2415 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2416 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2417 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2419 /* Break the verification */
2420 nt_verifier.hash[0]++;
2422 r.in.server = &server;
2423 r.in.account = &account;
2424 r.in.nt_password = &nt_pass;
2425 r.in.nt_verifier = &nt_verifier;
2426 r.in.lm_change = 1;
2427 r.in.lm_password = &lm_pass;
2428 r.in.lm_verifier = &lm_verifier;
2429 r.in.password3 = NULL;
2430 r.out.dominfo = &dominfo;
2431 r.out.reject = &reject;
2433 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2434 "ChangePasswordUser3 failed");
2435 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2436 __location__, __FUNCTION__,
2437 oldpass, newpass, nt_errstr(r.out.result));
2438 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2439 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2440 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2441 nt_errstr(r.out.result));
2442 ret = false;
2445 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2446 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2447 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2449 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2450 /* Break the NT hash */
2451 old_nt_hash[0]++;
2452 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2453 /* Unbreak it again */
2454 old_nt_hash[0]--;
2455 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2457 r.in.server = &server;
2458 r.in.account = &account;
2459 r.in.nt_password = &nt_pass;
2460 r.in.nt_verifier = &nt_verifier;
2461 r.in.lm_change = 1;
2462 r.in.lm_password = &lm_pass;
2463 r.in.lm_verifier = &lm_verifier;
2464 r.in.password3 = NULL;
2465 r.out.dominfo = &dominfo;
2466 r.out.reject = &reject;
2468 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2469 "ChangePasswordUser3 failed");
2470 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2471 __location__, __FUNCTION__,
2472 oldpass, newpass, nt_errstr(r.out.result));
2473 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2474 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2475 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2476 nt_errstr(r.out.result));
2477 ret = false;
2480 /* This shouldn't be a valid name */
2481 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2483 r.in.account = &account_bad;
2484 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2485 "ChangePasswordUser3 failed");
2486 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2487 __location__, __FUNCTION__,
2488 oldpass, newpass, nt_errstr(r.out.result));
2489 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2490 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2491 nt_errstr(r.out.result));
2492 ret = false;
2495 E_md4hash(oldpass, old_nt_hash);
2496 E_md4hash(newpass, new_nt_hash);
2498 E_deshash(oldpass, old_lm_hash);
2499 E_deshash(newpass, new_lm_hash);
2501 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2502 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2503 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2505 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2506 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2507 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2509 r.in.server = &server;
2510 r.in.account = &account;
2511 r.in.nt_password = &nt_pass;
2512 r.in.nt_verifier = &nt_verifier;
2513 r.in.lm_change = 1;
2514 r.in.lm_password = &lm_pass;
2515 r.in.lm_verifier = &lm_verifier;
2516 r.in.password3 = NULL;
2517 r.out.dominfo = &dominfo;
2518 r.out.reject = &reject;
2520 unix_to_nt_time(&t, time(NULL));
2522 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2523 "ChangePasswordUser3 failed");
2524 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2525 __location__, __FUNCTION__,
2526 oldpass, newpass, nt_errstr(r.out.result));
2528 torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2529 "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2530 __location__,
2531 (dominfo == NULL)? "NULL" : "present",
2532 reject ? "true" : "false",
2533 handle_reject_reason ? "true" : "false",
2534 null_nttime(last_password_change) ? "null" : "not null",
2535 dominfo ? (long long)dominfo->min_password_age : (long long)0);
2537 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2538 && dominfo
2539 && reject
2540 && handle_reject_reason
2541 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2542 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2544 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2545 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2546 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2547 return false;
2551 /* We tested the order of precendence which is as follows:
2553 * pwd min_age
2554 * pwd length
2555 * pwd complexity
2556 * pwd history
2558 Guenther */
2560 if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
2561 (last_password_change - dominfo->min_password_age > t)) {
2563 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2564 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2565 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2566 return false;
2569 } else if ((dominfo->min_password_length > 0) &&
2570 (strlen(newpass) < dominfo->min_password_length)) {
2572 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2573 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2574 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2575 return false;
2578 } else if ((dominfo->password_history_length > 0) &&
2579 strequal(oldpass, newpass)) {
2581 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2582 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2583 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2584 return false;
2586 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2588 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2589 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2590 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2591 return false;
2596 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2597 /* retry with adjusted size */
2598 return test_ChangePasswordUser3(p, tctx, account_string,
2599 dominfo->min_password_length,
2600 password, NULL, 0, false);
2604 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2605 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2606 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2607 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2608 return false;
2610 /* Perhaps the server has a 'min password age' set? */
2612 } else {
2613 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2615 *password = talloc_strdup(tctx, newpass);
2618 return ret;
2621 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2622 const char *account_string,
2623 struct policy_handle *handle,
2624 char **password)
2626 NTSTATUS status;
2627 struct samr_ChangePasswordUser3 r;
2628 struct samr_SetUserInfo s;
2629 union samr_UserInfo u;
2630 DATA_BLOB session_key;
2631 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2632 uint8_t confounder[16];
2633 MD5_CTX ctx;
2635 bool ret = true;
2636 struct lsa_String server, account;
2637 struct samr_CryptPassword nt_pass;
2638 struct samr_Password nt_verifier;
2639 DATA_BLOB new_random_pass;
2640 char *newpass;
2641 char *oldpass;
2642 struct dcerpc_binding_handle *b = p->binding_handle;
2643 uint8_t old_nt_hash[16], new_nt_hash[16];
2644 NTTIME t;
2645 struct samr_DomInfo1 *dominfo = NULL;
2646 struct userPwdChangeFailureInformation *reject = NULL;
2648 new_random_pass = samr_very_rand_pass(tctx, 128);
2650 torture_assert(tctx, *password != NULL,
2651 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2653 oldpass = *password;
2654 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2655 init_lsa_String(&account, account_string);
2657 s.in.user_handle = handle;
2658 s.in.info = &u;
2659 s.in.level = 25;
2661 ZERO_STRUCT(u);
2663 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2665 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2667 status = dcerpc_fetch_session_key(p, &session_key);
2668 if (!NT_STATUS_IS_OK(status)) {
2669 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
2670 s.in.level, nt_errstr(status));
2671 return false;
2674 generate_random_buffer((uint8_t *)confounder, 16);
2676 MD5Init(&ctx);
2677 MD5Update(&ctx, confounder, 16);
2678 MD5Update(&ctx, session_key.data, session_key.length);
2679 MD5Final(confounded_session_key.data, &ctx);
2681 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2682 memcpy(&u.info25.password.data[516], confounder, 16);
2684 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2686 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2687 "SetUserInfo failed");
2688 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2689 __location__, __FUNCTION__,
2690 oldpass, "RANDOM", nt_errstr(s.out.result));
2691 if (!NT_STATUS_IS_OK(s.out.result)) {
2692 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
2693 s.in.level, nt_errstr(s.out.result));
2694 ret = false;
2697 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2699 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2701 new_random_pass = samr_very_rand_pass(tctx, 128);
2703 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2705 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2706 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2707 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2709 r.in.server = &server;
2710 r.in.account = &account;
2711 r.in.nt_password = &nt_pass;
2712 r.in.nt_verifier = &nt_verifier;
2713 r.in.lm_change = 0;
2714 r.in.lm_password = NULL;
2715 r.in.lm_verifier = NULL;
2716 r.in.password3 = NULL;
2717 r.out.dominfo = &dominfo;
2718 r.out.reject = &reject;
2720 unix_to_nt_time(&t, time(NULL));
2722 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2723 "ChangePasswordUser3 failed");
2724 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2725 __location__, __FUNCTION__,
2726 oldpass, "RANDOM", nt_errstr(r.out.result));
2728 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2729 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2730 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2731 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2732 return false;
2734 /* Perhaps the server has a 'min password age' set? */
2736 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2737 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2738 ret = false;
2741 newpass = samr_rand_pass(tctx, 128);
2743 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2745 E_md4hash(newpass, new_nt_hash);
2747 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2748 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2749 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2751 r.in.server = &server;
2752 r.in.account = &account;
2753 r.in.nt_password = &nt_pass;
2754 r.in.nt_verifier = &nt_verifier;
2755 r.in.lm_change = 0;
2756 r.in.lm_password = NULL;
2757 r.in.lm_verifier = NULL;
2758 r.in.password3 = NULL;
2759 r.out.dominfo = &dominfo;
2760 r.out.reject = &reject;
2762 unix_to_nt_time(&t, time(NULL));
2764 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2765 "ChangePasswordUser3 failed");
2766 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2767 __location__, __FUNCTION__,
2768 oldpass, newpass, nt_errstr(r.out.result));
2770 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2771 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2772 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2773 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2774 return false;
2776 /* Perhaps the server has a 'min password age' set? */
2778 } else {
2779 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2780 *password = talloc_strdup(tctx, newpass);
2783 return ret;
2787 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2788 struct torture_context *tctx,
2789 struct policy_handle *alias_handle)
2791 struct samr_GetMembersInAlias r;
2792 struct lsa_SidArray sids;
2794 torture_comment(tctx, "Testing GetMembersInAlias\n");
2796 r.in.alias_handle = alias_handle;
2797 r.out.sids = &sids;
2799 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2800 "GetMembersInAlias failed");
2801 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2803 return true;
2806 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2807 struct torture_context *tctx,
2808 struct policy_handle *alias_handle,
2809 const struct dom_sid *domain_sid)
2811 struct samr_AddAliasMember r;
2812 struct samr_DeleteAliasMember d;
2813 struct dom_sid *sid;
2815 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2817 torture_comment(tctx, "Testing AddAliasMember\n");
2818 r.in.alias_handle = alias_handle;
2819 r.in.sid = sid;
2821 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2822 "AddAliasMember failed");
2823 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2825 d.in.alias_handle = alias_handle;
2826 d.in.sid = sid;
2828 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2829 "DeleteAliasMember failed");
2830 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2832 return true;
2835 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2836 struct torture_context *tctx,
2837 struct policy_handle *alias_handle)
2839 struct samr_AddMultipleMembersToAlias a;
2840 struct samr_RemoveMultipleMembersFromAlias r;
2841 struct lsa_SidArray sids;
2843 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2844 a.in.alias_handle = alias_handle;
2845 a.in.sids = &sids;
2847 sids.num_sids = 3;
2848 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2850 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2851 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2852 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2854 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2855 "AddMultipleMembersToAlias failed");
2856 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2859 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2860 r.in.alias_handle = alias_handle;
2861 r.in.sids = &sids;
2863 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2864 "RemoveMultipleMembersFromAlias failed");
2865 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2867 /* strange! removing twice doesn't give any error */
2868 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2869 "RemoveMultipleMembersFromAlias failed");
2870 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2872 /* but removing an alias that isn't there does */
2873 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2875 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2876 "RemoveMultipleMembersFromAlias failed");
2877 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2879 return true;
2882 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2883 struct torture_context *tctx,
2884 struct policy_handle *domain_handle)
2886 struct samr_GetAliasMembership r;
2887 struct lsa_SidArray sids;
2888 struct samr_Ids rids;
2890 torture_comment(tctx, "Testing GetAliasMembership\n");
2892 r.in.domain_handle = domain_handle;
2893 r.in.sids = &sids;
2894 r.out.rids = &rids;
2896 sids.num_sids = 0;
2897 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2899 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2900 "GetAliasMembership failed");
2901 torture_assert_ntstatus_ok(tctx, r.out.result,
2902 "samr_GetAliasMembership failed");
2904 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2905 "protocol misbehaviour");
2907 sids.num_sids = 1;
2908 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2909 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2911 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2912 "samr_GetAliasMembership failed");
2913 torture_assert_ntstatus_ok(tctx, r.out.result,
2914 "samr_GetAliasMembership failed");
2916 #if 0
2917 /* only true for w2k8 it seems
2918 * win7, xp, w2k3 will return a 0 length array pointer */
2920 if (rids.ids && (rids.count == 0)) {
2921 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2923 #endif
2924 if (!rids.ids && rids.count) {
2925 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2928 return true;
2931 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2932 struct torture_context *tctx,
2933 struct policy_handle *user_handle)
2935 struct samr_TestPrivateFunctionsUser r;
2937 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2939 r.in.user_handle = user_handle;
2941 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2942 "TestPrivateFunctionsUser failed");
2943 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2945 return true;
2948 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2949 struct torture_context *tctx,
2950 struct policy_handle *handle,
2951 bool use_info2,
2952 NTTIME *pwdlastset)
2954 NTSTATUS status;
2955 uint16_t levels[] = { /* 3, */ 5, 21 };
2956 int i;
2957 /* NTTIME pwdlastset3 = 0; */
2958 NTTIME pwdlastset5 = 0;
2959 NTTIME pwdlastset21 = 0;
2961 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2962 use_info2 ? "2":"");
2964 for (i=0; i<ARRAY_SIZE(levels); i++) {
2966 struct samr_QueryUserInfo r;
2967 struct samr_QueryUserInfo2 r2;
2968 union samr_UserInfo *info;
2970 if (use_info2) {
2971 r2.in.user_handle = handle;
2972 r2.in.level = levels[i];
2973 r2.out.info = &info;
2974 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2975 "QueryUserInfo2 failed");
2976 status = r2.out.result;
2978 } else {
2979 r.in.user_handle = handle;
2980 r.in.level = levels[i];
2981 r.out.info = &info;
2982 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2983 "QueryUserInfo failed");
2984 status = r.out.result;
2987 if (!NT_STATUS_IS_OK(status) &&
2988 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2989 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo%s level %u failed - %s\n",
2990 use_info2 ? "2":"", levels[i], nt_errstr(status));
2991 return false;
2994 switch (levels[i]) {
2995 case 3:
2996 /* pwdlastset3 = info->info3.last_password_change; */
2997 break;
2998 case 5:
2999 pwdlastset5 = info->info5.last_password_change;
3000 break;
3001 case 21:
3002 pwdlastset21 = info->info21.last_password_change;
3003 break;
3004 default:
3005 return false;
3008 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
3009 "pwdlastset mixup"); */
3010 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
3011 "pwdlastset mixup");
3013 *pwdlastset = pwdlastset21;
3015 torture_comment(tctx, "(pwdlastset: %llu)\n",
3016 (unsigned long long) *pwdlastset);
3018 return true;
3021 static bool test_SamLogon(struct torture_context *tctx,
3022 struct dcerpc_pipe *p,
3023 struct cli_credentials *machine_credentials,
3024 struct cli_credentials *test_credentials,
3025 NTSTATUS expected_result,
3026 bool interactive)
3028 NTSTATUS status;
3029 struct netr_LogonSamLogonEx r;
3030 union netr_LogonLevel logon;
3031 union netr_Validation validation;
3032 uint8_t authoritative;
3033 struct netr_IdentityInfo identity;
3034 struct netr_NetworkInfo ninfo;
3035 struct netr_PasswordInfo pinfo;
3036 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
3037 int flags = CLI_CRED_NTLM_AUTH;
3038 uint32_t samlogon_flags = 0;
3039 struct netlogon_creds_CredentialState *creds;
3040 struct netr_Authenticator a;
3041 struct dcerpc_binding_handle *b = p->binding_handle;
3043 torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), "");
3045 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
3046 flags |= CLI_CRED_LANMAN_AUTH;
3049 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
3050 flags |= CLI_CRED_NTLMv2_AUTH;
3053 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
3054 &identity.account_name.string,
3055 &identity.domain_name.string);
3057 identity.parameter_control =
3058 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
3059 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
3060 identity.logon_id_low = 0;
3061 identity.logon_id_high = 0;
3062 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
3064 if (interactive) {
3065 netlogon_creds_client_authenticator(creds, &a);
3067 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
3068 ZERO_STRUCT(pinfo.lmpassword.hash);
3070 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
3072 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3073 netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
3074 netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
3075 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
3076 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
3077 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
3078 } else {
3079 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
3080 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
3083 pinfo.identity_info = identity;
3084 logon.password = &pinfo;
3086 r.in.logon_level = NetlogonInteractiveInformation;
3087 } else {
3088 generate_random_buffer(ninfo.challenge,
3089 sizeof(ninfo.challenge));
3090 chal = data_blob_const(ninfo.challenge,
3091 sizeof(ninfo.challenge));
3093 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3094 cli_credentials_get_domain(test_credentials));
3096 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3097 &flags,
3098 chal,
3099 names_blob,
3100 &lm_resp, &nt_resp,
3101 NULL, NULL);
3102 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3104 ninfo.lm.data = lm_resp.data;
3105 ninfo.lm.length = lm_resp.length;
3107 ninfo.nt.data = nt_resp.data;
3108 ninfo.nt.length = nt_resp.length;
3110 ninfo.identity_info = identity;
3111 logon.network = &ninfo;
3113 r.in.logon_level = NetlogonNetworkInformation;
3116 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3117 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3118 r.in.logon = &logon;
3119 r.in.flags = &samlogon_flags;
3120 r.out.flags = &samlogon_flags;
3121 r.out.validation = &validation;
3122 r.out.authoritative = &authoritative;
3124 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3126 r.in.validation_level = 6;
3128 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3129 "netr_LogonSamLogonEx failed");
3130 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3131 r.in.validation_level = 3;
3132 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3133 "netr_LogonSamLogonEx failed");
3135 if (!NT_STATUS_IS_OK(r.out.result)) {
3136 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3137 return true;
3138 } else {
3139 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3142 return true;
3145 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3146 struct dcerpc_pipe *p,
3147 struct cli_credentials *machine_creds,
3148 const char *acct_name,
3149 const char *password,
3150 NTSTATUS expected_samlogon_result,
3151 bool interactive)
3153 bool ret = true;
3154 struct cli_credentials *test_credentials;
3156 test_credentials = cli_credentials_init(tctx);
3158 cli_credentials_set_workstation(test_credentials,
3159 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3160 cli_credentials_set_domain(test_credentials,
3161 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3162 cli_credentials_set_username(test_credentials,
3163 acct_name, CRED_SPECIFIED);
3164 cli_credentials_set_password(test_credentials,
3165 password, CRED_SPECIFIED);
3167 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3168 interactive ? "interactive" : "network", acct_name, password);
3170 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
3171 expected_samlogon_result, interactive)) {
3172 torture_result(tctx, TORTURE_FAIL, "new password did not work\n");
3173 ret = false;
3176 return ret;
3179 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3180 struct dcerpc_pipe *np,
3181 struct torture_context *tctx,
3182 struct policy_handle *handle,
3183 uint16_t level,
3184 uint32_t fields_present,
3185 uint8_t password_expired,
3186 bool *matched_expected_error,
3187 bool use_setinfo2,
3188 const char *acct_name,
3189 char **password,
3190 struct cli_credentials *machine_creds,
3191 bool use_queryinfo2,
3192 NTTIME *pwdlastset,
3193 NTSTATUS expected_samlogon_result)
3195 const char *fields = NULL;
3196 bool ret = true;
3197 struct dcerpc_binding_handle *b = p->binding_handle;
3199 switch (level) {
3200 case 21:
3201 case 23:
3202 case 25:
3203 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3204 fields_present);
3205 break;
3206 default:
3207 break;
3210 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3211 "(password_expired: %d) %s\n",
3212 use_setinfo2 ? "2":"", level, password_expired,
3213 fields ? fields : "");
3215 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3216 fields_present,
3217 password,
3218 password_expired,
3219 use_setinfo2,
3220 matched_expected_error)) {
3221 ret = false;
3224 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3225 use_queryinfo2,
3226 pwdlastset)) {
3227 ret = false;
3230 if (*matched_expected_error == true) {
3231 return ret;
3234 if (!test_SamLogon_with_creds(tctx, np,
3235 machine_creds,
3236 acct_name,
3237 *password,
3238 expected_samlogon_result,
3239 false)) {
3240 ret = false;
3243 return ret;
3246 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3247 struct cli_credentials *credentials,
3248 struct dcerpc_pipe **p)
3250 struct dcerpc_binding *b;
3251 NTSTATUS status;
3253 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3254 "failed to get rpc binding");
3256 /* We have to use schannel, otherwise the SamLogonEx fails
3257 * with INTERNAL_ERROR */
3259 status = dcerpc_binding_set_flags(b,
3260 DCERPC_SCHANNEL | DCERPC_SIGN |
3261 DCERPC_SCHANNEL_AUTO,
3262 DCERPC_AUTH_OPTIONS);
3263 torture_assert_ntstatus_ok(tctx, status, "set flags");
3265 torture_assert_ntstatus_ok(tctx,
3266 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3267 credentials, tctx->ev, tctx->lp_ctx),
3268 "failed to bind to netlogon");
3270 return true;
3273 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3274 struct torture_context *tctx,
3275 uint32_t acct_flags,
3276 const char *acct_name,
3277 struct policy_handle *handle,
3278 char **password,
3279 struct cli_credentials *machine_credentials)
3281 int s = 0, q = 0, f = 0, l = 0, z = 0;
3282 bool ret = true;
3283 int delay = 50000;
3284 bool set_levels[] = { false, true };
3285 bool query_levels[] = { false, true };
3286 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3287 uint32_t nonzeros[] = { 1, 24 };
3288 uint32_t fields_present[] = {
3290 SAMR_FIELD_EXPIRED_FLAG,
3291 SAMR_FIELD_LAST_PWD_CHANGE,
3292 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3293 SAMR_FIELD_COMMENT,
3294 SAMR_FIELD_NT_PASSWORD_PRESENT,
3295 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3296 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3297 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3298 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3299 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3300 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3302 struct dcerpc_pipe *np = NULL;
3304 if (torture_setting_bool(tctx, "samba3", false) ||
3305 torture_setting_bool(tctx, "samba4", false)) {
3306 delay = 999999;
3307 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3308 delay);
3311 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3313 /* set to 1 to enable testing for all possible opcode
3314 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3315 combinations */
3316 #if 0
3317 #define TEST_ALL_LEVELS 1
3318 #define TEST_SET_LEVELS 1
3319 #define TEST_QUERY_LEVELS 1
3320 #endif
3321 #ifdef TEST_ALL_LEVELS
3322 for (l=0; l<ARRAY_SIZE(levels); l++) {
3323 #else
3324 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3325 #endif
3326 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3327 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3328 #ifdef TEST_SET_LEVELS
3329 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3330 #endif
3331 #ifdef TEST_QUERY_LEVELS
3332 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3333 #endif
3334 NTTIME pwdlastset_old = 0;
3335 NTTIME pwdlastset_new = 0;
3336 bool matched_expected_error = false;
3337 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3339 torture_comment(tctx, "------------------------------\n"
3340 "Testing pwdLastSet attribute for flags: 0x%08x "
3341 "(s: %d (l: %d), q: %d)\n",
3342 acct_flags, s, levels[l], q);
3344 switch (levels[l]) {
3345 case 21:
3346 case 23:
3347 case 25:
3348 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3349 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3350 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3352 break;
3356 /* set #1 */
3358 /* set a password and force password change (pwdlastset 0) by
3359 * setting the password expired flag to a non-0 value */
3361 if (!test_SetPassword_level(p, np, tctx, handle,
3362 levels[l],
3363 fields_present[f],
3364 nonzeros[z],
3365 &matched_expected_error,
3366 set_levels[s],
3367 acct_name,
3368 password,
3369 machine_credentials,
3370 query_levels[q],
3371 &pwdlastset_new,
3372 expected_samlogon_result)) {
3373 ret = false;
3376 if (matched_expected_error == true) {
3377 /* skipping on expected failure */
3378 continue;
3381 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3382 * set without the SAMR_FIELD_EXPIRED_FLAG */
3384 switch (levels[l]) {
3385 case 21:
3386 case 23:
3387 case 25:
3388 if ((pwdlastset_new != 0) &&
3389 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3390 torture_comment(tctx, "not considering a non-0 "
3391 "pwdLastSet as a an error as the "
3392 "SAMR_FIELD_EXPIRED_FLAG has not "
3393 "been set\n");
3394 break;
3396 break;
3397 default:
3398 if (pwdlastset_new != 0) {
3399 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3400 "expected pwdLastSet 0 but got %llu\n",
3401 (unsigned long long) pwdlastset_old);
3402 ret = false;
3404 break;
3407 switch (levels[l]) {
3408 case 21:
3409 case 23:
3410 case 25:
3411 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3412 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3413 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3414 (pwdlastset_old >= pwdlastset_new)) {
3415 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3416 ret = false;
3418 break;
3421 pwdlastset_old = pwdlastset_new;
3423 usleep(delay);
3425 /* set #2 */
3427 /* set a password, pwdlastset needs to get updated (increased
3428 * value), password_expired value used here is 0 */
3430 if (!test_SetPassword_level(p, np, tctx, handle,
3431 levels[l],
3432 fields_present[f],
3434 &matched_expected_error,
3435 set_levels[s],
3436 acct_name,
3437 password,
3438 machine_credentials,
3439 query_levels[q],
3440 &pwdlastset_new,
3441 expected_samlogon_result)) {
3442 ret = false;
3445 /* when a password has been changed, pwdlastset must not be 0 afterwards
3446 * and must be larger then the old value */
3448 switch (levels[l]) {
3449 case 21:
3450 case 23:
3451 case 25:
3452 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3453 * password has been changed, old and new pwdlastset
3454 * need to be the same value */
3456 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3457 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3458 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3460 torture_assert_int_equal(tctx, pwdlastset_old,
3461 pwdlastset_new, "pwdlastset must be equal");
3462 break;
3464 break;
3465 default:
3466 if (pwdlastset_old >= pwdlastset_new) {
3467 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3468 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3469 (unsigned long long) pwdlastset_old,
3470 (unsigned long long) pwdlastset_new);
3471 ret = false;
3473 if (pwdlastset_new == 0) {
3474 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3475 "expected non-0 pwdlastset, got: %llu\n",
3476 (unsigned long long) pwdlastset_new);
3477 ret = false;
3479 break;
3482 switch (levels[l]) {
3483 case 21:
3484 case 23:
3485 case 25:
3486 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3487 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3488 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3489 (pwdlastset_old >= pwdlastset_new)) {
3490 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3491 ret = false;
3493 break;
3496 pwdlastset_old = pwdlastset_new;
3498 usleep(delay);
3500 /* set #2b */
3502 /* set a password, pwdlastset needs to get updated (increased
3503 * value), password_expired value used here is 0 */
3505 if (!test_SetPassword_level(p, np, tctx, handle,
3506 levels[l],
3507 fields_present[f],
3509 &matched_expected_error,
3510 set_levels[s],
3511 acct_name,
3512 password,
3513 machine_credentials,
3514 query_levels[q],
3515 &pwdlastset_new,
3516 expected_samlogon_result)) {
3517 ret = false;
3520 /* when a password has been changed, pwdlastset must not be 0 afterwards
3521 * and must be larger then the old value */
3523 switch (levels[l]) {
3524 case 21:
3525 case 23:
3526 case 25:
3528 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3529 * password has been changed, old and new pwdlastset
3530 * need to be the same value */
3532 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3533 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3534 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3536 torture_assert_int_equal(tctx, pwdlastset_old,
3537 pwdlastset_new, "pwdlastset must be equal");
3538 break;
3540 break;
3541 default:
3542 if (pwdlastset_old >= pwdlastset_new) {
3543 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3544 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3545 (unsigned long long) pwdlastset_old,
3546 (unsigned long long) pwdlastset_new);
3547 ret = false;
3549 if (pwdlastset_new == 0) {
3550 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3551 "expected non-0 pwdlastset, got: %llu\n",
3552 (unsigned long long) pwdlastset_new);
3553 ret = false;
3555 break;
3558 switch (levels[l]) {
3559 case 21:
3560 case 23:
3561 case 25:
3562 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3563 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3564 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3565 (pwdlastset_old >= pwdlastset_new)) {
3566 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3567 ret = false;
3569 break;
3572 pwdlastset_old = pwdlastset_new;
3574 usleep(delay);
3576 /* set #3 */
3578 /* set a password and force password change (pwdlastset 0) by
3579 * setting the password expired flag to a non-0 value */
3581 if (!test_SetPassword_level(p, np, tctx, handle,
3582 levels[l],
3583 fields_present[f],
3584 nonzeros[z],
3585 &matched_expected_error,
3586 set_levels[s],
3587 acct_name,
3588 password,
3589 machine_credentials,
3590 query_levels[q],
3591 &pwdlastset_new,
3592 expected_samlogon_result)) {
3593 ret = false;
3596 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3597 * set without the SAMR_FIELD_EXPIRED_FLAG */
3599 switch (levels[l]) {
3600 case 21:
3601 case 23:
3602 case 25:
3603 if ((pwdlastset_new != 0) &&
3604 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3605 torture_comment(tctx, "not considering a non-0 "
3606 "pwdLastSet as a an error as the "
3607 "SAMR_FIELD_EXPIRED_FLAG has not "
3608 "been set\n");
3609 break;
3612 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3613 * password has been changed, old and new pwdlastset
3614 * need to be the same value */
3616 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3617 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3618 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3620 torture_assert_int_equal(tctx, pwdlastset_old,
3621 pwdlastset_new, "pwdlastset must be equal");
3622 break;
3624 break;
3625 default:
3626 if (pwdlastset_new != 0) {
3627 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3628 "expected pwdLastSet 0, got %llu\n",
3629 (unsigned long long) pwdlastset_old);
3630 ret = false;
3632 break;
3635 switch (levels[l]) {
3636 case 21:
3637 case 23:
3638 case 25:
3639 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3640 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3641 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3642 (pwdlastset_old >= pwdlastset_new)) {
3643 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3644 ret = false;
3646 break;
3649 /* if the level we are testing does not have a fields_present
3650 * field, skip all fields present tests by setting f to to
3651 * arraysize */
3652 switch (levels[l]) {
3653 case 18:
3654 case 24:
3655 case 26:
3656 f = ARRAY_SIZE(fields_present);
3657 break;
3660 #ifdef TEST_QUERY_LEVELS
3662 #endif
3663 #ifdef TEST_SET_LEVELS
3665 #endif
3666 } /* fields present */
3667 } /* nonzeros */
3668 } /* levels */
3670 #undef TEST_SET_LEVELS
3671 #undef TEST_QUERY_LEVELS
3673 talloc_free(np);
3675 return ret;
3678 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3679 struct torture_context *tctx,
3680 struct policy_handle *handle,
3681 uint32_t *badpwdcount)
3683 union samr_UserInfo *info;
3684 struct samr_QueryUserInfo r;
3686 r.in.user_handle = handle;
3687 r.in.level = 3;
3688 r.out.info = &info;
3690 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3692 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3693 "failed to query userinfo");
3694 torture_assert_ntstatus_ok(tctx, r.out.result,
3695 "failed to query userinfo");
3697 *badpwdcount = info->info3.bad_password_count;
3699 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3701 return true;
3704 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3705 struct torture_context *tctx,
3706 struct policy_handle *user_handle,
3707 uint32_t acct_flags)
3709 struct samr_SetUserInfo r;
3710 union samr_UserInfo user_info;
3712 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3714 user_info.info16.acct_flags = acct_flags;
3716 r.in.user_handle = user_handle;
3717 r.in.level = 16;
3718 r.in.info = &user_info;
3720 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3721 "failed to set account flags");
3722 torture_assert_ntstatus_ok(tctx, r.out.result,
3723 "failed to set account flags");
3725 return true;
3728 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3729 struct torture_context *tctx,
3730 struct policy_handle *user_handle,
3731 uint32_t acct_flags,
3732 char **password)
3734 struct dcerpc_binding_handle *b = p->binding_handle;
3736 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3737 "failed to set password");
3739 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3741 torture_assert(tctx,
3742 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3743 acct_flags & ~ACB_DISABLED),
3744 "failed to enable user");
3746 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3747 "failed to set password");
3749 return true;
3752 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3753 struct torture_context *tctx,
3754 struct policy_handle *domain_handle,
3755 enum samr_DomainInfoClass level,
3756 union samr_DomainInfo *info)
3758 struct samr_SetDomainInfo r;
3760 r.in.domain_handle = domain_handle;
3761 r.in.level = level;
3762 r.in.info = info;
3764 torture_assert_ntstatus_ok(tctx,
3765 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3766 "failed to set domain info");
3767 torture_assert_ntstatus_ok(tctx, r.out.result,
3768 "failed to set domain info");
3770 return true;
3773 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3774 struct torture_context *tctx,
3775 struct policy_handle *domain_handle,
3776 enum samr_DomainInfoClass level,
3777 union samr_DomainInfo *info,
3778 NTSTATUS expected)
3780 struct samr_SetDomainInfo r;
3782 r.in.domain_handle = domain_handle;
3783 r.in.level = level;
3784 r.in.info = info;
3786 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3787 "SetDomainInfo failed");
3788 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3790 return true;
3793 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3794 struct torture_context *tctx,
3795 struct policy_handle *domain_handle,
3796 enum samr_DomainInfoClass level,
3797 union samr_DomainInfo **q_info)
3799 struct samr_QueryDomainInfo2 r;
3801 r.in.domain_handle = domain_handle;
3802 r.in.level = level;
3803 r.out.info = q_info;
3805 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3806 "failed to query domain info");
3807 torture_assert_ntstatus_ok(tctx, r.out.result,
3808 "failed to query domain info");
3810 return true;
3813 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3814 struct dcerpc_pipe *np,
3815 struct torture_context *tctx,
3816 uint32_t acct_flags,
3817 const char *acct_name,
3818 struct policy_handle *domain_handle,
3819 struct policy_handle *user_handle,
3820 char **password,
3821 struct cli_credentials *machine_credentials,
3822 const char *comment,
3823 bool disable,
3824 bool interactive,
3825 NTSTATUS expected_success_status,
3826 struct samr_DomInfo1 *info1,
3827 struct samr_DomInfo12 *info12)
3829 union samr_DomainInfo info;
3830 char **passwords;
3831 int i;
3832 uint32_t badpwdcount, tmp;
3833 uint32_t password_history_length = 12;
3834 uint32_t lockout_threshold = 15;
3835 uint32_t lockout_seconds = 5;
3836 uint64_t delta_time_factor = 10 * 1000 * 1000;
3837 struct dcerpc_binding_handle *b = p->binding_handle;
3839 if (torture_setting_bool(tctx, "samba3", false)) {
3840 lockout_seconds = 60;
3843 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3845 torture_assert(tctx, password_history_length < lockout_threshold,
3846 "password history length needs to be smaller than account lockout threshold for this test");
3849 /* set policies */
3851 info.info1 = *info1;
3852 info.info1.password_history_length = password_history_length;
3853 info.info1.min_password_age = 0;
3855 torture_assert(tctx,
3856 test_SetDomainInfo(b, tctx, domain_handle,
3857 DomainPasswordInformation, &info),
3858 "failed to set password history length and min passwd age");
3860 info.info12 = *info12;
3861 info.info12.lockout_threshold = lockout_threshold;
3863 /* set lockout duration of 5 seconds */
3864 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3865 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
3867 torture_assert(tctx,
3868 test_SetDomainInfo(b, tctx, domain_handle,
3869 DomainLockoutInformation, &info),
3870 "failed to set lockout threshold");
3872 /* reset bad pwd count */
3874 torture_assert(tctx,
3875 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3878 /* enable or disable account */
3879 if (disable) {
3880 torture_assert(tctx,
3881 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3882 acct_flags | ACB_DISABLED),
3883 "failed to disable user");
3884 } else {
3885 torture_assert(tctx,
3886 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3887 acct_flags & ~ACB_DISABLED),
3888 "failed to enable user");
3892 /* setup password history */
3894 passwords = talloc_array(tctx, char *, password_history_length);
3896 for (i=0; i < password_history_length; i++) {
3898 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3899 "failed to set password");
3900 passwords[i] = talloc_strdup(tctx, *password);
3902 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3903 acct_name, passwords[i],
3904 expected_success_status, interactive)) {
3905 torture_fail(tctx, "failed to auth with latest password");
3908 torture_assert(tctx,
3909 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3911 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3915 /* test with wrong password */
3917 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3918 acct_name, "random_crap",
3919 NT_STATUS_WRONG_PASSWORD, interactive)) {
3920 torture_fail(tctx, "succeeded to authenticate with wrong password");
3923 torture_assert(tctx,
3924 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3926 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3929 /* test with latest good password */
3931 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3932 passwords[password_history_length-1],
3933 expected_success_status, interactive)) {
3934 torture_fail(tctx, "succeeded to authenticate with wrong password");
3937 torture_assert(tctx,
3938 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3940 if (disable) {
3941 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3942 } else {
3943 /* only enabled accounts get the bad pwd count reset upon
3944 * successful logon */
3945 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3948 tmp = badpwdcount;
3951 /* test password history */
3953 for (i=0; i < password_history_length; i++) {
3955 torture_comment(tctx, "Testing bad password count behavior with "
3956 "password #%d of #%d\n", i, password_history_length);
3958 /* - network samlogon will succeed auth and not
3959 * increase badpwdcount for 2 last entries
3960 * - interactive samlogon only for the last one */
3962 if (i == password_history_length - 1 ||
3963 (i == password_history_length - 2 && !interactive)) {
3965 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3966 acct_name, passwords[i],
3967 expected_success_status, interactive)) {
3968 torture_fail(tctx, talloc_asprintf(tctx, "did not successfully to obtain %s for %s login with old password (#%d of #%d in history)",
3969 nt_errstr(expected_success_status),
3970 interactive ? "interactive" : "network", i, password_history_length));
3973 torture_assert(tctx,
3974 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3976 if (disable) {
3977 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3978 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3979 } else {
3980 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3981 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3984 tmp = badpwdcount;
3986 continue;
3989 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3990 acct_name, passwords[i],
3991 NT_STATUS_WRONG_PASSWORD, interactive)) {
3992 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3995 torture_assert(tctx,
3996 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3998 /* - network samlogon will fail auth but not increase
3999 * badpwdcount for 3rd last entry
4000 * - interactive samlogon for 3rd and 2nd last entry */
4002 if (i == password_history_length - 3 ||
4003 (i == password_history_length - 2 && interactive)) {
4004 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
4005 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
4006 } else {
4007 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
4008 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
4011 tmp = badpwdcount;
4014 return true;
4017 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
4018 struct torture_context *tctx,
4019 uint32_t acct_flags,
4020 const char *acct_name,
4021 struct policy_handle *domain_handle,
4022 struct policy_handle *user_handle,
4023 char **password,
4024 struct cli_credentials *machine_credentials)
4026 union samr_DomainInfo *q_info, s_info;
4027 struct samr_DomInfo1 info1, _info1;
4028 struct samr_DomInfo12 info12, _info12;
4029 bool ret = true;
4030 struct dcerpc_binding_handle *b = p->binding_handle;
4031 struct dcerpc_pipe *np;
4032 int i;
4034 struct {
4035 const char *comment;
4036 bool disabled;
4037 bool interactive;
4038 NTSTATUS expected_success_status;
4039 } creds[] = {
4041 .comment = "network logon (disabled account)",
4042 .disabled = true,
4043 .interactive = false,
4044 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4047 .comment = "network logon (enabled account)",
4048 .disabled = false,
4049 .interactive = false,
4050 .expected_success_status= NT_STATUS_OK
4053 .comment = "interactive logon (disabled account)",
4054 .disabled = true,
4055 .interactive = true,
4056 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4059 .comment = "interactive logon (enabled account)",
4060 .disabled = false,
4061 .interactive = true,
4062 .expected_success_status= NT_STATUS_OK
4066 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4068 /* backup old policies */
4070 torture_assert(tctx,
4071 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4072 DomainPasswordInformation, &q_info),
4073 "failed to query domain info level 1");
4075 info1 = q_info->info1;
4076 _info1 = info1;
4078 torture_assert(tctx,
4079 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4080 DomainLockoutInformation, &q_info),
4081 "failed to query domain info level 12");
4083 info12 = q_info->info12;
4084 _info12 = info12;
4086 /* run tests */
4088 for (i=0; i < ARRAY_SIZE(creds); i++) {
4090 /* skip trust tests for now */
4091 if (acct_flags & ACB_WSTRUST ||
4092 acct_flags & ACB_SVRTRUST ||
4093 acct_flags & ACB_DOMTRUST) {
4094 continue;
4097 if (!test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4098 domain_handle, user_handle, password,
4099 machine_credentials,
4100 creds[i].comment,
4101 creds[i].disabled,
4102 creds[i].interactive,
4103 creds[i].expected_success_status,
4104 &_info1, &_info12)) {
4105 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4106 ret = false;
4107 } else {
4108 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4112 /* restore policies */
4114 s_info.info1 = info1;
4116 torture_assert(tctx,
4117 test_SetDomainInfo(b, tctx, domain_handle,
4118 DomainPasswordInformation, &s_info),
4119 "failed to set password information");
4121 s_info.info12 = info12;
4123 torture_assert(tctx,
4124 test_SetDomainInfo(b, tctx, domain_handle,
4125 DomainLockoutInformation, &s_info),
4126 "failed to set lockout information");
4128 return ret;
4131 static bool test_QueryUserInfo_lockout(struct dcerpc_binding_handle *b,
4132 struct torture_context *tctx,
4133 struct policy_handle *domain_handle,
4134 const char *acct_name,
4135 uint16_t raw_bad_password_count,
4136 uint16_t effective_bad_password_count,
4137 uint32_t effective_acb_lockout)
4139 struct policy_handle user_handle;
4140 union samr_UserInfo *i;
4141 struct samr_QueryUserInfo r;
4143 NTSTATUS status = test_OpenUser_byname(b, tctx, domain_handle, acct_name, &user_handle);
4144 if (!NT_STATUS_IS_OK(status)) {
4145 return false;
4148 r.in.user_handle = &user_handle;
4149 r.in.level = 3;
4150 r.out.info = &i;
4151 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4152 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4153 "failed to query userinfo");
4154 torture_assert_ntstatus_ok(tctx, r.out.result,
4155 "failed to query userinfo");
4156 torture_comment(tctx, " (acct_flags: 0x%08x) (raw_bad_pwd_count: %u)\n",
4157 i->info3.acct_flags, i->info3.bad_password_count);
4158 torture_assert_int_equal(tctx, i->info3.bad_password_count,
4159 raw_bad_password_count,
4160 "raw badpwdcount");
4161 torture_assert_int_equal(tctx, i->info3.acct_flags & ACB_AUTOLOCK,
4162 effective_acb_lockout,
4163 "effective acb_lockout");
4164 TALLOC_FREE(i);
4166 r.in.user_handle = &user_handle;
4167 r.in.level = 5;
4168 r.out.info = &i;
4169 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4170 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4171 "failed to query userinfo");
4172 torture_assert_ntstatus_ok(tctx, r.out.result,
4173 "failed to query userinfo");
4174 torture_comment(tctx, " (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
4175 i->info5.acct_flags, i->info5.bad_password_count);
4176 torture_assert_int_equal(tctx, i->info5.bad_password_count,
4177 effective_bad_password_count,
4178 "effective badpwdcount");
4179 torture_assert_int_equal(tctx, i->info5.acct_flags & ACB_AUTOLOCK,
4180 effective_acb_lockout,
4181 "effective acb_lockout");
4182 TALLOC_FREE(i);
4184 r.in.user_handle = &user_handle;
4185 r.in.level = 16;
4186 r.out.info = &i;
4187 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4188 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4189 "failed to query userinfo");
4190 torture_assert_ntstatus_ok(tctx, r.out.result,
4191 "failed to query userinfo");
4192 torture_comment(tctx, " (acct_flags: 0x%08x)\n",
4193 i->info16.acct_flags);
4194 torture_assert_int_equal(tctx, i->info16.acct_flags & ACB_AUTOLOCK,
4195 effective_acb_lockout,
4196 "effective acb_lockout");
4197 TALLOC_FREE(i);
4199 r.in.user_handle = &user_handle;
4200 r.in.level = 21;
4201 r.out.info = &i;
4202 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4203 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4204 "failed to query userinfo");
4205 torture_assert_ntstatus_ok(tctx, r.out.result,
4206 "failed to query userinfo");
4207 torture_comment(tctx, " (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
4208 i->info21.acct_flags, i->info21.bad_password_count);
4209 torture_assert_int_equal(tctx, i->info21.bad_password_count,
4210 effective_bad_password_count,
4211 "effective badpwdcount");
4212 torture_assert_int_equal(tctx, i->info21.acct_flags & ACB_AUTOLOCK,
4213 effective_acb_lockout,
4214 "effective acb_lockout");
4215 TALLOC_FREE(i);
4217 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
4218 return false;
4221 return true;
4224 static bool test_Password_lockout(struct dcerpc_pipe *p,
4225 struct dcerpc_pipe *np,
4226 struct torture_context *tctx,
4227 uint32_t acct_flags,
4228 const char *acct_name,
4229 struct policy_handle *domain_handle,
4230 struct policy_handle *user_handle,
4231 char **password,
4232 struct cli_credentials *machine_credentials,
4233 const char *comment,
4234 bool disable,
4235 bool interactive,
4236 uint32_t password_history_length,
4237 NTSTATUS expected_success_status,
4238 struct samr_DomInfo1 *info1,
4239 struct samr_DomInfo12 *info12)
4241 union samr_DomainInfo info;
4242 uint64_t lockout_threshold = 1;
4243 uint32_t lockout_seconds = 5;
4244 uint64_t delta_time_factor = 10 * 1000 * 1000;
4245 struct dcerpc_binding_handle *b = p->binding_handle;
4247 if (torture_setting_bool(tctx, "samba3", false)) {
4248 lockout_seconds = 60;
4251 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4253 /* set policies */
4255 info.info1 = *info1;
4257 torture_comment(tctx, "setting password history length to %d.\n", password_history_length);
4258 info.info1.password_history_length = password_history_length;
4260 torture_comment(tctx, "setting min password again.\n");
4261 info.info1.min_password_age = 0;
4263 torture_assert(tctx,
4264 test_SetDomainInfo(b, tctx, domain_handle,
4265 DomainPasswordInformation, &info),
4266 "failed to set password history length");
4268 info.info12 = *info12;
4269 info.info12.lockout_threshold = lockout_threshold;
4271 /* set lockout duration < lockout window: should fail */
4272 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4273 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4275 torture_assert(tctx,
4276 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4277 DomainLockoutInformation, &info,
4278 NT_STATUS_INVALID_PARAMETER),
4279 "setting lockout duration < lockout window gave unexpected result");
4281 info.info12.lockout_duration = 0;
4282 info.info12.lockout_window = 0;
4284 torture_assert(tctx,
4285 test_SetDomainInfo(b, tctx, domain_handle,
4286 DomainLockoutInformation, &info),
4287 "failed to set lockout window and duration to 0");
4290 /* set lockout duration of 5 seconds */
4291 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4292 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4294 torture_assert(tctx,
4295 test_SetDomainInfo(b, tctx, domain_handle,
4296 DomainLockoutInformation, &info),
4297 "failed to set lockout window and duration to 5 seconds");
4299 /* reset bad pwd count */
4301 torture_assert(tctx,
4302 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4305 /* enable or disable account */
4307 if (disable) {
4308 torture_assert(tctx,
4309 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4310 acct_flags | ACB_DISABLED),
4311 "failed to disable user");
4312 } else {
4313 torture_assert(tctx,
4314 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4315 acct_flags & ~ACB_DISABLED),
4316 "failed to enable user");
4320 /* test logon with right password */
4322 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4323 acct_name, *password,
4324 expected_success_status, interactive)) {
4325 torture_fail(tctx, "failed to auth with latest password");
4328 torture_assert(tctx,
4329 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4330 0, 0, 0),
4331 "expected account to not be locked");
4333 /* test with wrong password ==> lockout */
4335 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4336 acct_name, "random_crap",
4337 NT_STATUS_WRONG_PASSWORD, interactive)) {
4338 torture_fail(tctx, "succeeded to authenticate with wrong password");
4342 * curiously, windows does _not_ return fresh values of
4343 * effective bad_password_count and ACB_AUTOLOCK.
4345 torture_assert(tctx,
4346 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4347 1, 1, ACB_AUTOLOCK),
4348 "expected account to not be locked");
4350 /* test with good password */
4352 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4353 *password,
4354 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4356 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4359 /* bad pwd count should not get updated */
4360 torture_assert(tctx,
4361 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4362 1, 1, ACB_AUTOLOCK),
4363 "expected account to be locked");
4365 torture_assert(tctx,
4366 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password,
4367 NT_STATUS_ACCOUNT_LOCKED_OUT),
4368 "got wrong status from ChangePasswordUser2");
4370 /* bad pwd count should not get updated */
4371 torture_assert(tctx,
4372 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4373 1, 1, ACB_AUTOLOCK),
4374 "expected account to be locked");
4376 torture_assert(tctx,
4377 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
4378 "got wrong status from ChangePasswordUser2");
4380 /* bad pwd count should not get updated */
4381 torture_assert(tctx,
4382 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4383 1, 1, ACB_AUTOLOCK),
4384 "expected account to be locked");
4386 /* with bad password */
4388 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4389 acct_name, "random_crap2",
4390 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4392 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4395 /* bad pwd count should not get updated */
4396 torture_assert(tctx,
4397 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4398 1, 1, ACB_AUTOLOCK),
4399 "expected account to be locked");
4401 /* let lockout duration expire ==> unlock */
4403 torture_comment(tctx, "let lockout duration expire...\n");
4404 sleep(lockout_seconds + 1);
4406 torture_assert(tctx,
4407 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4408 1, 0, 0),
4409 "expected account to not be locked");
4411 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4412 *password,
4413 expected_success_status, interactive))
4415 torture_fail(tctx, "failed to authenticate after lockout expired");
4418 if (NT_STATUS_IS_OK(expected_success_status)) {
4419 torture_assert(tctx,
4420 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4421 0, 0, 0),
4422 "expected account to not be locked");
4423 } else {
4424 torture_assert(tctx,
4425 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4426 1, 0, 0),
4427 "expected account to not be locked");
4430 torture_assert(tctx,
4431 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4432 "got wrong status from ChangePasswordUser2");
4434 torture_assert(tctx,
4435 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4436 1, 1, ACB_AUTOLOCK),
4437 "expected account to be locked");
4439 torture_assert(tctx,
4440 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
4441 "got wrong status from ChangePasswordUser2");
4443 torture_assert(tctx,
4444 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4445 1, 1, ACB_AUTOLOCK),
4446 "expected account to be locked");
4448 torture_assert(tctx,
4449 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
4450 "got wrong status from ChangePasswordUser2");
4452 torture_assert(tctx,
4453 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4454 1, 1, ACB_AUTOLOCK),
4455 "expected account to be locked");
4457 /* let lockout duration expire ==> unlock */
4459 torture_comment(tctx, "let lockout duration expire...\n");
4460 sleep(lockout_seconds + 1);
4462 torture_assert(tctx,
4463 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4464 1, 0, 0),
4465 "expected account to not be locked");
4467 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4468 *password,
4469 expected_success_status, interactive))
4471 torture_fail(tctx, "failed to authenticate after lockout expired");
4474 if (NT_STATUS_IS_OK(expected_success_status)) {
4475 torture_assert(tctx,
4476 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4477 0, 0, 0),
4478 "expected account to not be locked");
4479 } else {
4480 torture_assert(tctx,
4481 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4482 1, 0, 0),
4483 "expected account to not be locked");
4486 /* Testing ChangePasswordUser behaviour with 3 attempts */
4487 info.info12.lockout_threshold = 3;
4489 torture_assert(tctx,
4490 test_SetDomainInfo(b, tctx, domain_handle,
4491 DomainLockoutInformation, &info),
4492 "failed to set lockout threshold to 3");
4494 if (NT_STATUS_IS_OK(expected_success_status)) {
4495 torture_assert(tctx,
4496 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4497 0, 0, 0),
4498 "expected account to not be locked");
4499 } else {
4500 torture_assert(tctx,
4501 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4502 1, 0, 0),
4503 "expected account to not be locked");
4506 torture_assert(tctx,
4507 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4508 "got wrong status from ChangePasswordUser2");
4510 /* bad pwd count will get updated */
4511 torture_assert(tctx,
4512 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4513 1, 1, 0),
4514 "expected account to not be locked");
4516 torture_assert(tctx,
4517 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4518 "got wrong status from ChangePasswordUser2");
4520 /* bad pwd count will get updated */
4521 torture_assert(tctx,
4522 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4523 2, 2, 0),
4524 "expected account to not be locked");
4526 torture_assert(tctx,
4527 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4528 "got wrong status from ChangePasswordUser2");
4530 /* bad pwd count should get updated */
4531 torture_assert(tctx,
4532 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4533 3, 3, ACB_AUTOLOCK),
4534 "expected account to be locked");
4536 torture_assert(tctx,
4537 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
4538 "got wrong status from ChangePasswordUser2");
4540 /* bad pwd count should not get updated */
4541 torture_assert(tctx,
4542 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4543 3, 3, ACB_AUTOLOCK),
4544 "expected account to be locked");
4546 /* let lockout duration expire ==> unlock */
4548 torture_comment(tctx, "let lockout duration expire...\n");
4549 sleep(lockout_seconds + 1);
4551 torture_assert(tctx,
4552 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4553 3, 0, 0),
4554 "expected account to not be locked");
4556 torture_assert(tctx,
4557 test_ChangePasswordUser2(p, tctx, acct_name, password, NULL, false),
4558 "got wrong status from ChangePasswordUser2");
4560 torture_assert(tctx,
4561 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4562 3, 0, 0),
4563 "expected account to not be locked");
4565 /* Used to reset the badPwdCount for the other tests */
4566 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4567 *password,
4568 expected_success_status, interactive))
4570 torture_fail(tctx, "failed to authenticate after lockout expired");
4573 if (NT_STATUS_IS_OK(expected_success_status)) {
4574 torture_assert(tctx,
4575 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4576 0, 0, 0),
4577 "expected account to not be locked");
4578 } else {
4579 torture_assert(tctx,
4580 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4581 3, 0, 0),
4582 "expected account to not be locked");
4585 return true;
4588 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4589 struct torture_context *tctx,
4590 uint32_t acct_flags,
4591 const char *acct_name,
4592 struct policy_handle *domain_handle,
4593 struct policy_handle *user_handle,
4594 char **password,
4595 struct cli_credentials *machine_credentials)
4597 union samr_DomainInfo *q_info, s_info;
4598 struct samr_DomInfo1 info1, _info1;
4599 struct samr_DomInfo12 info12, _info12;
4600 bool ret = true;
4601 struct dcerpc_binding_handle *b = p->binding_handle;
4602 struct dcerpc_pipe *np;
4603 int i;
4605 struct {
4606 const char *comment;
4607 bool disabled;
4608 bool interactive;
4609 uint32_t password_history_length;
4610 NTSTATUS expected_success_status;
4611 } creds[] = {
4613 .comment = "network logon (disabled account)",
4614 .disabled = true,
4615 .interactive = false,
4616 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4619 .comment = "network logon (enabled account)",
4620 .disabled = false,
4621 .interactive = false,
4622 .expected_success_status= NT_STATUS_OK
4625 .comment = "network logon (enabled account, history len = 1)",
4626 .disabled = false,
4627 .interactive = false,
4628 .expected_success_status= NT_STATUS_OK,
4629 .password_history_length = 1
4632 .comment = "interactive logon (disabled account)",
4633 .disabled = true,
4634 .interactive = true,
4635 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4638 .comment = "interactive logon (enabled account)",
4639 .disabled = false,
4640 .interactive = true,
4641 .expected_success_status= NT_STATUS_OK
4644 .comment = "interactive logon (enabled account, history len = 1)",
4645 .disabled = false,
4646 .interactive = true,
4647 .expected_success_status= NT_STATUS_OK,
4648 .password_history_length = 1
4652 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4654 /* backup old policies */
4656 torture_assert(tctx,
4657 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4658 DomainPasswordInformation, &q_info),
4659 "failed to query domain info level 1");
4661 info1 = q_info->info1;
4662 _info1 = info1;
4664 torture_assert(tctx,
4665 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4666 DomainLockoutInformation, &q_info),
4667 "failed to query domain info level 12");
4669 info12 = q_info->info12;
4670 _info12 = info12;
4672 /* run tests */
4674 for (i=0; i < ARRAY_SIZE(creds); i++) {
4675 bool test_passed;
4676 /* skip trust tests for now */
4677 if (acct_flags & ACB_WSTRUST ||
4678 acct_flags & ACB_SVRTRUST ||
4679 acct_flags & ACB_DOMTRUST) {
4680 continue;
4683 test_passed = test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4684 domain_handle, user_handle, password,
4685 machine_credentials,
4686 creds[i].comment,
4687 creds[i].disabled,
4688 creds[i].interactive,
4689 creds[i].password_history_length,
4690 creds[i].expected_success_status,
4691 &_info1, &_info12);
4692 ret &= test_passed;
4693 if (!test_passed) {
4694 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4695 break;
4696 } else {
4697 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4701 /* restore policies */
4703 s_info.info1 = info1;
4705 torture_assert(tctx,
4706 test_SetDomainInfo(b, tctx, domain_handle,
4707 DomainPasswordInformation, &s_info),
4708 "failed to set password information");
4710 s_info.info12 = info12;
4712 torture_assert(tctx,
4713 test_SetDomainInfo(b, tctx, domain_handle,
4714 DomainLockoutInformation, &s_info),
4715 "failed to set lockout information");
4717 return ret;
4720 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4721 struct dcerpc_pipe *lp,
4722 struct torture_context *tctx,
4723 struct policy_handle *domain_handle,
4724 struct policy_handle *lsa_handle,
4725 struct policy_handle *user_handle,
4726 const struct dom_sid *domain_sid,
4727 uint32_t rid,
4728 struct cli_credentials *machine_credentials)
4730 bool ret = true;
4731 struct dcerpc_binding_handle *b = p->binding_handle;
4732 struct dcerpc_binding_handle *lb = lp->binding_handle;
4734 struct policy_handle lsa_acct_handle;
4735 struct dom_sid *user_sid;
4737 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4740 struct lsa_EnumAccountRights r;
4741 struct lsa_RightSet rights;
4743 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4745 r.in.handle = lsa_handle;
4746 r.in.sid = user_sid;
4747 r.out.rights = &rights;
4749 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4750 "lsa_EnumAccountRights failed");
4751 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4752 "Expected enum rights for account to fail");
4756 struct lsa_RightSet rights;
4757 struct lsa_StringLarge names[2];
4758 struct lsa_AddAccountRights r;
4760 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4762 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4763 init_lsa_StringLarge(&names[1], NULL);
4765 rights.count = 1;
4766 rights.names = names;
4768 r.in.handle = lsa_handle;
4769 r.in.sid = user_sid;
4770 r.in.rights = &rights;
4772 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4773 "lsa_AddAccountRights failed");
4774 torture_assert_ntstatus_ok(tctx, r.out.result,
4775 "Failed to add privileges");
4779 struct lsa_EnumAccounts r;
4780 uint32_t resume_handle = 0;
4781 struct lsa_SidArray lsa_sid_array;
4782 int i;
4783 bool found_sid = false;
4785 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4787 r.in.handle = lsa_handle;
4788 r.in.num_entries = 0x1000;
4789 r.in.resume_handle = &resume_handle;
4790 r.out.sids = &lsa_sid_array;
4791 r.out.resume_handle = &resume_handle;
4793 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4794 "lsa_EnumAccounts failed");
4795 torture_assert_ntstatus_ok(tctx, r.out.result,
4796 "Failed to enum accounts");
4798 for (i=0; i < lsa_sid_array.num_sids; i++) {
4799 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4800 found_sid = true;
4804 torture_assert(tctx, found_sid,
4805 "failed to list privileged account");
4809 struct lsa_EnumAccountRights r;
4810 struct lsa_RightSet user_rights;
4812 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4814 r.in.handle = lsa_handle;
4815 r.in.sid = user_sid;
4816 r.out.rights = &user_rights;
4818 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4819 "lsa_EnumAccountRights failed");
4820 torture_assert_ntstatus_ok(tctx, r.out.result,
4821 "Failed to enum rights for account");
4823 if (user_rights.count < 1) {
4824 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4825 return false;
4830 struct lsa_OpenAccount r;
4832 torture_comment(tctx, "Testing LSA OpenAccount\n");
4834 r.in.handle = lsa_handle;
4835 r.in.sid = user_sid;
4836 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4837 r.out.acct_handle = &lsa_acct_handle;
4839 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4840 "lsa_OpenAccount failed");
4841 torture_assert_ntstatus_ok(tctx, r.out.result,
4842 "Failed to open lsa account");
4846 struct lsa_GetSystemAccessAccount r;
4847 uint32_t access_mask;
4849 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4851 r.in.handle = &lsa_acct_handle;
4852 r.out.access_mask = &access_mask;
4854 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4855 "lsa_GetSystemAccessAccount failed");
4856 torture_assert_ntstatus_ok(tctx, r.out.result,
4857 "Failed to get lsa system access account");
4861 struct lsa_Close r;
4863 torture_comment(tctx, "Testing LSA Close\n");
4865 r.in.handle = &lsa_acct_handle;
4866 r.out.handle = &lsa_acct_handle;
4868 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4869 "lsa_Close failed");
4870 torture_assert_ntstatus_ok(tctx, r.out.result,
4871 "Failed to close lsa");
4875 struct samr_DeleteUser r;
4877 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4879 r.in.user_handle = user_handle;
4880 r.out.user_handle = user_handle;
4882 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4883 "DeleteUser failed");
4884 torture_assert_ntstatus_ok(tctx, r.out.result,
4885 "DeleteUser failed");
4889 struct lsa_EnumAccounts r;
4890 uint32_t resume_handle = 0;
4891 struct lsa_SidArray lsa_sid_array;
4892 int i;
4893 bool found_sid = false;
4895 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4897 r.in.handle = lsa_handle;
4898 r.in.num_entries = 0x1000;
4899 r.in.resume_handle = &resume_handle;
4900 r.out.sids = &lsa_sid_array;
4901 r.out.resume_handle = &resume_handle;
4903 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4904 "lsa_EnumAccounts failed");
4905 torture_assert_ntstatus_ok(tctx, r.out.result,
4906 "Failed to enum accounts");
4908 for (i=0; i < lsa_sid_array.num_sids; i++) {
4909 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4910 found_sid = true;
4914 torture_assert(tctx, found_sid,
4915 "failed to list privileged account");
4919 struct lsa_EnumAccountRights r;
4920 struct lsa_RightSet user_rights;
4922 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4924 r.in.handle = lsa_handle;
4925 r.in.sid = user_sid;
4926 r.out.rights = &user_rights;
4928 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4929 "lsa_EnumAccountRights failed");
4930 torture_assert_ntstatus_ok(tctx, r.out.result,
4931 "Failed to enum rights for account");
4933 if (user_rights.count < 1) {
4934 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4935 return false;
4940 struct lsa_OpenAccount r;
4942 torture_comment(tctx, "Testing LSA OpenAccount\n");
4944 r.in.handle = lsa_handle;
4945 r.in.sid = user_sid;
4946 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4947 r.out.acct_handle = &lsa_acct_handle;
4949 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4950 "lsa_OpenAccount failed");
4951 torture_assert_ntstatus_ok(tctx, r.out.result,
4952 "Failed to open lsa account");
4956 struct lsa_GetSystemAccessAccount r;
4957 uint32_t access_mask;
4959 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4961 r.in.handle = &lsa_acct_handle;
4962 r.out.access_mask = &access_mask;
4964 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4965 "lsa_GetSystemAccessAccount failed");
4966 torture_assert_ntstatus_ok(tctx, r.out.result,
4967 "Failed to get lsa system access account");
4971 struct lsa_DeleteObject r;
4973 torture_comment(tctx, "Testing LSA DeleteObject\n");
4975 r.in.handle = &lsa_acct_handle;
4976 r.out.handle = &lsa_acct_handle;
4978 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4979 "lsa_DeleteObject failed");
4980 torture_assert_ntstatus_ok(tctx, r.out.result,
4981 "Failed to delete object");
4985 struct lsa_EnumAccounts r;
4986 uint32_t resume_handle = 0;
4987 struct lsa_SidArray lsa_sid_array;
4988 int i;
4989 bool found_sid = false;
4991 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4993 r.in.handle = lsa_handle;
4994 r.in.num_entries = 0x1000;
4995 r.in.resume_handle = &resume_handle;
4996 r.out.sids = &lsa_sid_array;
4997 r.out.resume_handle = &resume_handle;
4999 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
5000 "lsa_EnumAccounts failed");
5001 torture_assert_ntstatus_ok(tctx, r.out.result,
5002 "Failed to enum accounts");
5004 for (i=0; i < lsa_sid_array.num_sids; i++) {
5005 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
5006 found_sid = true;
5010 torture_assert(tctx, !found_sid,
5011 "should not have listed privileged account");
5015 struct lsa_EnumAccountRights r;
5016 struct lsa_RightSet user_rights;
5018 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
5020 r.in.handle = lsa_handle;
5021 r.in.sid = user_sid;
5022 r.out.rights = &user_rights;
5024 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
5025 "lsa_EnumAccountRights failed");
5026 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
5027 "Failed to enum rights for account");
5030 return ret;
5033 static bool test_user_ops(struct dcerpc_pipe *p,
5034 struct torture_context *tctx,
5035 struct policy_handle *user_handle,
5036 struct policy_handle *domain_handle,
5037 const struct dom_sid *domain_sid,
5038 uint32_t base_acct_flags,
5039 const char *base_acct_name, enum torture_samr_choice which_ops,
5040 struct cli_credentials *machine_credentials)
5042 char *password = NULL;
5043 struct samr_QueryUserInfo q;
5044 union samr_UserInfo *info;
5045 NTSTATUS status;
5046 struct dcerpc_binding_handle *b = p->binding_handle;
5048 bool ret = true;
5049 int i;
5050 uint32_t rid;
5051 const uint32_t password_fields[] = {
5052 SAMR_FIELD_NT_PASSWORD_PRESENT,
5053 SAMR_FIELD_LM_PASSWORD_PRESENT,
5054 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
5058 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
5059 if (!NT_STATUS_IS_OK(status)) {
5060 ret = false;
5063 switch (which_ops) {
5064 case TORTURE_SAMR_USER_ATTRIBUTES:
5065 if (!test_QuerySecurity(b, tctx, user_handle)) {
5066 ret = false;
5069 if (!test_QueryUserInfo(b, tctx, user_handle)) {
5070 ret = false;
5073 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
5074 ret = false;
5077 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
5078 base_acct_name)) {
5079 ret = false;
5082 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
5083 ret = false;
5086 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
5087 ret = false;
5090 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
5091 ret = false;
5093 break;
5094 case TORTURE_SAMR_PASSWORDS:
5095 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
5096 char simple_pass[9];
5097 char *v = generate_random_str(tctx, 1);
5099 ZERO_STRUCT(simple_pass);
5100 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5102 torture_comment(tctx, "Testing machine account password policy rules\n");
5104 /* Workstation trust accounts don't seem to need to honour password quality policy */
5105 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
5106 ret = false;
5109 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
5110 ret = false;
5113 /* reset again, to allow another 'user' password change */
5114 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
5115 ret = false;
5118 /* Try a 'short' password */
5119 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
5120 ret = false;
5123 /* Try a compleatly random password */
5124 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
5125 ret = false;
5129 for (i = 0; password_fields[i]; i++) {
5130 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
5131 ret = false;
5134 /* check it was set right */
5135 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5136 ret = false;
5140 for (i = 0; password_fields[i]; i++) {
5141 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
5142 ret = false;
5145 /* check it was set right */
5146 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5147 ret = false;
5151 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
5152 ret = false;
5155 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
5156 ret = false;
5159 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
5160 ret = false;
5163 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5164 ret = false;
5167 for (i = 0; password_fields[i]; i++) {
5169 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
5170 /* we need to skip as that would break
5171 * the ChangePasswordUser3 verify */
5172 continue;
5175 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
5176 ret = false;
5179 /* check it was set right */
5180 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5181 ret = false;
5185 q.in.user_handle = user_handle;
5186 q.in.level = 5;
5187 q.out.info = &info;
5189 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5190 "QueryUserInfo failed");
5191 if (!NT_STATUS_IS_OK(q.out.result)) {
5192 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5193 q.in.level, nt_errstr(q.out.result));
5194 ret = false;
5195 } else {
5196 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5197 if ((info->info5.acct_flags) != expected_flags) {
5198 /* FIXME: GD */
5199 if (!torture_setting_bool(tctx, "samba3", false)) {
5200 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5201 info->info5.acct_flags,
5202 expected_flags);
5203 ret = false;
5206 if (info->info5.rid != rid) {
5207 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
5208 info->info5.rid, rid);
5213 break;
5215 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
5217 /* test last password change timestamp behaviour */
5218 torture_assert(tctx, test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
5219 base_acct_name,
5220 user_handle, &password,
5221 machine_credentials),
5222 "pwdLastSet test failed\n");
5223 break;
5225 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
5227 /* test bad pwd count change behaviour */
5228 torture_assert(tctx, test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
5229 base_acct_name,
5230 domain_handle,
5231 user_handle, &password,
5232 machine_credentials),
5233 "badPwdCount test failed\n");
5234 break;
5236 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
5238 torture_assert(tctx, test_Password_lockout_wrap(p, tctx, base_acct_flags,
5239 base_acct_name,
5240 domain_handle,
5241 user_handle, &password,
5242 machine_credentials),
5243 "Lockout test failed");
5244 break;
5247 case TORTURE_SAMR_USER_PRIVILEGES: {
5249 struct dcerpc_pipe *lp;
5250 struct policy_handle *lsa_handle;
5251 struct dcerpc_binding_handle *lb;
5253 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
5254 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
5255 lb = lp->binding_handle;
5257 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
5258 ret = false;
5261 if (!test_DeleteUser_with_privs(p, lp, tctx,
5262 domain_handle, lsa_handle, user_handle,
5263 domain_sid, rid,
5264 machine_credentials)) {
5265 ret = false;
5268 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
5269 ret = false;
5272 if (!ret) {
5273 torture_result(tctx, TORTURE_FAIL, "privileged user delete test failed\n");
5276 break;
5278 case TORTURE_SAMR_OTHER:
5279 case TORTURE_SAMR_MANY_ACCOUNTS:
5280 case TORTURE_SAMR_MANY_GROUPS:
5281 case TORTURE_SAMR_MANY_ALIASES:
5282 /* We just need the account to exist */
5283 break;
5285 return ret;
5288 static bool test_alias_ops(struct dcerpc_binding_handle *b,
5289 struct torture_context *tctx,
5290 struct policy_handle *alias_handle,
5291 const struct dom_sid *domain_sid)
5293 bool ret = true;
5295 if (!torture_setting_bool(tctx, "samba3", false)) {
5296 if (!test_QuerySecurity(b, tctx, alias_handle)) {
5297 ret = false;
5301 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
5302 ret = false;
5305 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
5306 ret = false;
5309 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
5310 ret = false;
5313 if (torture_setting_bool(tctx, "samba3", false) ||
5314 torture_setting_bool(tctx, "samba4", false)) {
5315 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
5316 return ret;
5319 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
5320 ret = false;
5323 return ret;
5327 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
5328 struct torture_context *tctx,
5329 struct policy_handle *user_handle)
5331 struct samr_DeleteUser d;
5332 torture_comment(tctx, "Testing DeleteUser\n");
5334 d.in.user_handle = user_handle;
5335 d.out.user_handle = user_handle;
5337 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5338 "DeleteUser failed");
5339 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5341 return true;
5344 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5345 struct torture_context *tctx,
5346 struct policy_handle *handle, const char *name)
5348 NTSTATUS status;
5349 struct samr_DeleteUser d;
5350 struct policy_handle user_handle;
5351 uint32_t rid;
5353 status = test_LookupName(b, tctx, handle, name, &rid);
5354 if (!NT_STATUS_IS_OK(status)) {
5355 goto failed;
5358 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5359 if (!NT_STATUS_IS_OK(status)) {
5360 goto failed;
5363 d.in.user_handle = &user_handle;
5364 d.out.user_handle = &user_handle;
5365 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5366 "DeleteUser failed");
5367 if (!NT_STATUS_IS_OK(d.out.result)) {
5368 status = d.out.result;
5369 goto failed;
5372 return true;
5374 failed:
5375 torture_result(tctx, TORTURE_FAIL, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
5376 return false;
5380 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
5381 struct torture_context *tctx,
5382 struct policy_handle *handle, const char *name)
5384 NTSTATUS status;
5385 struct samr_OpenGroup r;
5386 struct samr_DeleteDomainGroup d;
5387 struct policy_handle group_handle;
5388 uint32_t rid;
5390 status = test_LookupName(b, tctx, handle, name, &rid);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 goto failed;
5395 r.in.domain_handle = handle;
5396 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5397 r.in.rid = rid;
5398 r.out.group_handle = &group_handle;
5399 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5400 "OpenGroup failed");
5401 if (!NT_STATUS_IS_OK(r.out.result)) {
5402 status = r.out.result;
5403 goto failed;
5406 d.in.group_handle = &group_handle;
5407 d.out.group_handle = &group_handle;
5408 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
5409 "DeleteDomainGroup failed");
5410 if (!NT_STATUS_IS_OK(d.out.result)) {
5411 status = d.out.result;
5412 goto failed;
5415 return true;
5417 failed:
5418 torture_result(tctx, TORTURE_FAIL, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
5419 return false;
5423 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
5424 struct torture_context *tctx,
5425 struct policy_handle *domain_handle,
5426 const char *name)
5428 NTSTATUS status;
5429 struct samr_OpenAlias r;
5430 struct samr_DeleteDomAlias d;
5431 struct policy_handle alias_handle;
5432 uint32_t rid;
5434 torture_comment(tctx, "Testing DeleteAlias_byname\n");
5436 status = test_LookupName(b, tctx, domain_handle, name, &rid);
5437 if (!NT_STATUS_IS_OK(status)) {
5438 goto failed;
5441 r.in.domain_handle = domain_handle;
5442 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5443 r.in.rid = rid;
5444 r.out.alias_handle = &alias_handle;
5445 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5446 "OpenAlias failed");
5447 if (!NT_STATUS_IS_OK(r.out.result)) {
5448 status = r.out.result;
5449 goto failed;
5452 d.in.alias_handle = &alias_handle;
5453 d.out.alias_handle = &alias_handle;
5454 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5455 "DeleteDomAlias failed");
5456 if (!NT_STATUS_IS_OK(d.out.result)) {
5457 status = d.out.result;
5458 goto failed;
5461 return true;
5463 failed:
5464 torture_result(tctx, TORTURE_FAIL, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5465 return false;
5468 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5469 struct torture_context *tctx,
5470 struct policy_handle *alias_handle)
5472 struct samr_DeleteDomAlias d;
5473 bool ret = true;
5475 torture_comment(tctx, "Testing DeleteAlias\n");
5477 d.in.alias_handle = alias_handle;
5478 d.out.alias_handle = alias_handle;
5480 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5481 "DeleteDomAlias failed");
5482 if (!NT_STATUS_IS_OK(d.out.result)) {
5483 torture_result(tctx, TORTURE_FAIL, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5484 ret = false;
5487 return ret;
5490 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5491 struct torture_context *tctx,
5492 struct policy_handle *domain_handle,
5493 const char *alias_name,
5494 struct policy_handle *alias_handle,
5495 const struct dom_sid *domain_sid,
5496 bool test_alias)
5498 struct samr_CreateDomAlias r;
5499 struct lsa_String name;
5500 uint32_t rid;
5501 bool ret = true;
5503 init_lsa_String(&name, alias_name);
5504 r.in.domain_handle = domain_handle;
5505 r.in.alias_name = &name;
5506 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5507 r.out.alias_handle = alias_handle;
5508 r.out.rid = &rid;
5510 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5512 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5513 "CreateDomAlias failed");
5515 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5516 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5517 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5518 return true;
5519 } else {
5520 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5521 nt_errstr(r.out.result));
5522 return false;
5526 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5527 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5528 return false;
5530 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5531 "CreateDomAlias failed");
5534 if (!NT_STATUS_IS_OK(r.out.result)) {
5535 torture_result(tctx, TORTURE_FAIL, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5536 return false;
5539 if (!test_alias) {
5540 return ret;
5543 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5544 ret = false;
5547 return ret;
5550 static bool test_ChangePassword(struct dcerpc_pipe *p,
5551 struct torture_context *tctx,
5552 const char *acct_name,
5553 struct policy_handle *domain_handle, char **password)
5555 bool ret = true;
5556 struct dcerpc_binding_handle *b = p->binding_handle;
5558 if (!*password) {
5559 return false;
5562 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5563 ret = false;
5566 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5567 ret = false;
5570 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5571 ret = false;
5574 /* test what happens when setting the old password again */
5575 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5576 ret = false;
5580 char simple_pass[9];
5581 char *v = generate_random_str(tctx, 1);
5583 ZERO_STRUCT(simple_pass);
5584 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5586 /* test what happens when picking a simple password */
5587 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5588 ret = false;
5592 /* set samr_SetDomainInfo level 1 with min_length 5 */
5594 struct samr_QueryDomainInfo r;
5595 union samr_DomainInfo *info = NULL;
5596 struct samr_SetDomainInfo s;
5597 uint16_t len_old, len;
5598 uint32_t pwd_prop_old;
5599 int64_t min_pwd_age_old;
5601 len = 5;
5603 r.in.domain_handle = domain_handle;
5604 r.in.level = 1;
5605 r.out.info = &info;
5607 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5608 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5609 "QueryDomainInfo failed");
5610 if (!NT_STATUS_IS_OK(r.out.result)) {
5611 return false;
5614 s.in.domain_handle = domain_handle;
5615 s.in.level = 1;
5616 s.in.info = info;
5618 /* remember the old min length, so we can reset it */
5619 len_old = s.in.info->info1.min_password_length;
5620 s.in.info->info1.min_password_length = len;
5621 pwd_prop_old = s.in.info->info1.password_properties;
5622 /* turn off password complexity checks for this test */
5623 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5625 min_pwd_age_old = s.in.info->info1.min_password_age;
5626 s.in.info->info1.min_password_age = 0;
5628 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5629 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5630 "SetDomainInfo failed");
5631 if (!NT_STATUS_IS_OK(s.out.result)) {
5632 return false;
5635 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5637 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5638 ret = false;
5641 s.in.info->info1.min_password_length = len_old;
5642 s.in.info->info1.password_properties = pwd_prop_old;
5643 s.in.info->info1.min_password_age = min_pwd_age_old;
5645 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5646 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5647 "SetDomainInfo failed");
5648 if (!NT_STATUS_IS_OK(s.out.result)) {
5649 return false;
5655 struct samr_OpenUser r;
5656 struct samr_QueryUserInfo q;
5657 union samr_UserInfo *info;
5658 struct samr_LookupNames n;
5659 struct policy_handle user_handle;
5660 struct samr_Ids rids, types;
5662 n.in.domain_handle = domain_handle;
5663 n.in.num_names = 1;
5664 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5665 n.in.names[0].string = acct_name;
5666 n.out.rids = &rids;
5667 n.out.types = &types;
5669 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5670 "LookupNames failed");
5671 if (!NT_STATUS_IS_OK(n.out.result)) {
5672 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5673 return false;
5676 r.in.domain_handle = domain_handle;
5677 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5678 r.in.rid = n.out.rids->ids[0];
5679 r.out.user_handle = &user_handle;
5681 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5682 "OpenUser failed");
5683 if (!NT_STATUS_IS_OK(r.out.result)) {
5684 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5685 return false;
5688 q.in.user_handle = &user_handle;
5689 q.in.level = 5;
5690 q.out.info = &info;
5692 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5693 "QueryUserInfo failed");
5694 if (!NT_STATUS_IS_OK(q.out.result)) {
5695 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5696 return false;
5699 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5701 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5702 info->info5.last_password_change, true)) {
5703 ret = false;
5707 /* we change passwords twice - this has the effect of verifying
5708 they were changed correctly for the final call */
5709 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5710 ret = false;
5713 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5714 ret = false;
5717 return ret;
5720 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5721 struct policy_handle *domain_handle,
5722 const char *user_name,
5723 struct policy_handle *user_handle_out,
5724 struct dom_sid *domain_sid,
5725 enum torture_samr_choice which_ops,
5726 struct cli_credentials *machine_credentials,
5727 bool test_user)
5730 TALLOC_CTX *user_ctx;
5732 struct samr_CreateUser r;
5733 struct samr_QueryUserInfo q;
5734 union samr_UserInfo *info;
5735 struct samr_DeleteUser d;
5736 uint32_t rid;
5738 /* This call creates a 'normal' account - check that it really does */
5739 const uint32_t acct_flags = ACB_NORMAL;
5740 struct lsa_String name;
5741 bool ret = true;
5742 struct dcerpc_binding_handle *b = p->binding_handle;
5744 struct policy_handle user_handle;
5745 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5746 init_lsa_String(&name, user_name);
5748 r.in.domain_handle = domain_handle;
5749 r.in.account_name = &name;
5750 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5751 r.out.user_handle = &user_handle;
5752 r.out.rid = &rid;
5754 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5756 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5757 "CreateUser failed");
5759 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5760 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5761 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5762 return true;
5763 } else {
5764 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5765 nt_errstr(r.out.result));
5766 return false;
5770 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5771 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5772 talloc_free(user_ctx);
5773 return false;
5775 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5776 "CreateUser failed");
5779 if (!NT_STATUS_IS_OK(r.out.result)) {
5780 talloc_free(user_ctx);
5781 torture_result(tctx, TORTURE_FAIL, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5782 return false;
5785 if (!test_user) {
5786 if (user_handle_out) {
5787 *user_handle_out = user_handle;
5789 return ret;
5793 q.in.user_handle = &user_handle;
5794 q.in.level = 16;
5795 q.out.info = &info;
5797 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5798 "QueryUserInfo failed");
5799 if (!NT_STATUS_IS_OK(q.out.result)) {
5800 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5801 q.in.level, nt_errstr(q.out.result));
5802 ret = false;
5803 } else {
5804 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5805 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5806 info->info16.acct_flags,
5807 acct_flags);
5808 ret = false;
5812 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5813 domain_sid, acct_flags, name.string, which_ops,
5814 machine_credentials)) {
5815 ret = false;
5818 if (user_handle_out) {
5819 *user_handle_out = user_handle;
5820 } else {
5821 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5823 d.in.user_handle = &user_handle;
5824 d.out.user_handle = &user_handle;
5826 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5827 "DeleteUser failed");
5828 if (!NT_STATUS_IS_OK(d.out.result)) {
5829 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5830 ret = false;
5836 talloc_free(user_ctx);
5838 return ret;
5842 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5843 struct policy_handle *domain_handle,
5844 struct dom_sid *domain_sid,
5845 enum torture_samr_choice which_ops,
5846 struct cli_credentials *machine_credentials)
5848 struct samr_CreateUser2 r;
5849 struct samr_QueryUserInfo q;
5850 union samr_UserInfo *info;
5851 struct samr_DeleteUser d;
5852 struct policy_handle user_handle;
5853 uint32_t rid;
5854 struct lsa_String name;
5855 bool ret = true;
5856 int i;
5857 struct dcerpc_binding_handle *b = p->binding_handle;
5859 struct {
5860 uint32_t acct_flags;
5861 const char *account_name;
5862 NTSTATUS nt_status;
5863 } account_types[] = {
5864 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5865 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5866 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5867 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5868 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5869 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5870 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5871 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5872 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5873 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5874 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5875 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5876 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5877 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5878 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5881 for (i = 0; account_types[i].account_name; i++) {
5882 TALLOC_CTX *user_ctx;
5883 uint32_t acct_flags = account_types[i].acct_flags;
5884 uint32_t access_granted;
5885 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5886 init_lsa_String(&name, account_types[i].account_name);
5888 r.in.domain_handle = domain_handle;
5889 r.in.account_name = &name;
5890 r.in.acct_flags = acct_flags;
5891 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5892 r.out.user_handle = &user_handle;
5893 r.out.access_granted = &access_granted;
5894 r.out.rid = &rid;
5896 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5898 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5899 "CreateUser2 failed");
5901 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5902 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5903 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5904 continue;
5905 } else {
5906 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5907 nt_errstr(r.out.result));
5908 ret = false;
5909 continue;
5913 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5914 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5915 talloc_free(user_ctx);
5916 ret = false;
5917 continue;
5919 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5920 "CreateUser2 failed");
5923 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5924 torture_result(tctx, TORTURE_FAIL, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5925 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5926 ret = false;
5929 if (NT_STATUS_IS_OK(r.out.result)) {
5930 q.in.user_handle = &user_handle;
5931 q.in.level = 5;
5932 q.out.info = &info;
5934 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5935 "QueryUserInfo failed");
5936 if (!NT_STATUS_IS_OK(q.out.result)) {
5937 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5938 q.in.level, nt_errstr(q.out.result));
5939 ret = false;
5940 } else {
5941 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5942 if (acct_flags == ACB_NORMAL) {
5943 expected_flags |= ACB_PW_EXPIRED;
5945 if ((info->info5.acct_flags) != expected_flags) {
5946 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5947 info->info5.acct_flags,
5948 expected_flags);
5949 ret = false;
5951 switch (acct_flags) {
5952 case ACB_SVRTRUST:
5953 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5954 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5955 DOMAIN_RID_DCS, info->info5.primary_gid);
5956 ret = false;
5958 break;
5959 case ACB_WSTRUST:
5960 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5961 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5962 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5963 ret = false;
5965 break;
5966 case ACB_NORMAL:
5967 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5968 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5969 DOMAIN_RID_USERS, info->info5.primary_gid);
5970 ret = false;
5972 break;
5976 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5977 domain_sid, acct_flags, name.string, which_ops,
5978 machine_credentials)) {
5979 ret = false;
5982 if (!ndr_policy_handle_empty(&user_handle)) {
5983 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5985 d.in.user_handle = &user_handle;
5986 d.out.user_handle = &user_handle;
5988 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5989 "DeleteUser failed");
5990 if (!NT_STATUS_IS_OK(d.out.result)) {
5991 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5992 ret = false;
5996 talloc_free(user_ctx);
5999 return ret;
6002 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
6003 struct torture_context *tctx,
6004 struct policy_handle *handle)
6006 struct samr_QueryAliasInfo r;
6007 union samr_AliasInfo *info;
6008 uint16_t levels[] = {1, 2, 3};
6009 int i;
6010 bool ret = true;
6012 for (i=0;i<ARRAY_SIZE(levels);i++) {
6013 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
6015 r.in.alias_handle = handle;
6016 r.in.level = levels[i];
6017 r.out.info = &info;
6019 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
6020 "QueryAliasInfo failed");
6021 if (!NT_STATUS_IS_OK(r.out.result)) {
6022 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
6023 levels[i], nt_errstr(r.out.result));
6024 ret = false;
6028 return ret;
6031 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
6032 struct torture_context *tctx,
6033 struct policy_handle *handle)
6035 struct samr_QueryGroupInfo r;
6036 union samr_GroupInfo *info;
6037 uint16_t levels[] = {1, 2, 3, 4, 5};
6038 int i;
6039 bool ret = true;
6041 for (i=0;i<ARRAY_SIZE(levels);i++) {
6042 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
6044 r.in.group_handle = handle;
6045 r.in.level = levels[i];
6046 r.out.info = &info;
6048 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
6049 "QueryGroupInfo failed");
6050 if (!NT_STATUS_IS_OK(r.out.result)) {
6051 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
6052 levels[i], nt_errstr(r.out.result));
6053 ret = false;
6057 return ret;
6060 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
6061 struct torture_context *tctx,
6062 struct policy_handle *handle)
6064 struct samr_QueryGroupMember r;
6065 struct samr_RidAttrArray *rids = NULL;
6066 bool ret = true;
6068 torture_comment(tctx, "Testing QueryGroupMember\n");
6070 r.in.group_handle = handle;
6071 r.out.rids = &rids;
6073 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
6074 "QueryGroupMember failed");
6075 if (!NT_STATUS_IS_OK(r.out.result)) {
6076 torture_result(tctx, TORTURE_FAIL, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
6077 ret = false;
6080 return ret;
6084 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
6085 struct torture_context *tctx,
6086 struct policy_handle *handle)
6088 struct samr_QueryGroupInfo r;
6089 union samr_GroupInfo *info;
6090 struct samr_SetGroupInfo s;
6091 uint16_t levels[] = {1, 2, 3, 4};
6092 uint16_t set_ok[] = {0, 1, 1, 1};
6093 int i;
6094 bool ret = true;
6096 for (i=0;i<ARRAY_SIZE(levels);i++) {
6097 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
6099 r.in.group_handle = handle;
6100 r.in.level = levels[i];
6101 r.out.info = &info;
6103 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
6104 "QueryGroupInfo failed");
6105 if (!NT_STATUS_IS_OK(r.out.result)) {
6106 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
6107 levels[i], nt_errstr(r.out.result));
6108 ret = false;
6111 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
6113 s.in.group_handle = handle;
6114 s.in.level = levels[i];
6115 s.in.info = *r.out.info;
6117 #if 0
6118 /* disabled this, as it changes the name only from the point of view of samr,
6119 but leaves the name from the point of view of w2k3 internals (and ldap). This means
6120 the name is still reserved, so creating the old name fails, but deleting by the old name
6121 also fails */
6122 if (s.in.level == 2) {
6123 init_lsa_String(&s.in.info->string, "NewName");
6125 #endif
6127 if (s.in.level == 4) {
6128 init_lsa_String(&s.in.info->description, "test description");
6131 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
6132 "SetGroupInfo failed");
6133 if (set_ok[i]) {
6134 if (!NT_STATUS_IS_OK(s.out.result)) {
6135 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u failed - %s\n",
6136 r.in.level, nt_errstr(s.out.result));
6137 ret = false;
6138 continue;
6140 } else {
6141 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6142 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6143 r.in.level, nt_errstr(s.out.result));
6144 ret = false;
6145 continue;
6150 return ret;
6153 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
6154 struct torture_context *tctx,
6155 struct policy_handle *handle)
6157 struct samr_QueryUserInfo r;
6158 union samr_UserInfo *info;
6159 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6160 11, 12, 13, 14, 16, 17, 20, 21};
6161 int i;
6162 bool ret = true;
6164 for (i=0;i<ARRAY_SIZE(levels);i++) {
6165 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
6167 r.in.user_handle = handle;
6168 r.in.level = levels[i];
6169 r.out.info = &info;
6171 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
6172 "QueryUserInfo failed");
6173 if (!NT_STATUS_IS_OK(r.out.result)) {
6174 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
6175 levels[i], nt_errstr(r.out.result));
6176 ret = false;
6180 return ret;
6183 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
6184 struct torture_context *tctx,
6185 struct policy_handle *handle)
6187 struct samr_QueryUserInfo2 r;
6188 union samr_UserInfo *info;
6189 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6190 11, 12, 13, 14, 16, 17, 20, 21};
6191 int i;
6192 bool ret = true;
6194 for (i=0;i<ARRAY_SIZE(levels);i++) {
6195 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
6197 r.in.user_handle = handle;
6198 r.in.level = levels[i];
6199 r.out.info = &info;
6201 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
6202 "QueryUserInfo2 failed");
6203 if (!NT_STATUS_IS_OK(r.out.result)) {
6204 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo2 level %u failed - %s\n",
6205 levels[i], nt_errstr(r.out.result));
6206 ret = false;
6210 return ret;
6213 static bool test_OpenUser(struct dcerpc_binding_handle *b,
6214 struct torture_context *tctx,
6215 struct policy_handle *handle, uint32_t rid)
6217 struct samr_OpenUser r;
6218 struct policy_handle user_handle;
6219 bool ret = true;
6221 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6223 r.in.domain_handle = handle;
6224 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6225 r.in.rid = rid;
6226 r.out.user_handle = &user_handle;
6228 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6229 "OpenUser failed");
6230 if (!NT_STATUS_IS_OK(r.out.result)) {
6231 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6232 return false;
6235 if (!test_QuerySecurity(b, tctx, &user_handle)) {
6236 ret = false;
6239 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
6240 ret = false;
6243 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
6244 ret = false;
6247 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
6248 ret = false;
6251 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
6252 ret = false;
6255 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6256 ret = false;
6259 return ret;
6262 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
6263 struct torture_context *tctx,
6264 struct policy_handle *handle, uint32_t rid)
6266 struct samr_OpenGroup r;
6267 struct policy_handle group_handle;
6268 bool ret = true;
6270 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
6272 r.in.domain_handle = handle;
6273 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6274 r.in.rid = rid;
6275 r.out.group_handle = &group_handle;
6277 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
6278 "OpenGroup failed");
6279 if (!NT_STATUS_IS_OK(r.out.result)) {
6280 torture_result(tctx, TORTURE_FAIL, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6281 return false;
6284 if (!torture_setting_bool(tctx, "samba3", false)) {
6285 if (!test_QuerySecurity(b, tctx, &group_handle)) {
6286 ret = false;
6290 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
6291 ret = false;
6294 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
6295 ret = false;
6298 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
6299 ret = false;
6302 return ret;
6305 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
6306 struct torture_context *tctx,
6307 struct policy_handle *handle, uint32_t rid)
6309 struct samr_OpenAlias r;
6310 struct policy_handle alias_handle;
6311 bool ret = true;
6313 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
6315 r.in.domain_handle = handle;
6316 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6317 r.in.rid = rid;
6318 r.out.alias_handle = &alias_handle;
6320 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
6321 "OpenAlias failed");
6322 if (!NT_STATUS_IS_OK(r.out.result)) {
6323 torture_result(tctx, TORTURE_FAIL, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6324 return false;
6327 if (!torture_setting_bool(tctx, "samba3", false)) {
6328 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
6329 ret = false;
6333 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6334 ret = false;
6337 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6338 ret = false;
6341 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6342 ret = false;
6345 return ret;
6348 static bool check_mask(struct dcerpc_binding_handle *b,
6349 struct torture_context *tctx,
6350 struct policy_handle *handle, uint32_t rid,
6351 uint32_t acct_flag_mask)
6353 struct samr_OpenUser r;
6354 struct samr_QueryUserInfo q;
6355 union samr_UserInfo *info;
6356 struct policy_handle user_handle;
6357 bool ret = true;
6359 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6361 r.in.domain_handle = handle;
6362 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6363 r.in.rid = rid;
6364 r.out.user_handle = &user_handle;
6366 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6367 "OpenUser failed");
6368 if (!NT_STATUS_IS_OK(r.out.result)) {
6369 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6370 return false;
6373 q.in.user_handle = &user_handle;
6374 q.in.level = 16;
6375 q.out.info = &info;
6377 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6378 "QueryUserInfo failed");
6379 if (!NT_STATUS_IS_OK(q.out.result)) {
6380 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed - %s\n",
6381 nt_errstr(q.out.result));
6382 ret = false;
6383 } else {
6384 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
6385 torture_result(tctx, TORTURE_FAIL, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
6386 acct_flag_mask, info->info16.acct_flags, rid);
6387 ret = false;
6391 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6392 ret = false;
6395 return ret;
6398 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
6399 struct torture_context *tctx,
6400 struct policy_handle *handle)
6402 struct samr_EnumDomainUsers r;
6403 uint32_t mask, resume_handle=0;
6404 int i, mask_idx;
6405 bool ret = true;
6406 struct samr_LookupNames n;
6407 struct samr_LookupRids lr ;
6408 struct lsa_Strings names;
6409 struct samr_Ids rids, types;
6410 struct samr_SamArray *sam = NULL;
6411 uint32_t num_entries = 0;
6413 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
6414 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
6415 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
6416 ACB_PWNOEXP, 0};
6418 torture_comment(tctx, "Testing EnumDomainUsers\n");
6420 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
6421 r.in.domain_handle = handle;
6422 r.in.resume_handle = &resume_handle;
6423 r.in.acct_flags = mask = masks[mask_idx];
6424 r.in.max_size = (uint32_t)-1;
6425 r.out.resume_handle = &resume_handle;
6426 r.out.num_entries = &num_entries;
6427 r.out.sam = &sam;
6429 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
6430 "EnumDomainUsers failed");
6431 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6432 !NT_STATUS_IS_OK(r.out.result)) {
6433 torture_result(tctx, TORTURE_FAIL, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
6434 return false;
6437 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6439 if (sam->count == 0) {
6440 continue;
6443 for (i=0;i<sam->count;i++) {
6444 if (mask) {
6445 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6446 ret = false;
6448 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6449 ret = false;
6454 torture_comment(tctx, "Testing LookupNames\n");
6455 n.in.domain_handle = handle;
6456 n.in.num_names = sam->count;
6457 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6458 n.out.rids = &rids;
6459 n.out.types = &types;
6460 for (i=0;i<sam->count;i++) {
6461 n.in.names[i].string = sam->entries[i].name.string;
6463 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6464 "LookupNames failed");
6465 if (!NT_STATUS_IS_OK(n.out.result)) {
6466 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6467 ret = false;
6471 torture_comment(tctx, "Testing LookupRids\n");
6472 lr.in.domain_handle = handle;
6473 lr.in.num_rids = sam->count;
6474 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6475 lr.out.names = &names;
6476 lr.out.types = &types;
6477 for (i=0;i<sam->count;i++) {
6478 lr.in.rids[i] = sam->entries[i].idx;
6480 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6481 "LookupRids failed");
6482 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6484 return ret;
6488 try blasting the server with a bunch of sync requests
6490 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6491 struct policy_handle *handle)
6493 struct samr_EnumDomainUsers r;
6494 uint32_t resume_handle=0;
6495 int i;
6496 #define ASYNC_COUNT 100
6497 struct tevent_req *req[ASYNC_COUNT];
6499 if (!torture_setting_bool(tctx, "dangerous", false)) {
6500 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6503 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6505 r.in.domain_handle = handle;
6506 r.in.resume_handle = &resume_handle;
6507 r.in.acct_flags = 0;
6508 r.in.max_size = (uint32_t)-1;
6509 r.out.resume_handle = &resume_handle;
6511 for (i=0;i<ASYNC_COUNT;i++) {
6512 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6515 for (i=0;i<ASYNC_COUNT;i++) {
6516 tevent_req_poll(req[i], tctx->ev);
6517 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6518 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6519 i, nt_errstr(r.out.result)));
6522 torture_comment(tctx, "%d async requests OK\n", i);
6524 return true;
6527 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6528 struct torture_context *tctx,
6529 struct policy_handle *handle)
6531 struct samr_EnumDomainGroups r;
6532 uint32_t resume_handle=0;
6533 struct samr_SamArray *sam = NULL;
6534 uint32_t num_entries = 0;
6535 int i;
6536 bool ret = true;
6537 bool universal_group_found = false;
6539 torture_comment(tctx, "Testing EnumDomainGroups\n");
6541 r.in.domain_handle = handle;
6542 r.in.resume_handle = &resume_handle;
6543 r.in.max_size = (uint32_t)-1;
6544 r.out.resume_handle = &resume_handle;
6545 r.out.num_entries = &num_entries;
6546 r.out.sam = &sam;
6548 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6549 "EnumDomainGroups failed");
6550 if (!NT_STATUS_IS_OK(r.out.result)) {
6551 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6552 return false;
6555 if (!sam) {
6556 return false;
6559 for (i=0;i<sam->count;i++) {
6560 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6561 ret = false;
6563 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6564 "Enterprise Admins") == 0)) {
6565 universal_group_found = true;
6569 /* when we are running this on s4 we should get back at least the
6570 * "Enterprise Admins" universal group. If we don't get a group entry
6571 * at all we probably are performing the test on the builtin domain.
6572 * So ignore this case. */
6573 if (torture_setting_bool(tctx, "samba4", false)) {
6574 if ((sam->count > 0) && (!universal_group_found)) {
6575 ret = false;
6579 return ret;
6582 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6583 struct torture_context *tctx,
6584 struct policy_handle *handle)
6586 struct samr_EnumDomainAliases r;
6587 uint32_t resume_handle=0;
6588 struct samr_SamArray *sam = NULL;
6589 uint32_t num_entries = 0;
6590 int i;
6591 bool ret = true;
6593 torture_comment(tctx, "Testing EnumDomainAliases\n");
6595 r.in.domain_handle = handle;
6596 r.in.resume_handle = &resume_handle;
6597 r.in.max_size = (uint32_t)-1;
6598 r.out.sam = &sam;
6599 r.out.num_entries = &num_entries;
6600 r.out.resume_handle = &resume_handle;
6602 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6603 "EnumDomainAliases failed");
6604 if (!NT_STATUS_IS_OK(r.out.result)) {
6605 torture_result(tctx, TORTURE_FAIL, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6606 return false;
6609 if (!sam) {
6610 return false;
6613 for (i=0;i<sam->count;i++) {
6614 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6615 ret = false;
6619 return ret;
6622 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6623 struct torture_context *tctx,
6624 struct policy_handle *handle)
6626 struct samr_GetDisplayEnumerationIndex r;
6627 bool ret = true;
6628 uint16_t levels[] = {1, 2, 3, 4, 5};
6629 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6630 struct lsa_String name;
6631 uint32_t idx = 0;
6632 int i;
6634 for (i=0;i<ARRAY_SIZE(levels);i++) {
6635 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6637 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6639 r.in.domain_handle = handle;
6640 r.in.level = levels[i];
6641 r.in.name = &name;
6642 r.out.idx = &idx;
6644 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6645 "GetDisplayEnumerationIndex failed");
6647 if (ok_lvl[i] &&
6648 !NT_STATUS_IS_OK(r.out.result) &&
6649 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6650 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6651 levels[i], nt_errstr(r.out.result));
6652 ret = false;
6655 init_lsa_String(&name, "zzzzzzzz");
6657 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6658 "GetDisplayEnumerationIndex failed");
6660 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6661 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6662 levels[i], nt_errstr(r.out.result));
6663 ret = false;
6667 return ret;
6670 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6671 struct torture_context *tctx,
6672 struct policy_handle *handle)
6674 struct samr_GetDisplayEnumerationIndex2 r;
6675 bool ret = true;
6676 uint16_t levels[] = {1, 2, 3, 4, 5};
6677 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6678 struct lsa_String name;
6679 uint32_t idx = 0;
6680 int i;
6682 for (i=0;i<ARRAY_SIZE(levels);i++) {
6683 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6685 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6687 r.in.domain_handle = handle;
6688 r.in.level = levels[i];
6689 r.in.name = &name;
6690 r.out.idx = &idx;
6692 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6693 "GetDisplayEnumerationIndex2 failed");
6694 if (ok_lvl[i] &&
6695 !NT_STATUS_IS_OK(r.out.result) &&
6696 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6697 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6698 levels[i], nt_errstr(r.out.result));
6699 ret = false;
6702 init_lsa_String(&name, "zzzzzzzz");
6704 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6705 "GetDisplayEnumerationIndex2 failed");
6706 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6707 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6708 levels[i], nt_errstr(r.out.result));
6709 ret = false;
6713 return ret;
6716 #define STRING_EQUAL_QUERY(s1, s2, user) \
6717 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6718 /* odd, but valid */ \
6719 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6720 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: %s != %s (%s)\n", \
6721 #s1, user.string, s1.string, s2.string, __location__); \
6722 ret = false; \
6724 #define INT_EQUAL_QUERY(s1, s2, user) \
6725 if (s1 != s2) { \
6726 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6727 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6728 ret = false; \
6731 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6732 struct torture_context *tctx,
6733 struct samr_QueryDisplayInfo *querydisplayinfo,
6734 bool *seen_testuser)
6736 struct samr_OpenUser r;
6737 struct samr_QueryUserInfo q;
6738 union samr_UserInfo *info;
6739 struct policy_handle user_handle;
6740 int i, ret = true;
6741 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6742 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6743 for (i = 0; ; i++) {
6744 switch (querydisplayinfo->in.level) {
6745 case 1:
6746 if (i >= querydisplayinfo->out.info->info1.count) {
6747 return ret;
6749 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6750 break;
6751 case 2:
6752 if (i >= querydisplayinfo->out.info->info2.count) {
6753 return ret;
6755 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6756 break;
6757 case 3:
6758 /* Groups */
6759 case 4:
6760 case 5:
6761 /* Not interested in validating just the account name */
6762 return true;
6765 r.out.user_handle = &user_handle;
6767 switch (querydisplayinfo->in.level) {
6768 case 1:
6769 case 2:
6770 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6771 "OpenUser failed");
6772 if (!NT_STATUS_IS_OK(r.out.result)) {
6773 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6774 return false;
6778 q.in.user_handle = &user_handle;
6779 q.in.level = 21;
6780 q.out.info = &info;
6781 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6782 "QueryUserInfo failed");
6783 if (!NT_STATUS_IS_OK(r.out.result)) {
6784 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6785 return false;
6788 switch (querydisplayinfo->in.level) {
6789 case 1:
6790 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6791 *seen_testuser = true;
6793 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6794 info->info21.full_name, info->info21.account_name);
6795 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6796 info->info21.account_name, info->info21.account_name);
6797 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6798 info->info21.description, info->info21.account_name);
6799 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6800 info->info21.rid, info->info21.account_name);
6801 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6802 info->info21.acct_flags, info->info21.account_name);
6804 break;
6805 case 2:
6806 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6807 info->info21.account_name, info->info21.account_name);
6808 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6809 info->info21.description, info->info21.account_name);
6810 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6811 info->info21.rid, info->info21.account_name);
6812 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6813 info->info21.acct_flags, info->info21.account_name);
6815 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6816 torture_result(tctx, TORTURE_FAIL, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6817 info->info21.account_name.string);
6820 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6821 torture_result(tctx, TORTURE_FAIL, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6822 info->info21.account_name.string,
6823 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6824 info->info21.acct_flags);
6825 return false;
6828 break;
6831 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6832 return false;
6835 return ret;
6838 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6839 struct torture_context *tctx,
6840 struct policy_handle *handle)
6842 struct samr_QueryDisplayInfo r;
6843 struct samr_QueryDomainInfo dom_info;
6844 union samr_DomainInfo *info = NULL;
6845 bool ret = true;
6846 uint16_t levels[] = {1, 2, 3, 4, 5};
6847 int i;
6848 bool seen_testuser = false;
6849 uint32_t total_size;
6850 uint32_t returned_size;
6851 union samr_DispInfo disp_info;
6854 for (i=0;i<ARRAY_SIZE(levels);i++) {
6855 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6857 r.in.start_idx = 0;
6858 r.out.result = STATUS_MORE_ENTRIES;
6859 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6860 r.in.domain_handle = handle;
6861 r.in.level = levels[i];
6862 r.in.max_entries = 2;
6863 r.in.buf_size = (uint32_t)-1;
6864 r.out.total_size = &total_size;
6865 r.out.returned_size = &returned_size;
6866 r.out.info = &disp_info;
6868 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6869 "QueryDisplayInfo failed");
6870 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6871 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
6872 levels[i], nt_errstr(r.out.result));
6873 ret = false;
6875 switch (r.in.level) {
6876 case 1:
6877 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6878 ret = false;
6880 r.in.start_idx += r.out.info->info1.count;
6881 break;
6882 case 2:
6883 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6884 ret = false;
6886 r.in.start_idx += r.out.info->info2.count;
6887 break;
6888 case 3:
6889 r.in.start_idx += r.out.info->info3.count;
6890 break;
6891 case 4:
6892 r.in.start_idx += r.out.info->info4.count;
6893 break;
6894 case 5:
6895 r.in.start_idx += r.out.info->info5.count;
6896 break;
6899 dom_info.in.domain_handle = handle;
6900 dom_info.in.level = 2;
6901 dom_info.out.info = &info;
6903 /* Check number of users returned is correct */
6904 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6905 "QueryDomainInfo failed");
6906 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6907 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6908 r.in.level, nt_errstr(dom_info.out.result));
6909 ret = false;
6910 break;
6912 switch (r.in.level) {
6913 case 1:
6914 case 4:
6915 if (info->general.num_users < r.in.start_idx) {
6916 /* On AD deployments this numbers don't match
6917 * since QueryDisplayInfo returns universal and
6918 * global groups, QueryDomainInfo only global
6919 * ones. */
6920 if (torture_setting_bool(tctx, "samba3", false)) {
6921 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6922 r.in.start_idx, info->general.num_groups,
6923 info->general.domain_name.string);
6924 ret = false;
6927 if (!seen_testuser) {
6928 struct policy_handle user_handle;
6929 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6930 torture_result(tctx, TORTURE_FAIL, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6931 info->general.domain_name.string);
6932 ret = false;
6933 test_samr_handle_Close(b, tctx, &user_handle);
6936 break;
6937 case 3:
6938 case 5:
6939 if (info->general.num_groups != r.in.start_idx) {
6940 /* On AD deployments this numbers don't match
6941 * since QueryDisplayInfo returns universal and
6942 * global groups, QueryDomainInfo only global
6943 * ones. */
6944 if (torture_setting_bool(tctx, "samba3", false)) {
6945 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6946 r.in.start_idx, info->general.num_groups,
6947 info->general.domain_name.string);
6948 ret = false;
6952 break;
6957 return ret;
6960 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6961 struct torture_context *tctx,
6962 struct policy_handle *handle)
6964 struct samr_QueryDisplayInfo2 r;
6965 bool ret = true;
6966 uint16_t levels[] = {1, 2, 3, 4, 5};
6967 int i;
6968 uint32_t total_size;
6969 uint32_t returned_size;
6970 union samr_DispInfo info;
6972 for (i=0;i<ARRAY_SIZE(levels);i++) {
6973 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6975 r.in.domain_handle = handle;
6976 r.in.level = levels[i];
6977 r.in.start_idx = 0;
6978 r.in.max_entries = 1000;
6979 r.in.buf_size = (uint32_t)-1;
6980 r.out.total_size = &total_size;
6981 r.out.returned_size = &returned_size;
6982 r.out.info = &info;
6984 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6985 "QueryDisplayInfo2 failed");
6986 if (!NT_STATUS_IS_OK(r.out.result)) {
6987 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo2 level %u failed - %s\n",
6988 levels[i], nt_errstr(r.out.result));
6989 ret = false;
6993 return ret;
6996 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6997 struct torture_context *tctx,
6998 struct policy_handle *handle)
7000 struct samr_QueryDisplayInfo3 r;
7001 bool ret = true;
7002 uint16_t levels[] = {1, 2, 3, 4, 5};
7003 int i;
7004 uint32_t total_size;
7005 uint32_t returned_size;
7006 union samr_DispInfo info;
7008 for (i=0;i<ARRAY_SIZE(levels);i++) {
7009 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
7011 r.in.domain_handle = handle;
7012 r.in.level = levels[i];
7013 r.in.start_idx = 0;
7014 r.in.max_entries = 1000;
7015 r.in.buf_size = (uint32_t)-1;
7016 r.out.total_size = &total_size;
7017 r.out.returned_size = &returned_size;
7018 r.out.info = &info;
7020 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
7021 "QueryDisplayInfo3 failed");
7022 if (!NT_STATUS_IS_OK(r.out.result)) {
7023 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo3 level %u failed - %s\n",
7024 levels[i], nt_errstr(r.out.result));
7025 ret = false;
7029 return ret;
7033 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
7034 struct torture_context *tctx,
7035 struct policy_handle *handle)
7037 struct samr_QueryDisplayInfo r;
7038 bool ret = true;
7039 uint32_t total_size;
7040 uint32_t returned_size;
7041 union samr_DispInfo info;
7043 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
7045 r.in.domain_handle = handle;
7046 r.in.level = 1;
7047 r.in.start_idx = 0;
7048 r.in.max_entries = 1;
7049 r.in.buf_size = (uint32_t)-1;
7050 r.out.total_size = &total_size;
7051 r.out.returned_size = &returned_size;
7052 r.out.info = &info;
7054 do {
7055 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7056 "QueryDisplayInfo failed");
7057 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
7058 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
7059 torture_result(tctx, TORTURE_FAIL, "expected idx %d but got %d\n",
7060 r.in.start_idx + 1,
7061 r.out.info->info1.entries[0].idx);
7062 break;
7065 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
7066 !NT_STATUS_IS_OK(r.out.result)) {
7067 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
7068 r.in.level, nt_errstr(r.out.result));
7069 ret = false;
7070 break;
7072 r.in.start_idx++;
7073 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
7074 NT_STATUS_IS_OK(r.out.result)) &&
7075 *r.out.returned_size != 0);
7077 return ret;
7080 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
7081 struct torture_context *tctx,
7082 struct policy_handle *handle)
7084 struct samr_QueryDomainInfo r;
7085 union samr_DomainInfo *info = NULL;
7086 struct samr_SetDomainInfo s;
7087 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
7088 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
7089 int i;
7090 bool ret = true;
7091 struct dcerpc_binding_handle *b = p->binding_handle;
7092 const char *domain_comment = talloc_asprintf(tctx,
7093 "Tortured by Samba4 RPC-SAMR: %s",
7094 timestring(tctx, time(NULL)));
7096 s.in.domain_handle = handle;
7097 s.in.level = 4;
7098 s.in.info = talloc(tctx, union samr_DomainInfo);
7100 s.in.info->oem.oem_information.string = domain_comment;
7101 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
7102 "SetDomainInfo failed");
7103 if (!NT_STATUS_IS_OK(s.out.result)) {
7104 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u (set comment) failed - %s\n",
7105 s.in.level, nt_errstr(s.out.result));
7106 return false;
7109 for (i=0;i<ARRAY_SIZE(levels);i++) {
7110 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
7112 r.in.domain_handle = handle;
7113 r.in.level = levels[i];
7114 r.out.info = &info;
7116 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
7117 "QueryDomainInfo failed");
7118 if (!NT_STATUS_IS_OK(r.out.result)) {
7119 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7120 r.in.level, nt_errstr(r.out.result));
7121 ret = false;
7122 continue;
7125 switch (levels[i]) {
7126 case 2:
7127 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
7128 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
7129 levels[i], info->general.oem_information.string, domain_comment);
7130 if (!torture_setting_bool(tctx, "samba3", false)) {
7131 ret = false;
7134 if (!info->general.primary.string) {
7135 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
7136 levels[i]);
7137 ret = false;
7138 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
7139 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
7140 if (torture_setting_bool(tctx, "samba3", false)) {
7141 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
7142 levels[i], info->general.primary.string, dcerpc_server_name(p));
7146 break;
7147 case 4:
7148 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
7149 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
7150 levels[i], info->oem.oem_information.string, domain_comment);
7151 if (!torture_setting_bool(tctx, "samba3", false)) {
7152 ret = false;
7155 break;
7156 case 6:
7157 if (!info->info6.primary.string) {
7158 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
7159 levels[i]);
7160 ret = false;
7162 break;
7163 case 11:
7164 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
7165 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
7166 levels[i], info->general2.general.oem_information.string, domain_comment);
7167 if (!torture_setting_bool(tctx, "samba3", false)) {
7168 ret = false;
7171 break;
7174 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
7176 s.in.domain_handle = handle;
7177 s.in.level = levels[i];
7178 s.in.info = info;
7180 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
7181 "SetDomainInfo failed");
7182 if (set_ok[i]) {
7183 if (!NT_STATUS_IS_OK(s.out.result)) {
7184 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u failed - %s\n",
7185 r.in.level, nt_errstr(s.out.result));
7186 ret = false;
7187 continue;
7189 } else {
7190 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
7191 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
7192 r.in.level, nt_errstr(s.out.result));
7193 ret = false;
7194 continue;
7198 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
7199 "QueryDomainInfo failed");
7200 if (!NT_STATUS_IS_OK(r.out.result)) {
7201 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7202 r.in.level, nt_errstr(r.out.result));
7203 ret = false;
7204 continue;
7208 return ret;
7212 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
7213 struct torture_context *tctx,
7214 struct policy_handle *handle)
7216 struct samr_QueryDomainInfo2 r;
7217 union samr_DomainInfo *info = NULL;
7218 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
7219 int i;
7220 bool ret = true;
7222 for (i=0;i<ARRAY_SIZE(levels);i++) {
7223 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
7225 r.in.domain_handle = handle;
7226 r.in.level = levels[i];
7227 r.out.info = &info;
7229 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7230 "QueryDomainInfo2 failed");
7231 if (!NT_STATUS_IS_OK(r.out.result)) {
7232 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo2 level %u failed - %s\n",
7233 r.in.level, nt_errstr(r.out.result));
7234 ret = false;
7235 continue;
7239 return ret;
7242 /* Test whether querydispinfo level 5 and enumdomgroups return the same
7243 set of group names. */
7244 static bool test_GroupList(struct dcerpc_binding_handle *b,
7245 struct torture_context *tctx,
7246 struct dom_sid *domain_sid,
7247 struct policy_handle *handle)
7249 struct samr_EnumDomainGroups q1;
7250 struct samr_QueryDisplayInfo q2;
7251 NTSTATUS status;
7252 uint32_t resume_handle=0;
7253 struct samr_SamArray *sam = NULL;
7254 uint32_t num_entries = 0;
7255 int i;
7256 bool ret = true;
7257 uint32_t total_size;
7258 uint32_t returned_size;
7259 union samr_DispInfo info;
7261 size_t num_names = 0;
7262 const char **names = NULL;
7264 bool builtin_domain = dom_sid_compare(domain_sid,
7265 &global_sid_Builtin) == 0;
7267 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
7269 q1.in.domain_handle = handle;
7270 q1.in.resume_handle = &resume_handle;
7271 q1.in.max_size = 5;
7272 q1.out.resume_handle = &resume_handle;
7273 q1.out.num_entries = &num_entries;
7274 q1.out.sam = &sam;
7276 status = STATUS_MORE_ENTRIES;
7277 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7278 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
7279 "EnumDomainGroups failed");
7280 status = q1.out.result;
7282 if (!NT_STATUS_IS_OK(status) &&
7283 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7284 break;
7286 for (i=0; i<*q1.out.num_entries; i++) {
7287 add_string_to_array(tctx,
7288 sam->entries[i].name.string,
7289 &names, &num_names);
7293 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
7295 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
7297 if (builtin_domain) {
7298 torture_assert(tctx, num_names == 0,
7299 "EnumDomainGroups shouldn't return any group in the builtin domain!");
7302 q2.in.domain_handle = handle;
7303 q2.in.level = 5;
7304 q2.in.start_idx = 0;
7305 q2.in.max_entries = 5;
7306 q2.in.buf_size = (uint32_t)-1;
7307 q2.out.total_size = &total_size;
7308 q2.out.returned_size = &returned_size;
7309 q2.out.info = &info;
7311 status = STATUS_MORE_ENTRIES;
7312 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7313 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
7314 "QueryDisplayInfo failed");
7315 status = q2.out.result;
7316 if (!NT_STATUS_IS_OK(status) &&
7317 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7318 break;
7320 for (i=0; i<q2.out.info->info5.count; i++) {
7321 int j;
7322 const char *name = q2.out.info->info5.entries[i].account_name.string;
7323 bool found = false;
7324 for (j=0; j<num_names; j++) {
7325 if (names[j] == NULL)
7326 continue;
7327 if (strequal(names[j], name)) {
7328 names[j] = NULL;
7329 found = true;
7330 break;
7334 if ((!found) && (!builtin_domain)) {
7335 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7336 name);
7337 ret = false;
7340 q2.in.start_idx += q2.out.info->info5.count;
7343 if (!NT_STATUS_IS_OK(status)) {
7344 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level 5 failed - %s\n",
7345 nt_errstr(status));
7346 ret = false;
7349 if (builtin_domain) {
7350 torture_assert(tctx, q2.in.start_idx != 0,
7351 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
7354 for (i=0; i<num_names; i++) {
7355 if (names[i] != NULL) {
7356 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
7357 names[i]);
7358 ret = false;
7362 return ret;
7365 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
7366 struct torture_context *tctx,
7367 struct policy_handle *group_handle)
7369 struct samr_DeleteDomainGroup d;
7371 torture_comment(tctx, "Testing DeleteDomainGroup\n");
7373 d.in.group_handle = group_handle;
7374 d.out.group_handle = group_handle;
7376 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
7377 "DeleteDomainGroup failed");
7378 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
7380 return true;
7383 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
7384 struct torture_context *tctx,
7385 struct policy_handle *domain_handle)
7387 struct samr_TestPrivateFunctionsDomain r;
7388 bool ret = true;
7390 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
7392 r.in.domain_handle = domain_handle;
7394 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
7395 "TestPrivateFunctionsDomain failed");
7396 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
7398 return ret;
7401 static bool test_RidToSid(struct dcerpc_binding_handle *b,
7402 struct torture_context *tctx,
7403 struct dom_sid *domain_sid,
7404 struct policy_handle *domain_handle)
7406 struct samr_RidToSid r;
7407 bool ret = true;
7408 struct dom_sid *calc_sid, *out_sid;
7409 int rids[] = { 0, 42, 512, 10200 };
7410 int i;
7412 for (i=0;i<ARRAY_SIZE(rids);i++) {
7413 torture_comment(tctx, "Testing RidToSid\n");
7415 calc_sid = dom_sid_dup(tctx, domain_sid);
7416 r.in.domain_handle = domain_handle;
7417 r.in.rid = rids[i];
7418 r.out.sid = &out_sid;
7420 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
7421 "RidToSid failed");
7422 if (!NT_STATUS_IS_OK(r.out.result)) {
7423 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
7424 ret = false;
7425 } else {
7426 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
7428 if (!dom_sid_equal(calc_sid, out_sid)) {
7429 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
7430 dom_sid_string(tctx, out_sid),
7431 dom_sid_string(tctx, calc_sid));
7432 ret = false;
7437 return ret;
7440 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7441 struct torture_context *tctx,
7442 struct policy_handle *domain_handle)
7444 struct samr_GetBootKeyInformation r;
7445 bool ret = true;
7446 uint32_t unknown = 0;
7447 NTSTATUS status;
7449 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7451 r.in.domain_handle = domain_handle;
7452 r.out.unknown = &unknown;
7454 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7455 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7456 status = r.out.result;
7458 if (!NT_STATUS_IS_OK(status)) {
7459 /* w2k3 seems to fail this sometimes and pass it sometimes */
7460 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7463 return ret;
7466 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7467 struct torture_context *tctx,
7468 struct policy_handle *domain_handle,
7469 struct policy_handle *group_handle)
7471 NTSTATUS status;
7472 struct samr_AddGroupMember r;
7473 struct samr_DeleteGroupMember d;
7474 struct samr_QueryGroupMember q;
7475 struct samr_RidAttrArray *rids = NULL;
7476 struct samr_SetMemberAttributesOfGroup s;
7477 uint32_t rid;
7478 bool found_member = false;
7479 int i;
7481 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7482 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7484 r.in.group_handle = group_handle;
7485 r.in.rid = rid;
7486 r.in.flags = 0; /* ??? */
7488 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7490 d.in.group_handle = group_handle;
7491 d.in.rid = rid;
7493 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7494 "DeleteGroupMember failed");
7495 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7497 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7498 "AddGroupMember failed");
7499 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7501 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7502 "AddGroupMember failed");
7503 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7505 if (torture_setting_bool(tctx, "samba4", false) ||
7506 torture_setting_bool(tctx, "samba3", false)) {
7507 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7508 } else {
7509 /* this one is quite strange. I am using random inputs in the
7510 hope of triggering an error that might give us a clue */
7512 s.in.group_handle = group_handle;
7513 s.in.unknown1 = random();
7514 s.in.unknown2 = random();
7516 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7517 "SetMemberAttributesOfGroup failed");
7518 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7521 q.in.group_handle = group_handle;
7522 q.out.rids = &rids;
7524 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7525 "QueryGroupMember failed");
7526 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7527 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7529 for (i=0; i < rids->count; i++) {
7530 if (rids->rids[i] == rid) {
7531 found_member = true;
7535 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7537 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7538 "DeleteGroupMember failed");
7539 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7541 rids = NULL;
7542 found_member = false;
7544 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7545 "QueryGroupMember failed");
7546 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7547 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7549 for (i=0; i < rids->count; i++) {
7550 if (rids->rids[i] == rid) {
7551 found_member = true;
7555 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7557 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7558 "AddGroupMember failed");
7559 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7561 return true;
7565 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7566 struct torture_context *tctx,
7567 struct policy_handle *domain_handle,
7568 const char *group_name,
7569 struct policy_handle *group_handle,
7570 struct dom_sid *domain_sid,
7571 bool test_group)
7573 struct samr_CreateDomainGroup r;
7574 uint32_t rid;
7575 struct lsa_String name;
7576 bool ret = true;
7578 init_lsa_String(&name, group_name);
7580 r.in.domain_handle = domain_handle;
7581 r.in.name = &name;
7582 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7583 r.out.group_handle = group_handle;
7584 r.out.rid = &rid;
7586 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7588 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7589 "CreateDomainGroup failed");
7591 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7592 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7593 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7594 return true;
7595 } else {
7596 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7597 nt_errstr(r.out.result));
7598 return false;
7602 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7603 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7604 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7605 nt_errstr(r.out.result));
7606 return false;
7608 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7609 "CreateDomainGroup failed");
7611 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7612 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7614 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7615 nt_errstr(r.out.result));
7616 return false;
7618 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7619 "CreateDomainGroup failed");
7621 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7623 if (!test_group) {
7624 return ret;
7627 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7628 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7629 ret = false;
7632 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7633 ret = false;
7636 return ret;
7641 its not totally clear what this does. It seems to accept any sid you like.
7643 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7644 struct torture_context *tctx,
7645 struct policy_handle *domain_handle)
7647 struct samr_RemoveMemberFromForeignDomain r;
7649 r.in.domain_handle = domain_handle;
7650 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7652 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7653 "RemoveMemberFromForeignDomain failed");
7654 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7656 return true;
7659 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7660 struct torture_context *tctx,
7661 struct policy_handle *domain_handle,
7662 uint32_t *total_num_entries_p)
7664 NTSTATUS status;
7665 struct samr_EnumDomainUsers r;
7666 uint32_t resume_handle = 0;
7667 uint32_t num_entries = 0;
7668 uint32_t total_num_entries = 0;
7669 struct samr_SamArray *sam;
7671 r.in.domain_handle = domain_handle;
7672 r.in.acct_flags = 0;
7673 r.in.max_size = (uint32_t)-1;
7674 r.in.resume_handle = &resume_handle;
7676 r.out.sam = &sam;
7677 r.out.num_entries = &num_entries;
7678 r.out.resume_handle = &resume_handle;
7680 torture_comment(tctx, "Testing EnumDomainUsers\n");
7682 do {
7683 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7684 "EnumDomainUsers failed");
7685 if (NT_STATUS_IS_ERR(r.out.result)) {
7686 torture_assert_ntstatus_ok(tctx, r.out.result,
7687 "failed to enumerate users");
7689 status = r.out.result;
7691 total_num_entries += num_entries;
7692 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7694 if (total_num_entries_p) {
7695 *total_num_entries_p = total_num_entries;
7698 return true;
7701 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7702 struct torture_context *tctx,
7703 struct policy_handle *domain_handle,
7704 uint32_t *total_num_entries_p)
7706 NTSTATUS status;
7707 struct samr_EnumDomainGroups r;
7708 uint32_t resume_handle = 0;
7709 uint32_t num_entries = 0;
7710 uint32_t total_num_entries = 0;
7711 struct samr_SamArray *sam;
7713 r.in.domain_handle = domain_handle;
7714 r.in.max_size = (uint32_t)-1;
7715 r.in.resume_handle = &resume_handle;
7717 r.out.sam = &sam;
7718 r.out.num_entries = &num_entries;
7719 r.out.resume_handle = &resume_handle;
7721 torture_comment(tctx, "Testing EnumDomainGroups\n");
7723 do {
7724 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7725 "EnumDomainGroups failed");
7726 if (NT_STATUS_IS_ERR(r.out.result)) {
7727 torture_assert_ntstatus_ok(tctx, r.out.result,
7728 "failed to enumerate groups");
7730 status = r.out.result;
7732 total_num_entries += num_entries;
7733 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7735 if (total_num_entries_p) {
7736 *total_num_entries_p = total_num_entries;
7739 return true;
7742 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7743 struct torture_context *tctx,
7744 struct policy_handle *domain_handle,
7745 uint32_t *total_num_entries_p)
7747 NTSTATUS status;
7748 struct samr_EnumDomainAliases r;
7749 uint32_t resume_handle = 0;
7750 uint32_t num_entries = 0;
7751 uint32_t total_num_entries = 0;
7752 struct samr_SamArray *sam;
7754 r.in.domain_handle = domain_handle;
7755 r.in.max_size = (uint32_t)-1;
7756 r.in.resume_handle = &resume_handle;
7758 r.out.sam = &sam;
7759 r.out.num_entries = &num_entries;
7760 r.out.resume_handle = &resume_handle;
7762 torture_comment(tctx, "Testing EnumDomainAliases\n");
7764 do {
7765 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7766 "EnumDomainAliases failed");
7767 if (NT_STATUS_IS_ERR(r.out.result)) {
7768 torture_assert_ntstatus_ok(tctx, r.out.result,
7769 "failed to enumerate aliases");
7771 status = r.out.result;
7773 total_num_entries += num_entries;
7774 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7776 if (total_num_entries_p) {
7777 *total_num_entries_p = total_num_entries;
7780 return true;
7783 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7784 struct torture_context *tctx,
7785 struct policy_handle *handle,
7786 uint16_t level,
7787 uint32_t *total_num_entries_p)
7789 NTSTATUS status;
7790 struct samr_QueryDisplayInfo r;
7791 uint32_t total_num_entries = 0;
7793 r.in.domain_handle = handle;
7794 r.in.level = level;
7795 r.in.start_idx = 0;
7796 r.in.max_entries = (uint32_t)-1;
7797 r.in.buf_size = (uint32_t)-1;
7799 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7801 do {
7802 uint32_t total_size;
7803 uint32_t returned_size;
7804 union samr_DispInfo info;
7806 r.out.total_size = &total_size;
7807 r.out.returned_size = &returned_size;
7808 r.out.info = &info;
7810 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7811 "failed to query displayinfo");
7812 if (NT_STATUS_IS_ERR(r.out.result)) {
7813 torture_assert_ntstatus_ok(tctx, r.out.result,
7814 "failed to query displayinfo");
7816 status = r.out.result;
7818 if (*r.out.returned_size == 0) {
7819 break;
7822 switch (r.in.level) {
7823 case 1:
7824 total_num_entries += info.info1.count;
7825 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7826 break;
7827 case 2:
7828 total_num_entries += info.info2.count;
7829 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7830 break;
7831 case 3:
7832 total_num_entries += info.info3.count;
7833 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7834 break;
7835 case 4:
7836 total_num_entries += info.info4.count;
7837 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7838 break;
7839 case 5:
7840 total_num_entries += info.info5.count;
7841 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7842 break;
7843 default:
7844 return false;
7847 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7849 if (total_num_entries_p) {
7850 *total_num_entries_p = total_num_entries;
7853 return true;
7856 static bool test_ManyObjects(struct dcerpc_pipe *p,
7857 struct torture_context *tctx,
7858 struct policy_handle *domain_handle,
7859 struct dom_sid *domain_sid,
7860 struct torture_samr_context *ctx)
7862 uint32_t num_total = ctx->num_objects_large_dc;
7863 uint32_t num_enum = 0;
7864 uint32_t num_disp = 0;
7865 uint32_t num_created = 0;
7866 uint32_t num_anounced = 0;
7867 uint32_t i;
7868 struct dcerpc_binding_handle *b = p->binding_handle;
7870 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7872 /* query */
7875 struct samr_QueryDomainInfo2 r;
7876 union samr_DomainInfo *info;
7877 r.in.domain_handle = domain_handle;
7878 r.in.level = 2;
7879 r.out.info = &info;
7881 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7882 "QueryDomainInfo2 failed");
7883 torture_assert_ntstatus_ok(tctx, r.out.result,
7884 "failed to query domain info");
7886 switch (ctx->choice) {
7887 case TORTURE_SAMR_MANY_ACCOUNTS:
7888 num_anounced = info->general.num_users;
7889 break;
7890 case TORTURE_SAMR_MANY_GROUPS:
7891 num_anounced = info->general.num_groups;
7892 break;
7893 case TORTURE_SAMR_MANY_ALIASES:
7894 num_anounced = info->general.num_aliases;
7895 break;
7896 default:
7897 return false;
7901 /* create */
7903 for (i=0; i < num_total; i++) {
7905 const char *name = NULL;
7907 switch (ctx->choice) {
7908 case TORTURE_SAMR_MANY_ACCOUNTS:
7909 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7910 torture_assert(tctx,
7911 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7912 "failed to create user");
7913 break;
7914 case TORTURE_SAMR_MANY_GROUPS:
7915 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7916 torture_assert(tctx,
7917 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7918 "failed to create group");
7919 break;
7920 case TORTURE_SAMR_MANY_ALIASES:
7921 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7922 torture_assert(tctx,
7923 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7924 "failed to create alias");
7925 break;
7926 default:
7927 return false;
7929 if (!ndr_policy_handle_empty(&handles[i])) {
7930 num_created++;
7934 /* enum */
7936 switch (ctx->choice) {
7937 case TORTURE_SAMR_MANY_ACCOUNTS:
7938 torture_assert(tctx,
7939 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7940 "failed to enum users");
7941 break;
7942 case TORTURE_SAMR_MANY_GROUPS:
7943 torture_assert(tctx,
7944 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7945 "failed to enum groups");
7946 break;
7947 case TORTURE_SAMR_MANY_ALIASES:
7948 torture_assert(tctx,
7949 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7950 "failed to enum aliases");
7951 break;
7952 default:
7953 return false;
7956 /* dispinfo */
7958 switch (ctx->choice) {
7959 case TORTURE_SAMR_MANY_ACCOUNTS:
7960 torture_assert(tctx,
7961 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
7962 "failed to query display info");
7963 break;
7964 case TORTURE_SAMR_MANY_GROUPS:
7965 torture_assert(tctx,
7966 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
7967 "failed to query display info");
7968 break;
7969 case TORTURE_SAMR_MANY_ALIASES:
7970 /* no aliases in dispinfo */
7971 break;
7972 default:
7973 return false;
7976 /* close or delete */
7978 for (i=0; i < num_total; i++) {
7980 if (ndr_policy_handle_empty(&handles[i])) {
7981 continue;
7984 if (torture_setting_bool(tctx, "samba3", false)) {
7985 torture_assert(tctx,
7986 test_samr_handle_Close(b, tctx, &handles[i]),
7987 "failed to close handle");
7988 } else {
7989 switch (ctx->choice) {
7990 case TORTURE_SAMR_MANY_ACCOUNTS:
7991 torture_assert(tctx,
7992 test_DeleteUser(b, tctx, &handles[i]),
7993 "failed to delete user");
7994 break;
7995 case TORTURE_SAMR_MANY_GROUPS:
7996 torture_assert(tctx,
7997 test_DeleteDomainGroup(b, tctx, &handles[i]),
7998 "failed to delete group");
7999 break;
8000 case TORTURE_SAMR_MANY_ALIASES:
8001 torture_assert(tctx,
8002 test_DeleteAlias(b, tctx, &handles[i]),
8003 "failed to delete alias");
8004 break;
8005 default:
8006 return false;
8011 talloc_free(handles);
8013 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
8014 torture_comment(tctx,
8015 "unexpected number of results (%u) returned in enum call, expected %u\n",
8016 num_enum, num_anounced + num_created);
8018 torture_comment(tctx,
8019 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
8020 num_disp, num_anounced + num_created);
8023 return true;
8026 static bool test_Connect(struct dcerpc_binding_handle *b,
8027 struct torture_context *tctx,
8028 struct policy_handle *handle);
8030 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
8031 struct torture_samr_context *ctx, struct dom_sid *sid)
8033 struct samr_OpenDomain r;
8034 struct policy_handle domain_handle;
8035 struct policy_handle alias_handle;
8036 struct policy_handle user_handle;
8037 struct policy_handle group_handle;
8038 bool ret = true;
8039 struct dcerpc_binding_handle *b = p->binding_handle;
8041 ZERO_STRUCT(alias_handle);
8042 ZERO_STRUCT(user_handle);
8043 ZERO_STRUCT(group_handle);
8044 ZERO_STRUCT(domain_handle);
8046 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
8048 r.in.connect_handle = &ctx->handle;
8049 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8050 r.in.sid = sid;
8051 r.out.domain_handle = &domain_handle;
8053 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
8054 "OpenDomain failed");
8055 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
8057 /* run the domain tests with the main handle closed - this tests
8058 the servers reference counting */
8059 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
8061 switch (ctx->choice) {
8062 case TORTURE_SAMR_PASSWORDS:
8063 case TORTURE_SAMR_USER_PRIVILEGES:
8064 if (!torture_setting_bool(tctx, "samba3", false)) {
8065 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
8067 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8068 if (!ret) {
8069 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
8071 break;
8072 case TORTURE_SAMR_USER_ATTRIBUTES:
8073 if (!torture_setting_bool(tctx, "samba3", false)) {
8074 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
8076 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8077 /* This test needs 'complex' users to validate */
8078 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
8079 if (!ret) {
8080 torture_result(tctx, TORTURE_FAIL, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
8082 break;
8083 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
8084 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
8085 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
8086 if (!torture_setting_bool(tctx, "samba3", false)) {
8087 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
8089 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
8090 if (!ret) {
8091 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
8093 break;
8094 case TORTURE_SAMR_MANY_ACCOUNTS:
8095 case TORTURE_SAMR_MANY_GROUPS:
8096 case TORTURE_SAMR_MANY_ALIASES:
8097 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
8098 if (!ret) {
8099 torture_result(tctx, TORTURE_FAIL, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
8101 break;
8102 case TORTURE_SAMR_OTHER:
8103 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8104 if (!ret) {
8105 torture_result(tctx, TORTURE_FAIL, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
8107 if (!torture_setting_bool(tctx, "samba3", false)) {
8108 ret &= test_QuerySecurity(b, tctx, &domain_handle);
8110 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
8111 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
8112 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
8113 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
8114 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
8115 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
8116 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
8117 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
8118 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
8119 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
8120 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
8121 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
8122 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
8124 if (torture_setting_bool(tctx, "samba4", false)) {
8125 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
8126 } else {
8127 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
8128 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
8130 ret &= test_GroupList(b, tctx, sid, &domain_handle);
8131 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
8132 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
8133 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
8134 if (!ret) {
8135 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
8137 break;
8140 if (!ndr_policy_handle_empty(&user_handle) &&
8141 !test_DeleteUser(b, tctx, &user_handle)) {
8142 ret = false;
8145 if (!ndr_policy_handle_empty(&alias_handle) &&
8146 !test_DeleteAlias(b, tctx, &alias_handle)) {
8147 ret = false;
8150 if (!ndr_policy_handle_empty(&group_handle) &&
8151 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
8152 ret = false;
8155 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
8157 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
8158 /* reconnect the main handle */
8160 if (!ret) {
8161 torture_result(tctx, TORTURE_FAIL, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
8164 return ret;
8167 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
8168 struct torture_samr_context *ctx, const char *domain)
8170 struct samr_LookupDomain r;
8171 struct dom_sid2 *sid = NULL;
8172 struct lsa_String n1;
8173 struct lsa_String n2;
8174 bool ret = true;
8175 struct dcerpc_binding_handle *b = p->binding_handle;
8177 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
8179 /* check for correct error codes */
8180 r.in.connect_handle = &ctx->handle;
8181 r.in.domain_name = &n2;
8182 r.out.sid = &sid;
8183 n2.string = NULL;
8185 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8186 "LookupDomain failed");
8187 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
8189 init_lsa_String(&n2, "xxNODOMAINxx");
8191 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8192 "LookupDomain failed");
8193 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
8195 r.in.connect_handle = &ctx->handle;
8197 init_lsa_String(&n1, domain);
8198 r.in.domain_name = &n1;
8200 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8201 "LookupDomain failed");
8202 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
8204 if (!test_GetDomPwInfo(p, tctx, &n1)) {
8205 ret = false;
8208 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
8209 ret = false;
8212 return ret;
8216 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
8217 struct torture_samr_context *ctx)
8219 struct samr_EnumDomains r;
8220 uint32_t resume_handle = 0;
8221 uint32_t num_entries = 0;
8222 struct samr_SamArray *sam = NULL;
8223 int i;
8224 bool ret = true;
8225 struct dcerpc_binding_handle *b = p->binding_handle;
8227 r.in.connect_handle = &ctx->handle;
8228 r.in.resume_handle = &resume_handle;
8229 r.in.buf_size = (uint32_t)-1;
8230 r.out.resume_handle = &resume_handle;
8231 r.out.num_entries = &num_entries;
8232 r.out.sam = &sam;
8234 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
8235 "EnumDomains failed");
8236 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
8238 if (!*r.out.sam) {
8239 return false;
8242 for (i=0;i<sam->count;i++) {
8243 if (!test_LookupDomain(p, tctx, ctx,
8244 sam->entries[i].name.string)) {
8245 ret = false;
8249 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
8250 "EnumDomains failed");
8251 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
8253 return ret;
8257 static bool test_Connect(struct dcerpc_binding_handle *b,
8258 struct torture_context *tctx,
8259 struct policy_handle *handle)
8261 struct samr_Connect r;
8262 struct samr_Connect2 r2;
8263 struct samr_Connect3 r3;
8264 struct samr_Connect4 r4;
8265 struct samr_Connect5 r5;
8266 union samr_ConnectInfo info;
8267 struct policy_handle h;
8268 uint32_t level_out = 0;
8269 bool ret = true, got_handle = false;
8271 torture_comment(tctx, "Testing samr_Connect\n");
8273 r.in.system_name = NULL;
8274 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8275 r.out.connect_handle = &h;
8277 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
8278 "Connect failed");
8279 if (!NT_STATUS_IS_OK(r.out.result)) {
8280 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
8281 ret = false;
8282 } else {
8283 got_handle = true;
8284 *handle = h;
8287 torture_comment(tctx, "Testing samr_Connect2\n");
8289 r2.in.system_name = NULL;
8290 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8291 r2.out.connect_handle = &h;
8293 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
8294 "Connect2 failed");
8295 if (!NT_STATUS_IS_OK(r2.out.result)) {
8296 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
8297 ret = false;
8298 } else {
8299 if (got_handle) {
8300 test_samr_handle_Close(b, tctx, handle);
8302 got_handle = true;
8303 *handle = h;
8306 torture_comment(tctx, "Testing samr_Connect3\n");
8308 r3.in.system_name = NULL;
8309 r3.in.unknown = 0;
8310 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8311 r3.out.connect_handle = &h;
8313 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
8314 "Connect3 failed");
8315 if (!NT_STATUS_IS_OK(r3.out.result)) {
8316 torture_result(tctx, TORTURE_FAIL, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
8317 ret = false;
8318 } else {
8319 if (got_handle) {
8320 test_samr_handle_Close(b, tctx, handle);
8322 got_handle = true;
8323 *handle = h;
8326 torture_comment(tctx, "Testing samr_Connect4\n");
8328 r4.in.system_name = "";
8329 r4.in.client_version = 0;
8330 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8331 r4.out.connect_handle = &h;
8333 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8334 "Connect4 failed");
8335 if (!NT_STATUS_IS_OK(r4.out.result)) {
8336 torture_result(tctx, TORTURE_FAIL, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8337 ret = false;
8338 } else {
8339 if (got_handle) {
8340 test_samr_handle_Close(b, tctx, handle);
8342 got_handle = true;
8343 *handle = h;
8346 torture_comment(tctx, "Testing samr_Connect5\n");
8348 info.info1.client_version = 0;
8349 info.info1.unknown2 = 0;
8351 r5.in.system_name = "";
8352 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8353 r5.in.level_in = 1;
8354 r5.out.level_out = &level_out;
8355 r5.in.info_in = &info;
8356 r5.out.info_out = &info;
8357 r5.out.connect_handle = &h;
8359 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
8360 "Connect5 failed");
8361 if (!NT_STATUS_IS_OK(r5.out.result)) {
8362 torture_result(tctx, TORTURE_FAIL, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
8363 ret = false;
8364 } else {
8365 if (got_handle) {
8366 test_samr_handle_Close(b, tctx, handle);
8368 got_handle = true;
8369 *handle = h;
8372 return ret;
8376 static bool test_samr_ValidatePassword(struct torture_context *tctx,
8377 struct dcerpc_pipe *p)
8379 struct samr_ValidatePassword r;
8380 union samr_ValidatePasswordReq req;
8381 union samr_ValidatePasswordRep *repp = NULL;
8382 NTSTATUS status;
8383 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
8384 int i;
8385 struct dcerpc_binding_handle *b = p->binding_handle;
8387 torture_comment(tctx, "Testing samr_ValidatePassword\n");
8389 if (p->conn->transport.transport != NCACN_IP_TCP) {
8390 torture_comment(tctx, "samr_ValidatePassword only should succeed over NCACN_IP_TCP!\n");
8393 ZERO_STRUCT(r);
8394 r.in.level = NetValidatePasswordReset;
8395 r.in.req = &req;
8396 r.out.rep = &repp;
8398 ZERO_STRUCT(req);
8399 req.req3.account.string = "non-existent-account-aklsdji";
8401 for (i=0; passwords[i]; i++) {
8402 req.req3.password.string = passwords[i];
8404 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
8405 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
8406 torture_skip(tctx, "ValidatePassword not supported by server\n");
8408 torture_assert_ntstatus_ok(tctx, status,
8409 "samr_ValidatePassword failed");
8410 torture_assert_ntstatus_ok(tctx, r.out.result,
8411 "samr_ValidatePassword failed");
8412 torture_comment(tctx, "Server %s password '%s' with code %i\n",
8413 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
8414 req.req3.password.string, repp->ctr3.status);
8417 return true;
8420 bool torture_rpc_samr(struct torture_context *torture)
8422 NTSTATUS status;
8423 struct dcerpc_pipe *p;
8424 bool ret = true;
8425 struct torture_samr_context *ctx;
8426 struct dcerpc_binding_handle *b;
8428 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8429 if (!NT_STATUS_IS_OK(status)) {
8430 return false;
8432 b = p->binding_handle;
8434 ctx = talloc_zero(torture, struct torture_samr_context);
8436 ctx->choice = TORTURE_SAMR_OTHER;
8438 ret &= test_Connect(b, torture, &ctx->handle);
8440 if (!torture_setting_bool(torture, "samba3", false)) {
8441 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8444 ret &= test_EnumDomains(p, torture, ctx);
8446 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8448 ret &= test_Shutdown(b, torture, &ctx->handle);
8450 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8452 return ret;
8456 bool torture_rpc_samr_users(struct torture_context *torture)
8458 NTSTATUS status;
8459 struct dcerpc_pipe *p;
8460 bool ret = true;
8461 struct torture_samr_context *ctx;
8462 struct dcerpc_binding_handle *b;
8464 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8465 if (!NT_STATUS_IS_OK(status)) {
8466 return false;
8468 b = p->binding_handle;
8470 ctx = talloc_zero(torture, struct torture_samr_context);
8472 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8474 ret &= test_Connect(b, torture, &ctx->handle);
8476 if (!torture_setting_bool(torture, "samba3", false)) {
8477 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8480 ret &= test_EnumDomains(p, torture, ctx);
8482 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8484 ret &= test_Shutdown(b, torture, &ctx->handle);
8486 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8488 return ret;
8492 bool torture_rpc_samr_passwords(struct torture_context *torture)
8494 NTSTATUS status;
8495 struct dcerpc_pipe *p;
8496 bool ret = true;
8497 struct torture_samr_context *ctx;
8498 struct dcerpc_binding_handle *b;
8500 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8501 if (!NT_STATUS_IS_OK(status)) {
8502 return false;
8504 b = p->binding_handle;
8506 ctx = talloc_zero(torture, struct torture_samr_context);
8508 ctx->choice = TORTURE_SAMR_PASSWORDS;
8510 ret &= test_Connect(b, torture, &ctx->handle);
8512 ret &= test_EnumDomains(p, torture, ctx);
8514 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8516 return ret;
8519 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8520 struct dcerpc_pipe *p2,
8521 struct cli_credentials *machine_credentials)
8523 NTSTATUS status;
8524 struct dcerpc_pipe *p;
8525 bool ret = true;
8526 struct torture_samr_context *ctx;
8527 struct dcerpc_binding_handle *b;
8529 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8530 if (!NT_STATUS_IS_OK(status)) {
8531 return false;
8533 b = p->binding_handle;
8535 ctx = talloc_zero(torture, struct torture_samr_context);
8537 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8538 ctx->machine_credentials = machine_credentials;
8540 ret &= test_Connect(b, torture, &ctx->handle);
8542 ret &= test_EnumDomains(p, torture, ctx);
8544 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8546 return ret;
8549 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8551 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8552 struct torture_rpc_tcase *tcase;
8554 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8555 &ndr_table_samr,
8556 TEST_ACCOUNT_NAME_PWD);
8558 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8559 torture_rpc_samr_pwdlastset);
8561 return suite;
8564 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8565 struct dcerpc_pipe *p2,
8566 struct cli_credentials *machine_credentials)
8568 NTSTATUS status;
8569 struct dcerpc_pipe *p;
8570 bool ret = true;
8571 struct torture_samr_context *ctx;
8572 struct dcerpc_binding_handle *b;
8574 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8575 if (!NT_STATUS_IS_OK(status)) {
8576 return false;
8578 b = p->binding_handle;
8580 ctx = talloc_zero(torture, struct torture_samr_context);
8582 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8583 ctx->machine_credentials = machine_credentials;
8585 ret &= test_Connect(b, torture, &ctx->handle);
8587 ret &= test_EnumDomains(p, torture, ctx);
8589 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8591 return ret;
8594 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8596 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8597 struct torture_rpc_tcase *tcase;
8599 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8600 &ndr_table_samr,
8601 TEST_ACCOUNT_NAME_PWD);
8603 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8604 torture_rpc_samr_users_privileges_delete_user);
8606 return suite;
8609 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8610 struct dcerpc_pipe *p2,
8611 void *data)
8613 NTSTATUS status;
8614 struct dcerpc_pipe *p;
8615 bool ret = true;
8616 struct torture_samr_context *ctx =
8617 talloc_get_type_abort(data, struct torture_samr_context);
8618 struct dcerpc_binding_handle *b;
8620 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8621 if (!NT_STATUS_IS_OK(status)) {
8622 return false;
8624 b = p->binding_handle;
8626 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8627 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8628 ctx->num_objects_large_dc);
8630 ret &= test_Connect(b, torture, &ctx->handle);
8632 ret &= test_EnumDomains(p, torture, ctx);
8634 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8636 return ret;
8639 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8640 struct dcerpc_pipe *p2,
8641 void *data)
8643 NTSTATUS status;
8644 struct dcerpc_pipe *p;
8645 bool ret = true;
8646 struct torture_samr_context *ctx =
8647 talloc_get_type_abort(data, struct torture_samr_context);
8648 struct dcerpc_binding_handle *b;
8650 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8651 if (!NT_STATUS_IS_OK(status)) {
8652 return false;
8654 b = p->binding_handle;
8656 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8657 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8658 ctx->num_objects_large_dc);
8660 ret &= test_Connect(b, torture, &ctx->handle);
8662 ret &= test_EnumDomains(p, torture, ctx);
8664 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8666 return ret;
8669 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8670 struct dcerpc_pipe *p2,
8671 void *data)
8673 NTSTATUS status;
8674 struct dcerpc_pipe *p;
8675 bool ret = true;
8676 struct torture_samr_context *ctx =
8677 talloc_get_type_abort(data, struct torture_samr_context);
8678 struct dcerpc_binding_handle *b;
8680 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8681 if (!NT_STATUS_IS_OK(status)) {
8682 return false;
8684 b = p->binding_handle;
8686 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8687 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8688 ctx->num_objects_large_dc);
8690 ret &= test_Connect(b, torture, &ctx->handle);
8692 ret &= test_EnumDomains(p, torture, ctx);
8694 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8696 return ret;
8699 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8701 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8702 struct torture_rpc_tcase *tcase;
8703 struct torture_samr_context *ctx;
8705 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8707 ctx = talloc_zero(suite, struct torture_samr_context);
8708 ctx->num_objects_large_dc = 150;
8710 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8711 torture_rpc_samr_many_aliases, ctx);
8712 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8713 torture_rpc_samr_many_groups, ctx);
8714 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8715 torture_rpc_samr_many_accounts, ctx);
8717 return suite;
8720 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8721 struct dcerpc_pipe *p2,
8722 struct cli_credentials *machine_credentials)
8724 NTSTATUS status;
8725 struct dcerpc_pipe *p;
8726 bool ret = true;
8727 struct torture_samr_context *ctx;
8728 struct dcerpc_binding_handle *b;
8730 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8731 if (!NT_STATUS_IS_OK(status)) {
8732 return false;
8734 b = p->binding_handle;
8736 ctx = talloc_zero(torture, struct torture_samr_context);
8738 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8739 ctx->machine_credentials = machine_credentials;
8741 ret &= test_Connect(b, torture, &ctx->handle);
8743 ret &= test_EnumDomains(p, torture, ctx);
8745 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8747 return ret;
8750 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8752 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8753 struct torture_rpc_tcase *tcase;
8755 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8756 &ndr_table_samr,
8757 TEST_ACCOUNT_NAME_PWD);
8759 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8760 torture_rpc_samr_badpwdcount);
8762 return suite;
8765 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8766 struct dcerpc_pipe *p2,
8767 struct cli_credentials *machine_credentials)
8769 NTSTATUS status;
8770 struct dcerpc_pipe *p;
8771 bool ret = true;
8772 struct torture_samr_context *ctx;
8773 struct dcerpc_binding_handle *b;
8775 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8776 if (!NT_STATUS_IS_OK(status)) {
8777 return false;
8779 b = p->binding_handle;
8781 ctx = talloc_zero(torture, struct torture_samr_context);
8783 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8784 ctx->machine_credentials = machine_credentials;
8786 ret &= test_Connect(b, torture, &ctx->handle);
8788 ret &= test_EnumDomains(p, torture, ctx);
8790 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8792 return ret;
8795 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8797 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8798 struct torture_rpc_tcase *tcase;
8800 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8801 &ndr_table_samr,
8802 TEST_ACCOUNT_NAME_PWD);
8804 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8805 torture_rpc_samr_lockout);
8807 return suite;
8810 struct torture_suite *torture_rpc_samr_passwords_validate(TALLOC_CTX *mem_ctx)
8812 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.validate");
8813 struct torture_rpc_tcase *tcase;
8815 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
8816 &ndr_table_samr);
8817 torture_rpc_tcase_add_test(tcase, "validate",
8818 test_samr_ValidatePassword);
8820 return suite;