testprogs: Update the kpasswd setpassword test
[Samba.git] / source4 / torture / rpc / samr.c
blob92861f4c8aaaba4f17fa4e060619fe25a75db7c9
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"
42 #include "torture/util.h"
44 #define TEST_ACCOUNT_NAME "samrtorturetest"
45 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
46 #define TEST_ALIASNAME "samrtorturetestalias"
47 #define TEST_GROUPNAME "samrtorturetestgroup"
48 #define TEST_MACHINENAME "samrtestmach$"
49 #define TEST_DOMAINNAME "samrtestdom$"
51 enum torture_samr_choice {
52 TORTURE_SAMR_PASSWORDS,
53 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
54 TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
55 TORTURE_SAMR_PASSWORDS_LOCKOUT,
56 TORTURE_SAMR_USER_ATTRIBUTES,
57 TORTURE_SAMR_USER_PRIVILEGES,
58 TORTURE_SAMR_OTHER,
59 TORTURE_SAMR_MANY_ACCOUNTS,
60 TORTURE_SAMR_MANY_GROUPS,
61 TORTURE_SAMR_MANY_ALIASES
64 struct torture_samr_context {
65 struct policy_handle handle;
66 struct cli_credentials *machine_credentials;
67 enum torture_samr_choice choice;
68 uint32_t num_objects_large_dc;
71 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
72 struct torture_context *tctx,
73 struct policy_handle *handle);
75 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
76 struct torture_context *tctx,
77 struct policy_handle *handle);
79 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
80 struct torture_context *tctx,
81 struct policy_handle *handle);
83 static bool test_ChangePassword(struct dcerpc_pipe *p,
84 struct torture_context *tctx,
85 const char *acct_name,
86 struct policy_handle *domain_handle, char **password);
88 static void init_lsa_String(struct lsa_String *string, const char *s)
90 string->string = s;
93 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
95 string->string = s;
98 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
100 string->length = length;
101 string->size = length;
102 string->array = (uint16_t *)discard_const(s);
105 bool test_samr_handle_Close(struct dcerpc_binding_handle *b,
106 struct torture_context *tctx,
107 struct policy_handle *handle)
109 struct samr_Close r;
111 r.in.handle = handle;
112 r.out.handle = handle;
114 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Close_r(b, tctx, &r),
115 "Close failed");
116 torture_assert_ntstatus_ok(tctx, r.out.result, "Close failed");
118 return true;
121 static bool test_Shutdown(struct dcerpc_binding_handle *b,
122 struct torture_context *tctx,
123 struct policy_handle *handle)
125 struct samr_Shutdown r;
127 if (!torture_setting_bool(tctx, "dangerous", false)) {
128 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
129 return true;
132 r.in.connect_handle = handle;
134 torture_comment(tctx, "Testing samr_Shutdown\n");
136 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Shutdown_r(b, tctx, &r),
137 "Shutdown failed");
138 torture_assert_ntstatus_ok(tctx, r.out.result, "Shutdown failed");
140 return true;
143 static bool test_SetDsrmPassword(struct dcerpc_binding_handle *b,
144 struct torture_context *tctx,
145 struct policy_handle *handle)
147 struct samr_SetDsrmPassword r;
148 struct lsa_String string;
149 struct samr_Password hash;
151 if (!torture_setting_bool(tctx, "dangerous", false)) {
152 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
155 E_md4hash("TeSTDSRM123", hash.hash);
157 init_lsa_String(&string, "Administrator");
159 r.in.name = &string;
160 r.in.unknown = 0;
161 r.in.hash = &hash;
163 torture_comment(tctx, "Testing samr_SetDsrmPassword\n");
165 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDsrmPassword_r(b, tctx, &r),
166 "SetDsrmPassword failed");
167 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_SUPPORTED, "SetDsrmPassword failed");
169 return true;
173 static bool test_QuerySecurity(struct dcerpc_binding_handle *b,
174 struct torture_context *tctx,
175 struct policy_handle *handle)
177 struct samr_QuerySecurity r;
178 struct samr_SetSecurity s;
179 struct sec_desc_buf *sdbuf = NULL;
181 r.in.handle = handle;
182 r.in.sec_info = 7;
183 r.out.sdbuf = &sdbuf;
185 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
186 "QuerySecurity failed");
187 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
189 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
191 s.in.handle = handle;
192 s.in.sec_info = 7;
193 s.in.sdbuf = sdbuf;
195 if (torture_setting_bool(tctx, "samba4", false)) {
196 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
199 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetSecurity_r(b, tctx, &s),
200 "SetSecurity failed");
201 torture_assert_ntstatus_ok(tctx, r.out.result, "SetSecurity failed");
203 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
204 "QuerySecurity failed");
205 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
207 return true;
211 static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_context *tctx,
212 struct policy_handle *handle, uint32_t base_acct_flags,
213 const char *base_account_name)
215 struct samr_SetUserInfo s;
216 struct samr_SetUserInfo2 s2;
217 struct samr_QueryUserInfo q;
218 struct samr_QueryUserInfo q0;
219 union samr_UserInfo u;
220 union samr_UserInfo *info;
221 bool ret = true;
222 const char *test_account_name;
224 uint32_t user_extra_flags = 0;
226 if (!torture_setting_bool(tctx, "samba3", false)) {
227 if (base_acct_flags == ACB_NORMAL) {
228 /* When created, accounts are expired by default */
229 user_extra_flags = ACB_PW_EXPIRED;
233 s.in.user_handle = handle;
234 s.in.info = &u;
236 s2.in.user_handle = handle;
237 s2.in.info = &u;
239 q.in.user_handle = handle;
240 q.out.info = &info;
241 q0 = q;
243 #define TESTCALL(call, r) \
244 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ ##call## _r(b, tctx, &r),\
245 #call " failed"); \
246 if (!NT_STATUS_IS_OK(r.out.result)) { \
247 torture_result(tctx, TORTURE_FAIL, #call " level %u failed - %s (%s)\n", \
248 r.in.level, nt_errstr(r.out.result), __location__); \
249 ret = false; \
250 break; \
253 #define STRING_EQUAL(s1, s2, field) \
254 torture_assert_str_equal(tctx, s1, s2, "Failed to set " #field)
256 #define MEM_EQUAL(s1, s2, length, field) \
257 torture_assert_mem_equal(tctx, s1, s2, length, "Failed to set " #field)
259 #define INT_EQUAL(i1, i2, field) \
260 torture_assert_int_equal(tctx, i1, i2, "Failed to set " #field)
262 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
263 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
264 q.in.level = lvl1; \
265 TESTCALL(QueryUserInfo, q) \
266 s.in.level = lvl1; \
267 s2.in.level = lvl1; \
268 u = *info; \
269 if (lvl1 == 21) { \
270 ZERO_STRUCT(u.info21); \
271 u.info21.fields_present = fpval; \
273 init_lsa_String(&u.info ## lvl1.field1, value); \
274 TESTCALL(SetUserInfo, s) \
275 TESTCALL(SetUserInfo2, s2) \
276 init_lsa_String(&u.info ## lvl1.field1, ""); \
277 TESTCALL(QueryUserInfo, q); \
278 u = *info; \
279 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
280 q.in.level = lvl2; \
281 TESTCALL(QueryUserInfo, q) \
282 u = *info; \
283 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
284 } while (0)
286 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
287 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
288 q.in.level = lvl1; \
289 TESTCALL(QueryUserInfo, q) \
290 s.in.level = lvl1; \
291 s2.in.level = lvl1; \
292 u = *info; \
293 if (lvl1 == 21) { \
294 ZERO_STRUCT(u.info21); \
295 u.info21.fields_present = fpval; \
297 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
298 TESTCALL(SetUserInfo, s) \
299 TESTCALL(SetUserInfo2, s2) \
300 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
301 TESTCALL(QueryUserInfo, q); \
302 u = *info; \
303 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
304 q.in.level = lvl2; \
305 TESTCALL(QueryUserInfo, q) \
306 u = *info; \
307 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
308 } while (0)
310 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
311 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
312 q.in.level = lvl1; \
313 TESTCALL(QueryUserInfo, q) \
314 s.in.level = lvl1; \
315 s2.in.level = lvl1; \
316 u = *info; \
317 if (lvl1 == 21) { \
318 uint8_t *bits = u.info21.logon_hours.bits; \
319 ZERO_STRUCT(u.info21); \
320 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
321 u.info21.logon_hours.units_per_week = 168; \
322 u.info21.logon_hours.bits = bits; \
324 u.info21.fields_present = fpval; \
326 u.info ## lvl1.field1 = value; \
327 TESTCALL(SetUserInfo, s) \
328 TESTCALL(SetUserInfo2, s2) \
329 u.info ## lvl1.field1 = 0; \
330 TESTCALL(QueryUserInfo, q); \
331 u = *info; \
332 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
333 q.in.level = lvl2; \
334 TESTCALL(QueryUserInfo, q) \
335 u = *info; \
336 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
337 } while (0)
339 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
340 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
341 } while (0)
343 q0.in.level = 12;
344 do { TESTCALL(QueryUserInfo, q0) } while (0);
346 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
347 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
348 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
349 SAMR_FIELD_COMMENT);
351 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
352 TEST_USERINFO_STRING(7, account_name, 1, account_name, test_account_name, 0);
353 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
354 TEST_USERINFO_STRING(7, account_name, 3, account_name, test_account_name, 0);
355 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
356 TEST_USERINFO_STRING(7, account_name, 5, account_name, test_account_name, 0);
357 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
358 TEST_USERINFO_STRING(7, account_name, 6, account_name, test_account_name, 0);
359 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
360 TEST_USERINFO_STRING(7, account_name, 7, account_name, test_account_name, 0);
361 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
362 TEST_USERINFO_STRING(7, account_name, 21, account_name, test_account_name, 0);
363 test_account_name = base_account_name;
364 TEST_USERINFO_STRING(21, account_name, 21, account_name, test_account_name,
365 SAMR_FIELD_ACCOUNT_NAME);
367 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
368 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
369 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
370 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
371 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
372 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
373 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
374 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
375 SAMR_FIELD_FULL_NAME);
377 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
378 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
379 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
380 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
381 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
382 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
383 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
384 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
385 SAMR_FIELD_FULL_NAME);
387 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
388 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
389 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
390 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
391 SAMR_FIELD_LOGON_SCRIPT);
393 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
394 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
395 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
396 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
397 SAMR_FIELD_PROFILE_PATH);
399 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
400 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
401 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
402 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
403 SAMR_FIELD_HOME_DIRECTORY);
404 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
405 SAMR_FIELD_HOME_DIRECTORY);
407 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
408 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
409 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
410 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
411 SAMR_FIELD_HOME_DRIVE);
412 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
413 SAMR_FIELD_HOME_DRIVE);
415 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
416 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
417 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
418 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
419 SAMR_FIELD_DESCRIPTION);
421 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
422 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
423 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
424 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
425 SAMR_FIELD_WORKSTATIONS);
426 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
427 SAMR_FIELD_WORKSTATIONS);
428 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
429 SAMR_FIELD_WORKSTATIONS);
430 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
431 SAMR_FIELD_WORKSTATIONS);
433 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
434 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
435 SAMR_FIELD_PARAMETERS);
436 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
437 SAMR_FIELD_PARAMETERS);
438 /* also empty user parameters are allowed */
439 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
440 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
441 SAMR_FIELD_PARAMETERS);
442 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
443 SAMR_FIELD_PARAMETERS);
445 /* Samba 3 cannot store country_code and code_page atm. - gd */
446 if (!torture_setting_bool(tctx, "samba3", false)) {
447 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
448 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
449 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
450 SAMR_FIELD_COUNTRY_CODE);
451 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
452 SAMR_FIELD_COUNTRY_CODE);
454 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
455 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
456 SAMR_FIELD_CODE_PAGE);
457 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
458 SAMR_FIELD_CODE_PAGE);
461 if (!torture_setting_bool(tctx, "samba3", false)) {
462 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
463 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
464 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
465 SAMR_FIELD_ACCT_EXPIRY);
466 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
467 SAMR_FIELD_ACCT_EXPIRY);
468 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
469 SAMR_FIELD_ACCT_EXPIRY);
470 } else {
471 /* Samba 3 can only store seconds / time_t in passdb - gd */
472 NTTIME nt;
473 unix_to_nt_time(&nt, time(NULL) + __LINE__);
474 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
475 unix_to_nt_time(&nt, time(NULL) + __LINE__);
476 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
477 unix_to_nt_time(&nt, time(NULL) + __LINE__);
478 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
479 unix_to_nt_time(&nt, time(NULL) + __LINE__);
480 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
481 unix_to_nt_time(&nt, time(NULL) + __LINE__);
482 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
485 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
486 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
487 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
488 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
489 SAMR_FIELD_LOGON_HOURS);
491 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
492 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
493 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
495 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
496 (base_acct_flags | ACB_DISABLED),
497 (base_acct_flags | ACB_DISABLED | user_extra_flags),
500 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
501 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
502 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
503 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
505 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
506 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
507 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
511 /* The 'autolock' flag doesn't stick - check this */
512 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
513 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
514 (base_acct_flags | ACB_DISABLED | user_extra_flags),
516 #if 0
517 /* Removing the 'disabled' flag doesn't stick - check this */
518 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
519 (base_acct_flags),
520 (base_acct_flags | ACB_DISABLED | user_extra_flags),
522 #endif
524 /* Samba3 cannot store these atm */
525 if (!torture_setting_bool(tctx, "samba3", false)) {
526 /* The 'store plaintext' flag does stick */
527 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
528 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
529 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
531 /* The 'use DES' flag does stick */
532 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
533 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
534 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
536 /* The 'don't require kerberos pre-authentication flag does stick */
537 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
538 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
539 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
541 /* The 'no kerberos PAC required' flag sticks */
542 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
543 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
544 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
547 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
548 (base_acct_flags | ACB_DISABLED),
549 (base_acct_flags | ACB_DISABLED | user_extra_flags),
550 SAMR_FIELD_ACCT_FLAGS);
552 #if 0
553 /* these fail with win2003 - it appears you can't set the primary gid?
554 the set succeeds, but the gid isn't changed. Very weird! */
555 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
556 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
557 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
558 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
559 #endif
561 return ret;
565 generate a random password for password change tests
567 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
569 size_t len = MAX(8, min_len);
570 char *s = generate_random_password(mem_ctx, len, len+6);
571 return s;
574 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
576 char *s = samr_rand_pass_silent(mem_ctx, min_len);
577 printf("Generated password '%s'\n", s);
578 return s;
583 generate a random password for password change tests
585 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
587 int i;
588 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
589 generate_random_buffer(password.data, password.length);
591 for (i=0; i < len; i++) {
592 if (((uint16_t *)password.data)[i] == 0) {
593 ((uint16_t *)password.data)[i] = 1;
597 return password;
601 generate a random password for password change tests (fixed length)
603 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
605 char *s = generate_random_password(mem_ctx, len, len);
606 printf("Generated password '%s'\n", s);
607 return s;
610 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
611 struct policy_handle *handle, char **password)
613 NTSTATUS status;
614 struct samr_SetUserInfo s;
615 union samr_UserInfo u;
616 bool ret = true;
617 DATA_BLOB session_key;
618 char *newpass;
619 struct dcerpc_binding_handle *b = p->binding_handle;
620 struct samr_GetUserPwInfo pwp;
621 struct samr_PwInfo info;
622 int policy_min_pw_len = 0;
623 pwp.in.user_handle = handle;
624 pwp.out.info = &info;
626 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
627 "GetUserPwInfo failed");
628 if (NT_STATUS_IS_OK(pwp.out.result)) {
629 policy_min_pw_len = pwp.out.info->min_password_length;
631 newpass = samr_rand_pass(tctx, policy_min_pw_len);
633 s.in.user_handle = handle;
634 s.in.info = &u;
635 s.in.level = 24;
637 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
638 u.info24.password_expired = 0;
640 status = dcerpc_fetch_session_key(p, &session_key);
641 if (!NT_STATUS_IS_OK(status)) {
642 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
643 s.in.level, nt_errstr(status));
644 return false;
647 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
649 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
651 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
652 "SetUserInfo failed");
653 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
654 __location__, __FUNCTION__,
655 newpass, nt_errstr(s.out.result));
656 if (!NT_STATUS_IS_OK(s.out.result)) {
657 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
658 s.in.level, nt_errstr(s.out.result));
659 ret = false;
660 } else {
661 *password = newpass;
664 return ret;
668 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
669 struct policy_handle *handle, uint32_t fields_present,
670 char **password)
672 NTSTATUS status;
673 struct samr_SetUserInfo s;
674 union samr_UserInfo u;
675 bool ret = true;
676 DATA_BLOB session_key;
677 struct dcerpc_binding_handle *b = p->binding_handle;
678 char *newpass;
679 struct samr_GetUserPwInfo pwp;
680 struct samr_PwInfo info;
681 int policy_min_pw_len = 0;
682 pwp.in.user_handle = handle;
683 pwp.out.info = &info;
685 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
686 "GetUserPwInfo failed");
687 if (NT_STATUS_IS_OK(pwp.out.result)) {
688 policy_min_pw_len = pwp.out.info->min_password_length;
690 newpass = samr_rand_pass(tctx, policy_min_pw_len);
692 s.in.user_handle = handle;
693 s.in.info = &u;
694 s.in.level = 23;
696 ZERO_STRUCT(u);
698 u.info23.info.fields_present = fields_present;
700 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
702 status = dcerpc_fetch_session_key(p, &session_key);
703 if (!NT_STATUS_IS_OK(status)) {
704 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
705 s.in.level, nt_errstr(status));
706 return false;
709 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
711 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
713 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
714 "SetUserInfo failed");
715 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
716 __location__, __FUNCTION__,
717 newpass, nt_errstr(s.out.result));
718 if (!NT_STATUS_IS_OK(s.out.result)) {
719 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
720 s.in.level, nt_errstr(s.out.result));
721 ret = false;
722 } else {
723 *password = newpass;
726 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
728 status = dcerpc_fetch_session_key(p, &session_key);
729 if (!NT_STATUS_IS_OK(status)) {
730 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
731 s.in.level, nt_errstr(status));
732 return false;
735 /* This should break the key nicely */
736 session_key.length--;
737 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
739 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
741 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
742 "SetUserInfo failed");
743 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
744 __location__, __FUNCTION__,
745 newpass, nt_errstr(s.out.result));
746 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
747 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
748 s.in.level, nt_errstr(s.out.result));
749 ret = false;
752 return ret;
756 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
757 struct policy_handle *handle, bool makeshort,
758 char **password)
760 NTSTATUS status;
761 struct samr_SetUserInfo s;
762 union samr_UserInfo u;
763 bool ret = true;
764 DATA_BLOB session_key;
765 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
766 uint8_t confounder[16];
767 char *newpass;
768 struct dcerpc_binding_handle *b = p->binding_handle;
769 MD5_CTX ctx;
770 struct samr_GetUserPwInfo pwp;
771 struct samr_PwInfo info;
772 int policy_min_pw_len = 0;
773 pwp.in.user_handle = handle;
774 pwp.out.info = &info;
776 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
777 "GetUserPwInfo failed");
778 if (NT_STATUS_IS_OK(pwp.out.result)) {
779 policy_min_pw_len = pwp.out.info->min_password_length;
781 if (makeshort && policy_min_pw_len) {
782 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
783 } else {
784 newpass = samr_rand_pass(tctx, policy_min_pw_len);
787 s.in.user_handle = handle;
788 s.in.info = &u;
789 s.in.level = 26;
791 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
792 u.info26.password_expired = 0;
794 status = dcerpc_fetch_session_key(p, &session_key);
795 if (!NT_STATUS_IS_OK(status)) {
796 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
797 s.in.level, nt_errstr(status));
798 return false;
801 generate_random_buffer((uint8_t *)confounder, 16);
803 MD5Init(&ctx);
804 MD5Update(&ctx, confounder, 16);
805 MD5Update(&ctx, session_key.data, session_key.length);
806 MD5Final(confounded_session_key.data, &ctx);
808 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
809 memcpy(&u.info26.password.data[516], confounder, 16);
811 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
813 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
814 "SetUserInfo failed");
815 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
816 __location__, __FUNCTION__,
817 newpass, nt_errstr(s.out.result));
818 if (!NT_STATUS_IS_OK(s.out.result)) {
819 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
820 s.in.level, nt_errstr(s.out.result));
821 ret = false;
822 } else {
823 *password = newpass;
826 /* This should break the key nicely */
827 confounded_session_key.data[0]++;
829 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
830 memcpy(&u.info26.password.data[516], confounder, 16);
832 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
834 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
835 "SetUserInfo failed");
836 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
837 __location__, __FUNCTION__,
838 newpass, nt_errstr(s.out.result));
839 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
840 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
841 s.in.level, nt_errstr(s.out.result));
842 ret = false;
843 } else {
844 *password = newpass;
847 return ret;
850 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
851 struct policy_handle *handle, uint32_t fields_present,
852 char **password)
854 NTSTATUS status;
855 struct samr_SetUserInfo s;
856 union samr_UserInfo u;
857 bool ret = true;
858 DATA_BLOB session_key;
859 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
860 MD5_CTX ctx;
861 uint8_t confounder[16];
862 char *newpass;
863 struct dcerpc_binding_handle *b = p->binding_handle;
864 struct samr_GetUserPwInfo pwp;
865 struct samr_PwInfo info;
866 int policy_min_pw_len = 0;
867 pwp.in.user_handle = handle;
868 pwp.out.info = &info;
870 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
871 "GetUserPwInfo failed");
872 if (NT_STATUS_IS_OK(pwp.out.result)) {
873 policy_min_pw_len = pwp.out.info->min_password_length;
875 newpass = samr_rand_pass(tctx, policy_min_pw_len);
877 s.in.user_handle = handle;
878 s.in.info = &u;
879 s.in.level = 25;
881 ZERO_STRUCT(u);
883 u.info25.info.fields_present = fields_present;
885 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
887 status = dcerpc_fetch_session_key(p, &session_key);
888 if (!NT_STATUS_IS_OK(status)) {
889 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
890 s.in.level, nt_errstr(status));
891 return false;
894 generate_random_buffer((uint8_t *)confounder, 16);
896 MD5Init(&ctx);
897 MD5Update(&ctx, confounder, 16);
898 MD5Update(&ctx, session_key.data, session_key.length);
899 MD5Final(confounded_session_key.data, &ctx);
901 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
902 memcpy(&u.info25.password.data[516], confounder, 16);
904 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
906 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
907 "SetUserInfo failed");
908 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
909 __location__, __FUNCTION__,
910 newpass, nt_errstr(s.out.result));
911 if (!NT_STATUS_IS_OK(s.out.result)) {
912 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
913 s.in.level, nt_errstr(s.out.result));
914 ret = false;
915 } else {
916 *password = newpass;
919 /* This should break the key nicely */
920 confounded_session_key.data[0]++;
922 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
923 memcpy(&u.info25.password.data[516], confounder, 16);
925 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
927 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
928 "SetUserInfo failed");
929 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
930 __location__, __FUNCTION__,
931 newpass, nt_errstr(s.out.result));
932 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
933 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
934 s.in.level, nt_errstr(s.out.result));
935 ret = false;
938 return ret;
941 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
942 struct policy_handle *handle, char **password)
944 NTSTATUS status;
945 struct samr_SetUserInfo s;
946 union samr_UserInfo u;
947 bool ret = true;
948 DATA_BLOB session_key;
949 char *newpass;
950 struct dcerpc_binding_handle *b = p->binding_handle;
951 struct samr_GetUserPwInfo pwp;
952 struct samr_PwInfo info;
953 int policy_min_pw_len = 0;
954 uint8_t lm_hash[16], nt_hash[16];
956 pwp.in.user_handle = handle;
957 pwp.out.info = &info;
959 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
960 "GetUserPwInfo failed");
961 if (NT_STATUS_IS_OK(pwp.out.result)) {
962 policy_min_pw_len = pwp.out.info->min_password_length;
964 newpass = samr_rand_pass(tctx, policy_min_pw_len);
966 s.in.user_handle = handle;
967 s.in.info = &u;
968 s.in.level = 18;
970 ZERO_STRUCT(u);
972 u.info18.nt_pwd_active = true;
973 u.info18.lm_pwd_active = true;
975 E_md4hash(newpass, nt_hash);
976 E_deshash(newpass, lm_hash);
978 status = dcerpc_fetch_session_key(p, &session_key);
979 if (!NT_STATUS_IS_OK(status)) {
980 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
981 s.in.level, nt_errstr(status));
982 return false;
986 DATA_BLOB in,out;
987 in = data_blob_const(nt_hash, 16);
988 out = data_blob_talloc_zero(tctx, 16);
989 sess_crypt_blob(&out, &in, &session_key, true);
990 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
993 DATA_BLOB in,out;
994 in = data_blob_const(lm_hash, 16);
995 out = data_blob_talloc_zero(tctx, 16);
996 sess_crypt_blob(&out, &in, &session_key, true);
997 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1000 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
1002 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1003 "SetUserInfo failed");
1004 if (!NT_STATUS_IS_OK(s.out.result)) {
1005 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1006 s.in.level, nt_errstr(s.out.result));
1007 ret = false;
1008 } else {
1009 *password = newpass;
1012 return ret;
1015 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1016 struct policy_handle *handle, uint32_t fields_present,
1017 char **password)
1019 NTSTATUS status;
1020 struct samr_SetUserInfo s;
1021 union samr_UserInfo u;
1022 bool ret = true;
1023 DATA_BLOB session_key;
1024 char *newpass;
1025 struct dcerpc_binding_handle *b = p->binding_handle;
1026 struct samr_GetUserPwInfo pwp;
1027 struct samr_PwInfo info;
1028 int policy_min_pw_len = 0;
1029 uint8_t lm_hash[16], nt_hash[16];
1031 pwp.in.user_handle = handle;
1032 pwp.out.info = &info;
1034 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1035 "GetUserPwInfo failed");
1036 if (NT_STATUS_IS_OK(pwp.out.result)) {
1037 policy_min_pw_len = pwp.out.info->min_password_length;
1039 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1041 s.in.user_handle = handle;
1042 s.in.info = &u;
1043 s.in.level = 21;
1045 E_md4hash(newpass, nt_hash);
1046 E_deshash(newpass, lm_hash);
1048 ZERO_STRUCT(u);
1050 u.info21.fields_present = fields_present;
1052 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1053 u.info21.lm_owf_password.length = 16;
1054 u.info21.lm_owf_password.size = 16;
1055 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1056 u.info21.lm_password_set = true;
1059 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1060 u.info21.nt_owf_password.length = 16;
1061 u.info21.nt_owf_password.size = 16;
1062 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1063 u.info21.nt_password_set = true;
1066 status = dcerpc_fetch_session_key(p, &session_key);
1067 if (!NT_STATUS_IS_OK(status)) {
1068 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1069 s.in.level, nt_errstr(status));
1070 return false;
1073 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1074 DATA_BLOB in,out;
1075 in = data_blob_const(u.info21.lm_owf_password.array,
1076 u.info21.lm_owf_password.length);
1077 out = data_blob_talloc_zero(tctx, 16);
1078 sess_crypt_blob(&out, &in, &session_key, true);
1079 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1082 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1083 DATA_BLOB in,out;
1084 in = data_blob_const(u.info21.nt_owf_password.array,
1085 u.info21.nt_owf_password.length);
1086 out = data_blob_talloc_zero(tctx, 16);
1087 sess_crypt_blob(&out, &in, &session_key, true);
1088 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1091 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1093 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1094 "SetUserInfo failed");
1095 if (!NT_STATUS_IS_OK(s.out.result)) {
1096 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1097 s.in.level, nt_errstr(s.out.result));
1098 ret = false;
1099 } else {
1100 *password = newpass;
1103 /* try invalid length */
1104 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1106 u.info21.nt_owf_password.length++;
1108 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1109 "SetUserInfo failed");
1110 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1111 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1112 s.in.level, nt_errstr(s.out.result));
1113 ret = false;
1117 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1119 u.info21.lm_owf_password.length++;
1121 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1122 "SetUserInfo failed");
1123 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1124 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1125 s.in.level, nt_errstr(s.out.result));
1126 ret = false;
1130 return ret;
1133 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1134 struct torture_context *tctx,
1135 struct policy_handle *handle,
1136 uint16_t level,
1137 uint32_t fields_present,
1138 char **password, uint8_t password_expired,
1139 bool use_setinfo2,
1140 bool *matched_expected_error)
1142 NTSTATUS status;
1143 NTSTATUS expected_error = NT_STATUS_OK;
1144 struct samr_SetUserInfo s;
1145 struct samr_SetUserInfo2 s2;
1146 union samr_UserInfo u;
1147 bool ret = true;
1148 DATA_BLOB session_key;
1149 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1150 MD5_CTX ctx;
1151 uint8_t confounder[16];
1152 char *newpass;
1153 struct dcerpc_binding_handle *b = p->binding_handle;
1154 struct samr_GetUserPwInfo pwp;
1155 struct samr_PwInfo info;
1156 int policy_min_pw_len = 0;
1157 const char *comment = NULL;
1158 uint8_t lm_hash[16], nt_hash[16];
1160 pwp.in.user_handle = handle;
1161 pwp.out.info = &info;
1163 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1164 "GetUserPwInfo failed");
1165 if (NT_STATUS_IS_OK(pwp.out.result)) {
1166 policy_min_pw_len = pwp.out.info->min_password_length;
1168 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1170 if (use_setinfo2) {
1171 s2.in.user_handle = handle;
1172 s2.in.info = &u;
1173 s2.in.level = level;
1174 } else {
1175 s.in.user_handle = handle;
1176 s.in.info = &u;
1177 s.in.level = level;
1180 if (fields_present & SAMR_FIELD_COMMENT) {
1181 comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
1184 ZERO_STRUCT(u);
1186 switch (level) {
1187 case 18:
1188 E_md4hash(newpass, nt_hash);
1189 E_deshash(newpass, lm_hash);
1191 u.info18.nt_pwd_active = true;
1192 u.info18.lm_pwd_active = true;
1193 u.info18.password_expired = password_expired;
1195 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1196 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1198 break;
1199 case 21:
1200 E_md4hash(newpass, nt_hash);
1201 E_deshash(newpass, lm_hash);
1203 u.info21.fields_present = fields_present;
1204 u.info21.password_expired = password_expired;
1205 u.info21.comment.string = comment;
1207 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1208 u.info21.lm_owf_password.length = 16;
1209 u.info21.lm_owf_password.size = 16;
1210 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1211 u.info21.lm_password_set = true;
1214 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1215 u.info21.nt_owf_password.length = 16;
1216 u.info21.nt_owf_password.size = 16;
1217 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1218 u.info21.nt_password_set = true;
1221 break;
1222 case 23:
1223 u.info23.info.fields_present = fields_present;
1224 u.info23.info.password_expired = password_expired;
1225 u.info23.info.comment.string = comment;
1227 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1229 break;
1230 case 24:
1231 u.info24.password_expired = password_expired;
1233 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1235 break;
1236 case 25:
1237 u.info25.info.fields_present = fields_present;
1238 u.info25.info.password_expired = password_expired;
1239 u.info25.info.comment.string = comment;
1241 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1243 break;
1244 case 26:
1245 u.info26.password_expired = password_expired;
1247 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1249 break;
1252 status = dcerpc_fetch_session_key(p, &session_key);
1253 if (!NT_STATUS_IS_OK(status)) {
1254 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1255 s.in.level, nt_errstr(status));
1256 return false;
1259 generate_random_buffer((uint8_t *)confounder, 16);
1261 MD5Init(&ctx);
1262 MD5Update(&ctx, confounder, 16);
1263 MD5Update(&ctx, session_key.data, session_key.length);
1264 MD5Final(confounded_session_key.data, &ctx);
1266 switch (level) {
1267 case 18:
1269 DATA_BLOB in,out;
1270 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1271 out = data_blob_talloc_zero(tctx, 16);
1272 sess_crypt_blob(&out, &in, &session_key, true);
1273 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1276 DATA_BLOB in,out;
1277 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1278 out = data_blob_talloc_zero(tctx, 16);
1279 sess_crypt_blob(&out, &in, &session_key, true);
1280 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1283 break;
1284 case 21:
1285 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1286 DATA_BLOB in,out;
1287 in = data_blob_const(u.info21.lm_owf_password.array,
1288 u.info21.lm_owf_password.length);
1289 out = data_blob_talloc_zero(tctx, 16);
1290 sess_crypt_blob(&out, &in, &session_key, true);
1291 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1293 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1294 DATA_BLOB in,out;
1295 in = data_blob_const(u.info21.nt_owf_password.array,
1296 u.info21.nt_owf_password.length);
1297 out = data_blob_talloc_zero(tctx, 16);
1298 sess_crypt_blob(&out, &in, &session_key, true);
1299 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1301 break;
1302 case 23:
1303 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1304 break;
1305 case 24:
1306 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1307 break;
1308 case 25:
1309 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1310 memcpy(&u.info25.password.data[516], confounder, 16);
1311 break;
1312 case 26:
1313 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1314 memcpy(&u.info26.password.data[516], confounder, 16);
1315 break;
1318 if (use_setinfo2) {
1319 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1320 "SetUserInfo2 failed");
1321 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1322 __location__, __FUNCTION__,
1323 newpass, nt_errstr(s2.out.result));
1324 status = s2.out.result;
1325 } else {
1326 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1327 "SetUserInfo failed");
1328 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1329 __location__, __FUNCTION__,
1330 newpass, nt_errstr(s.out.result));
1331 status = s.out.result;
1334 if (!NT_STATUS_IS_OK(status)) {
1335 if (fields_present == 0) {
1336 expected_error = NT_STATUS_INVALID_PARAMETER;
1338 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1339 expected_error = NT_STATUS_ACCESS_DENIED;
1343 if (!NT_STATUS_IS_OK(expected_error)) {
1344 if (use_setinfo2) {
1345 torture_assert_ntstatus_equal(tctx,
1346 s2.out.result,
1347 expected_error, "SetUserInfo2 failed");
1348 } else {
1349 torture_assert_ntstatus_equal(tctx,
1350 s.out.result,
1351 expected_error, "SetUserInfo failed");
1353 *matched_expected_error = true;
1354 return true;
1357 if (!NT_STATUS_IS_OK(status)) {
1358 torture_result(tctx, TORTURE_FAIL, "SetUserInfo%s level %u failed - %s\n",
1359 use_setinfo2 ? "2":"", level, nt_errstr(status));
1360 ret = false;
1361 } else {
1362 *password = newpass;
1365 return ret;
1368 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1369 struct torture_context *tctx,
1370 struct policy_handle *handle)
1372 struct samr_SetAliasInfo r;
1373 struct samr_QueryAliasInfo q;
1374 union samr_AliasInfo *info;
1375 uint16_t levels[] = {2, 3};
1376 int i;
1377 bool ret = true;
1379 /* Ignoring switch level 1, as that includes the number of members for the alias
1380 * and setting this to a wrong value might have negative consequences
1383 for (i=0;i<ARRAY_SIZE(levels);i++) {
1384 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1386 r.in.alias_handle = handle;
1387 r.in.level = levels[i];
1388 r.in.info = talloc(tctx, union samr_AliasInfo);
1389 switch (r.in.level) {
1390 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1391 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1392 "Test Description, should test I18N as well"); break;
1393 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1396 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1397 "SetAliasInfo failed");
1398 if (!NT_STATUS_IS_OK(r.out.result)) {
1399 torture_result(tctx, TORTURE_FAIL, "SetAliasInfo level %u failed - %s\n",
1400 levels[i], nt_errstr(r.out.result));
1401 ret = false;
1404 q.in.alias_handle = handle;
1405 q.in.level = levels[i];
1406 q.out.info = &info;
1408 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1409 "QueryAliasInfo failed");
1410 if (!NT_STATUS_IS_OK(q.out.result)) {
1411 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
1412 levels[i], nt_errstr(q.out.result));
1413 ret = false;
1417 return ret;
1420 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1421 struct torture_context *tctx,
1422 struct policy_handle *user_handle)
1424 struct samr_GetGroupsForUser r;
1425 struct samr_RidWithAttributeArray *rids = NULL;
1427 torture_comment(tctx, "Testing GetGroupsForUser\n");
1429 r.in.user_handle = user_handle;
1430 r.out.rids = &rids;
1432 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1433 "GetGroupsForUser failed");
1434 torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1436 return true;
1440 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1441 struct lsa_String *domain_name)
1443 struct samr_GetDomPwInfo r;
1444 struct samr_PwInfo info;
1445 struct dcerpc_binding_handle *b = p->binding_handle;
1447 r.in.domain_name = domain_name;
1448 r.out.info = &info;
1450 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1452 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1453 "GetDomPwInfo failed");
1454 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1456 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1457 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1459 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1460 "GetDomPwInfo failed");
1461 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1463 r.in.domain_name->string = "\\\\__NONAME__";
1464 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1466 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1467 "GetDomPwInfo failed");
1468 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1470 r.in.domain_name->string = "\\\\Builtin";
1471 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1473 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1474 "GetDomPwInfo failed");
1475 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1477 return true;
1480 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1481 struct torture_context *tctx,
1482 struct policy_handle *handle)
1484 struct samr_GetUserPwInfo r;
1485 struct samr_PwInfo info;
1487 torture_comment(tctx, "Testing GetUserPwInfo\n");
1489 r.in.user_handle = handle;
1490 r.out.info = &info;
1492 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1493 "GetUserPwInfo failed");
1494 torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1496 return true;
1499 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1500 struct torture_context *tctx,
1501 struct policy_handle *domain_handle, const char *name,
1502 uint32_t *rid)
1504 NTSTATUS status;
1505 struct samr_LookupNames n;
1506 struct lsa_String sname[2];
1507 struct samr_Ids rids, types;
1509 init_lsa_String(&sname[0], name);
1511 n.in.domain_handle = domain_handle;
1512 n.in.num_names = 1;
1513 n.in.names = sname;
1514 n.out.rids = &rids;
1515 n.out.types = &types;
1516 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1517 if (!NT_STATUS_IS_OK(status)) {
1518 return status;
1520 if (NT_STATUS_IS_OK(n.out.result)) {
1521 *rid = n.out.rids->ids[0];
1522 } else {
1523 return n.out.result;
1526 init_lsa_String(&sname[1], "xxNONAMExx");
1527 n.in.num_names = 2;
1528 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1529 if (!NT_STATUS_IS_OK(status)) {
1530 return status;
1532 if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1533 torture_result(tctx, TORTURE_FAIL, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1534 if (NT_STATUS_IS_OK(n.out.result)) {
1535 return NT_STATUS_UNSUCCESSFUL;
1537 return n.out.result;
1540 n.in.num_names = 0;
1541 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1542 if (!NT_STATUS_IS_OK(status)) {
1543 return status;
1545 if (!NT_STATUS_IS_OK(n.out.result)) {
1546 torture_result(tctx, TORTURE_FAIL, "LookupNames[0] failed - %s\n", nt_errstr(status));
1547 return n.out.result;
1550 init_lsa_String(&sname[0], "xxNONAMExx");
1551 n.in.num_names = 1;
1552 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1553 if (!NT_STATUS_IS_OK(status)) {
1554 return status;
1556 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1557 torture_result(tctx, TORTURE_FAIL, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1558 if (NT_STATUS_IS_OK(n.out.result)) {
1559 return NT_STATUS_UNSUCCESSFUL;
1561 return n.out.result;
1564 init_lsa_String(&sname[0], "xxNONAMExx");
1565 init_lsa_String(&sname[1], "xxNONAME2xx");
1566 n.in.num_names = 2;
1567 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 return status;
1571 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1572 torture_result(tctx, TORTURE_FAIL, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1573 if (NT_STATUS_IS_OK(n.out.result)) {
1574 return NT_STATUS_UNSUCCESSFUL;
1576 return n.out.result;
1579 return NT_STATUS_OK;
1582 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1583 struct torture_context *tctx,
1584 struct policy_handle *domain_handle,
1585 const char *name, struct policy_handle *user_handle)
1587 NTSTATUS status;
1588 struct samr_OpenUser r;
1589 uint32_t rid;
1591 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1592 if (!NT_STATUS_IS_OK(status)) {
1593 return status;
1596 r.in.domain_handle = domain_handle;
1597 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1598 r.in.rid = rid;
1599 r.out.user_handle = user_handle;
1600 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1601 if (!NT_STATUS_IS_OK(status)) {
1602 return status;
1604 if (!NT_STATUS_IS_OK(r.out.result)) {
1605 torture_result(tctx, TORTURE_FAIL, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1608 return r.out.result;
1611 #if 0
1612 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1613 struct torture_context *tctx,
1614 struct policy_handle *handle)
1616 NTSTATUS status;
1617 struct samr_ChangePasswordUser r;
1618 bool ret = true;
1619 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1620 struct policy_handle user_handle;
1621 char *oldpass = "test";
1622 char *newpass = "test2";
1623 uint8_t old_nt_hash[16], new_nt_hash[16];
1624 uint8_t old_lm_hash[16], new_lm_hash[16];
1626 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 return false;
1631 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1633 torture_comment(tctx, "old password: %s\n", oldpass);
1634 torture_comment(tctx, "new password: %s\n", newpass);
1636 E_md4hash(oldpass, old_nt_hash);
1637 E_md4hash(newpass, new_nt_hash);
1638 E_deshash(oldpass, old_lm_hash);
1639 E_deshash(newpass, new_lm_hash);
1641 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1642 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1643 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1644 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1645 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1646 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1648 r.in.handle = &user_handle;
1649 r.in.lm_present = 1;
1650 r.in.old_lm_crypted = &hash1;
1651 r.in.new_lm_crypted = &hash2;
1652 r.in.nt_present = 1;
1653 r.in.old_nt_crypted = &hash3;
1654 r.in.new_nt_crypted = &hash4;
1655 r.in.cross1_present = 1;
1656 r.in.nt_cross = &hash5;
1657 r.in.cross2_present = 1;
1658 r.in.lm_cross = &hash6;
1660 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1661 "ChangePasswordUser failed");
1662 if (!NT_STATUS_IS_OK(r.out.result)) {
1663 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1664 ret = false;
1667 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1668 ret = false;
1671 return ret;
1673 #endif
1675 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1676 struct torture_context *tctx,
1677 const char *acct_name,
1678 struct policy_handle *handle, char **password)
1680 NTSTATUS status;
1681 struct samr_ChangePasswordUser r;
1682 bool ret = true;
1683 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1684 struct policy_handle user_handle;
1685 char *oldpass;
1686 uint8_t old_nt_hash[16], new_nt_hash[16];
1687 uint8_t old_lm_hash[16], new_lm_hash[16];
1688 bool changed = true;
1690 char *newpass;
1691 struct samr_GetUserPwInfo pwp;
1692 struct samr_PwInfo info;
1693 int policy_min_pw_len = 0;
1695 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1696 if (!NT_STATUS_IS_OK(status)) {
1697 return false;
1699 pwp.in.user_handle = &user_handle;
1700 pwp.out.info = &info;
1702 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1703 "GetUserPwInfo failed");
1704 if (NT_STATUS_IS_OK(pwp.out.result)) {
1705 policy_min_pw_len = pwp.out.info->min_password_length;
1707 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1709 torture_comment(tctx, "Testing ChangePasswordUser\n");
1711 torture_assert(tctx, *password != NULL,
1712 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1714 oldpass = *password;
1716 E_md4hash(oldpass, old_nt_hash);
1717 E_md4hash(newpass, new_nt_hash);
1718 E_deshash(oldpass, old_lm_hash);
1719 E_deshash(newpass, new_lm_hash);
1721 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1722 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1723 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1724 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1725 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1726 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1728 r.in.user_handle = &user_handle;
1729 r.in.lm_present = 1;
1730 /* Break the NT hash */
1731 hash3.hash[0]++;
1732 r.in.old_lm_crypted = &hash1;
1733 r.in.new_lm_crypted = &hash2;
1734 r.in.nt_present = 1;
1735 r.in.old_nt_crypted = &hash3;
1736 r.in.new_nt_crypted = &hash4;
1737 r.in.cross1_present = 1;
1738 r.in.nt_cross = &hash5;
1739 r.in.cross2_present = 1;
1740 r.in.lm_cross = &hash6;
1742 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1743 "ChangePasswordUser failed");
1744 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1745 __location__, __FUNCTION__,
1746 oldpass, newpass, nt_errstr(r.out.result));
1748 /* Do not proceed if this call has been removed */
1749 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
1750 torture_skip(tctx, "ValidatePassword not supported by server\n");
1753 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1754 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1755 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1758 /* Unbreak the NT hash */
1759 hash3.hash[0]--;
1761 r.in.user_handle = &user_handle;
1762 r.in.lm_present = 1;
1763 r.in.old_lm_crypted = &hash1;
1764 r.in.new_lm_crypted = &hash2;
1765 /* Break the LM hash */
1766 hash1.hash[0]--;
1767 r.in.nt_present = 1;
1768 r.in.old_nt_crypted = &hash3;
1769 r.in.new_nt_crypted = &hash4;
1770 r.in.cross1_present = 1;
1771 r.in.nt_cross = &hash5;
1772 r.in.cross2_present = 1;
1773 r.in.lm_cross = &hash6;
1775 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1776 "ChangePasswordUser failed");
1777 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1778 __location__, __FUNCTION__,
1779 oldpass, newpass, nt_errstr(r.out.result));
1780 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1781 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1782 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1785 /* Unbreak the NT hash */
1786 hash3.hash[0]--;
1788 r.in.user_handle = &user_handle;
1789 r.in.lm_present = 1;
1790 r.in.old_lm_crypted = &hash1;
1791 r.in.new_lm_crypted = &hash2;
1792 r.in.nt_present = 1;
1793 r.in.old_nt_crypted = &hash3;
1794 r.in.new_nt_crypted = &hash4;
1795 r.in.cross1_present = 1;
1796 r.in.nt_cross = &hash5;
1797 r.in.cross2_present = 1;
1798 /* Break the LM cross */
1799 hash6.hash[0]++;
1800 r.in.lm_cross = &hash6;
1802 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1803 "ChangePasswordUser failed");
1804 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1805 __location__, __FUNCTION__,
1806 oldpass, newpass, nt_errstr(r.out.result));
1807 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1808 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1810 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));
1811 ret = false;
1814 /* Unbreak the LM cross */
1815 hash6.hash[0]--;
1817 r.in.user_handle = &user_handle;
1818 r.in.lm_present = 1;
1819 r.in.old_lm_crypted = &hash1;
1820 r.in.new_lm_crypted = &hash2;
1821 r.in.nt_present = 1;
1822 r.in.old_nt_crypted = &hash3;
1823 r.in.new_nt_crypted = &hash4;
1824 r.in.cross1_present = 1;
1825 /* Break the NT cross */
1826 hash5.hash[0]++;
1827 r.in.nt_cross = &hash5;
1828 r.in.cross2_present = 1;
1829 r.in.lm_cross = &hash6;
1831 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1832 "ChangePasswordUser failed");
1833 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1834 __location__, __FUNCTION__,
1835 oldpass, newpass, nt_errstr(r.out.result));
1836 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1837 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1839 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));
1840 ret = false;
1843 /* Unbreak the NT cross */
1844 hash5.hash[0]--;
1847 /* Reset the hashes to not broken values */
1848 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1849 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1850 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1851 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1852 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1853 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1855 r.in.user_handle = &user_handle;
1856 r.in.lm_present = 1;
1857 r.in.old_lm_crypted = &hash1;
1858 r.in.new_lm_crypted = &hash2;
1859 r.in.nt_present = 1;
1860 r.in.old_nt_crypted = &hash3;
1861 r.in.new_nt_crypted = &hash4;
1862 r.in.cross1_present = 1;
1863 r.in.nt_cross = &hash5;
1864 r.in.cross2_present = 0;
1865 r.in.lm_cross = NULL;
1867 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1868 "ChangePasswordUser failed");
1869 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1870 __location__, __FUNCTION__,
1871 oldpass, newpass, nt_errstr(r.out.result));
1872 if (NT_STATUS_IS_OK(r.out.result)) {
1873 changed = true;
1874 *password = newpass;
1875 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1876 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));
1877 ret = false;
1880 oldpass = newpass;
1881 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1883 E_md4hash(oldpass, old_nt_hash);
1884 E_md4hash(newpass, new_nt_hash);
1885 E_deshash(oldpass, old_lm_hash);
1886 E_deshash(newpass, new_lm_hash);
1889 /* Reset the hashes to not broken values */
1890 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1891 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1892 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1893 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1894 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1895 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1897 r.in.user_handle = &user_handle;
1898 r.in.lm_present = 1;
1899 r.in.old_lm_crypted = &hash1;
1900 r.in.new_lm_crypted = &hash2;
1901 r.in.nt_present = 1;
1902 r.in.old_nt_crypted = &hash3;
1903 r.in.new_nt_crypted = &hash4;
1904 r.in.cross1_present = 0;
1905 r.in.nt_cross = NULL;
1906 r.in.cross2_present = 1;
1907 r.in.lm_cross = &hash6;
1909 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1910 "ChangePasswordUser failed");
1911 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1912 __location__, __FUNCTION__,
1913 oldpass, newpass, nt_errstr(r.out.result));
1914 if (NT_STATUS_IS_OK(r.out.result)) {
1915 changed = true;
1916 *password = newpass;
1917 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1918 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));
1919 ret = false;
1922 oldpass = newpass;
1923 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1925 E_md4hash(oldpass, old_nt_hash);
1926 E_md4hash(newpass, new_nt_hash);
1927 E_deshash(oldpass, old_lm_hash);
1928 E_deshash(newpass, new_lm_hash);
1931 /* Reset the hashes to not broken values */
1932 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1933 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1934 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1935 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1936 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1937 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1939 r.in.user_handle = &user_handle;
1940 r.in.lm_present = 1;
1941 r.in.old_lm_crypted = &hash1;
1942 r.in.new_lm_crypted = &hash2;
1943 r.in.nt_present = 1;
1944 r.in.old_nt_crypted = &hash3;
1945 r.in.new_nt_crypted = &hash4;
1946 r.in.cross1_present = 1;
1947 r.in.nt_cross = &hash5;
1948 r.in.cross2_present = 1;
1949 r.in.lm_cross = &hash6;
1951 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1952 "ChangePasswordUser failed");
1953 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1954 __location__, __FUNCTION__,
1955 oldpass, newpass, nt_errstr(r.out.result));
1956 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1957 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1958 } else if (!NT_STATUS_IS_OK(r.out.result)) {
1959 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1960 ret = false;
1961 } else {
1962 changed = true;
1963 *password = newpass;
1966 r.in.user_handle = &user_handle;
1967 r.in.lm_present = 1;
1968 r.in.old_lm_crypted = &hash1;
1969 r.in.new_lm_crypted = &hash2;
1970 r.in.nt_present = 1;
1971 r.in.old_nt_crypted = &hash3;
1972 r.in.new_nt_crypted = &hash4;
1973 r.in.cross1_present = 1;
1974 r.in.nt_cross = &hash5;
1975 r.in.cross2_present = 1;
1976 r.in.lm_cross = &hash6;
1978 if (changed) {
1979 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1980 "ChangePasswordUser failed");
1981 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1982 __location__, __FUNCTION__,
1983 oldpass, newpass, nt_errstr(r.out.result));
1984 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1985 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1986 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1987 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));
1988 ret = false;
1993 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
1994 ret = false;
1997 return ret;
2001 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
2002 struct torture_context *tctx,
2003 const char *acct_name,
2004 struct policy_handle *handle, char **password)
2006 struct samr_OemChangePasswordUser2 r;
2007 bool ret = true;
2008 struct samr_Password lm_verifier;
2009 struct samr_CryptPassword lm_pass;
2010 struct lsa_AsciiString server, account, account_bad;
2011 char *oldpass;
2012 char *newpass;
2013 struct dcerpc_binding_handle *b = p->binding_handle;
2014 uint8_t old_lm_hash[16], new_lm_hash[16];
2016 struct samr_GetDomPwInfo dom_pw_info;
2017 struct samr_PwInfo info;
2018 int policy_min_pw_len = 0;
2020 struct lsa_String domain_name;
2022 domain_name.string = "";
2023 dom_pw_info.in.domain_name = &domain_name;
2024 dom_pw_info.out.info = &info;
2026 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
2028 torture_assert(tctx, *password != NULL,
2029 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
2031 oldpass = *password;
2033 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2034 "GetDomPwInfo failed");
2035 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2036 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2039 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2041 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2042 account.string = acct_name;
2044 E_deshash(oldpass, old_lm_hash);
2045 E_deshash(newpass, new_lm_hash);
2047 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2048 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2049 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2051 r.in.server = &server;
2052 r.in.account = &account;
2053 r.in.password = &lm_pass;
2054 r.in.hash = &lm_verifier;
2056 /* Break the verification */
2057 lm_verifier.hash[0]++;
2059 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2060 "OemChangePasswordUser2 failed");
2061 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2062 __location__, __FUNCTION__,
2063 oldpass, newpass, nt_errstr(r.out.result));
2065 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2066 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2067 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2068 nt_errstr(r.out.result));
2069 ret = false;
2072 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2073 /* Break the old password */
2074 old_lm_hash[0]++;
2075 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2076 /* unbreak it for the next operation */
2077 old_lm_hash[0]--;
2078 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2080 r.in.server = &server;
2081 r.in.account = &account;
2082 r.in.password = &lm_pass;
2083 r.in.hash = &lm_verifier;
2085 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2086 "OemChangePasswordUser2 failed");
2087 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2088 __location__, __FUNCTION__,
2089 oldpass, newpass, nt_errstr(r.out.result));
2091 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2092 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2093 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2094 nt_errstr(r.out.result));
2095 ret = false;
2098 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2099 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2101 r.in.server = &server;
2102 r.in.account = &account;
2103 r.in.password = &lm_pass;
2104 r.in.hash = NULL;
2106 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2107 "OemChangePasswordUser2 failed");
2108 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2109 __location__, __FUNCTION__,
2110 oldpass, newpass, nt_errstr(r.out.result));
2112 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2113 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2114 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2115 nt_errstr(r.out.result));
2116 ret = false;
2119 /* This shouldn't be a valid name */
2120 account_bad.string = TEST_ACCOUNT_NAME "XX";
2121 r.in.account = &account_bad;
2123 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2124 "OemChangePasswordUser2 failed");
2125 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2126 __location__, __FUNCTION__,
2127 oldpass, newpass, nt_errstr(r.out.result));
2129 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2130 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2131 nt_errstr(r.out.result));
2132 ret = false;
2135 /* This shouldn't be a valid name */
2136 account_bad.string = TEST_ACCOUNT_NAME "XX";
2137 r.in.account = &account_bad;
2138 r.in.password = &lm_pass;
2139 r.in.hash = &lm_verifier;
2141 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2142 "OemChangePasswordUser2 failed");
2143 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2144 __location__, __FUNCTION__,
2145 oldpass, newpass, nt_errstr(r.out.result));
2147 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2148 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2149 nt_errstr(r.out.result));
2150 ret = false;
2153 /* This shouldn't be a valid name */
2154 account_bad.string = TEST_ACCOUNT_NAME "XX";
2155 r.in.account = &account_bad;
2156 r.in.password = NULL;
2157 r.in.hash = &lm_verifier;
2159 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2160 "OemChangePasswordUser2 failed");
2161 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2162 __location__, __FUNCTION__,
2163 oldpass, newpass, nt_errstr(r.out.result));
2165 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2166 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2167 nt_errstr(r.out.result));
2168 ret = false;
2171 E_deshash(oldpass, old_lm_hash);
2172 E_deshash(newpass, new_lm_hash);
2174 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2175 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2176 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2178 r.in.server = &server;
2179 r.in.account = &account;
2180 r.in.password = &lm_pass;
2181 r.in.hash = &lm_verifier;
2183 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2184 "OemChangePasswordUser2 failed");
2185 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2186 __location__, __FUNCTION__,
2187 oldpass, newpass, nt_errstr(r.out.result));
2189 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2190 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2191 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2192 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2193 ret = false;
2194 } else {
2195 *password = newpass;
2198 return ret;
2202 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2203 const char *acct_name,
2204 char **password,
2205 char *newpass, bool allow_password_restriction)
2207 struct samr_ChangePasswordUser2 r;
2208 bool ret = true;
2209 struct lsa_String server, account;
2210 struct samr_CryptPassword nt_pass, lm_pass;
2211 struct samr_Password nt_verifier, lm_verifier;
2212 char *oldpass;
2213 struct dcerpc_binding_handle *b = p->binding_handle;
2214 uint8_t old_nt_hash[16], new_nt_hash[16];
2215 uint8_t old_lm_hash[16], new_lm_hash[16];
2217 struct samr_GetDomPwInfo dom_pw_info;
2218 struct samr_PwInfo info;
2220 struct lsa_String domain_name;
2222 domain_name.string = "";
2223 dom_pw_info.in.domain_name = &domain_name;
2224 dom_pw_info.out.info = &info;
2226 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2228 torture_assert(tctx, *password != NULL,
2229 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2230 oldpass = *password;
2232 if (!newpass) {
2233 int policy_min_pw_len = 0;
2234 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2235 "GetDomPwInfo failed");
2236 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2237 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2240 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2243 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2244 init_lsa_String(&account, acct_name);
2246 E_md4hash(oldpass, old_nt_hash);
2247 E_md4hash(newpass, new_nt_hash);
2249 E_deshash(oldpass, old_lm_hash);
2250 E_deshash(newpass, new_lm_hash);
2252 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2253 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2254 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2256 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2257 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2258 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2260 r.in.server = &server;
2261 r.in.account = &account;
2262 r.in.nt_password = &nt_pass;
2263 r.in.nt_verifier = &nt_verifier;
2264 r.in.lm_change = 1;
2265 r.in.lm_password = &lm_pass;
2266 r.in.lm_verifier = &lm_verifier;
2268 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2269 "ChangePasswordUser2 failed");
2270 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2271 __location__, __FUNCTION__,
2272 oldpass, newpass, nt_errstr(r.out.result));
2274 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2275 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2276 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2277 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2278 ret = false;
2279 } else {
2280 *password = newpass;
2283 return ret;
2287 static bool test_ChangePasswordUser2_ntstatus(struct dcerpc_pipe *p, struct torture_context *tctx,
2288 const char *acct_name,
2289 const char *password, NTSTATUS status)
2291 struct samr_ChangePasswordUser2 r;
2292 struct lsa_String server, account;
2293 struct samr_CryptPassword nt_pass, lm_pass;
2294 struct samr_Password nt_verifier, lm_verifier;
2295 const char *oldpass;
2296 struct dcerpc_binding_handle *b = p->binding_handle;
2297 uint8_t old_nt_hash[16], new_nt_hash[16];
2298 uint8_t old_lm_hash[16], new_lm_hash[16];
2300 struct samr_GetDomPwInfo dom_pw_info;
2301 struct samr_PwInfo info;
2303 struct lsa_String domain_name;
2304 char *newpass;
2305 int policy_min_pw_len = 0;
2307 domain_name.string = "";
2308 dom_pw_info.in.domain_name = &domain_name;
2309 dom_pw_info.out.info = &info;
2311 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2313 oldpass = password;
2315 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2316 "GetDomPwInfo failed");
2317 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2318 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2321 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2323 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2324 init_lsa_String(&account, acct_name);
2326 E_md4hash(oldpass, old_nt_hash);
2327 E_md4hash(newpass, new_nt_hash);
2329 E_deshash(oldpass, old_lm_hash);
2330 E_deshash(newpass, new_lm_hash);
2332 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2333 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2334 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2336 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2337 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2338 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2340 r.in.server = &server;
2341 r.in.account = &account;
2342 r.in.nt_password = &nt_pass;
2343 r.in.nt_verifier = &nt_verifier;
2344 r.in.lm_change = 1;
2345 r.in.lm_password = &lm_pass;
2346 r.in.lm_verifier = &lm_verifier;
2348 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2349 "ChangePasswordUser2 failed");
2350 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2351 __location__, __FUNCTION__,
2352 oldpass, newpass, nt_errstr(r.out.result));
2354 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2355 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2356 } else {
2357 torture_assert_ntstatus_equal(tctx, r.out.result, status, "ChangePasswordUser2 returned unexpected value");
2360 return true;
2364 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2365 const char *account_string,
2366 int policy_min_pw_len,
2367 char **password,
2368 const char *newpass,
2369 NTTIME last_password_change,
2370 bool handle_reject_reason)
2372 struct samr_ChangePasswordUser3 r;
2373 bool ret = true;
2374 struct lsa_String server, account, account_bad;
2375 struct samr_CryptPassword nt_pass, lm_pass;
2376 struct samr_Password nt_verifier, lm_verifier;
2377 char *oldpass;
2378 struct dcerpc_binding_handle *b = p->binding_handle;
2379 uint8_t old_nt_hash[16], new_nt_hash[16];
2380 uint8_t old_lm_hash[16], new_lm_hash[16];
2381 NTTIME t;
2382 struct samr_DomInfo1 *dominfo = NULL;
2383 struct userPwdChangeFailureInformation *reject = NULL;
2385 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2387 if (newpass == NULL) {
2388 do {
2389 if (policy_min_pw_len == 0) {
2390 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2391 } else {
2392 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2394 } while (check_password_quality(newpass) == false);
2395 } else {
2396 torture_comment(tctx, "Using password '%s'\n", newpass);
2399 torture_assert(tctx, *password != NULL,
2400 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2402 oldpass = *password;
2403 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2404 init_lsa_String(&account, account_string);
2406 E_md4hash(oldpass, old_nt_hash);
2407 E_md4hash(newpass, new_nt_hash);
2409 E_deshash(oldpass, old_lm_hash);
2410 E_deshash(newpass, new_lm_hash);
2412 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2413 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2414 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2416 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2417 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2418 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2420 /* Break the verification */
2421 nt_verifier.hash[0]++;
2423 r.in.server = &server;
2424 r.in.account = &account;
2425 r.in.nt_password = &nt_pass;
2426 r.in.nt_verifier = &nt_verifier;
2427 r.in.lm_change = 1;
2428 r.in.lm_password = &lm_pass;
2429 r.in.lm_verifier = &lm_verifier;
2430 r.in.password3 = NULL;
2431 r.out.dominfo = &dominfo;
2432 r.out.reject = &reject;
2434 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2435 "ChangePasswordUser3 failed");
2436 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2437 __location__, __FUNCTION__,
2438 oldpass, newpass, nt_errstr(r.out.result));
2439 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2440 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2441 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2442 nt_errstr(r.out.result));
2443 ret = false;
2446 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2447 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2448 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2450 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2451 /* Break the NT hash */
2452 old_nt_hash[0]++;
2453 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2454 /* Unbreak it again */
2455 old_nt_hash[0]--;
2456 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2458 r.in.server = &server;
2459 r.in.account = &account;
2460 r.in.nt_password = &nt_pass;
2461 r.in.nt_verifier = &nt_verifier;
2462 r.in.lm_change = 1;
2463 r.in.lm_password = &lm_pass;
2464 r.in.lm_verifier = &lm_verifier;
2465 r.in.password3 = NULL;
2466 r.out.dominfo = &dominfo;
2467 r.out.reject = &reject;
2469 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2470 "ChangePasswordUser3 failed");
2471 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2472 __location__, __FUNCTION__,
2473 oldpass, newpass, nt_errstr(r.out.result));
2474 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2475 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2476 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2477 nt_errstr(r.out.result));
2478 ret = false;
2481 /* This shouldn't be a valid name */
2482 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2484 r.in.account = &account_bad;
2485 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2486 "ChangePasswordUser3 failed");
2487 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2488 __location__, __FUNCTION__,
2489 oldpass, newpass, nt_errstr(r.out.result));
2490 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2491 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2492 nt_errstr(r.out.result));
2493 ret = false;
2496 E_md4hash(oldpass, old_nt_hash);
2497 E_md4hash(newpass, new_nt_hash);
2499 E_deshash(oldpass, old_lm_hash);
2500 E_deshash(newpass, new_lm_hash);
2502 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2503 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2504 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2506 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2507 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2508 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2510 r.in.server = &server;
2511 r.in.account = &account;
2512 r.in.nt_password = &nt_pass;
2513 r.in.nt_verifier = &nt_verifier;
2514 r.in.lm_change = 1;
2515 r.in.lm_password = &lm_pass;
2516 r.in.lm_verifier = &lm_verifier;
2517 r.in.password3 = NULL;
2518 r.out.dominfo = &dominfo;
2519 r.out.reject = &reject;
2521 unix_to_nt_time(&t, time(NULL));
2523 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2524 "ChangePasswordUser3 failed");
2525 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2526 __location__, __FUNCTION__,
2527 oldpass, newpass, nt_errstr(r.out.result));
2529 torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2530 "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2531 __location__,
2532 (dominfo == NULL)? "NULL" : "present",
2533 reject ? "true" : "false",
2534 handle_reject_reason ? "true" : "false",
2535 null_nttime(last_password_change) ? "null" : "not null",
2536 dominfo ? (long long)dominfo->min_password_age : (long long)0);
2538 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2539 && dominfo
2540 && reject
2541 && handle_reject_reason
2542 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2543 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2545 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2546 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2547 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2548 return false;
2552 /* We tested the order of precendence which is as follows:
2554 * pwd min_age
2555 * pwd length
2556 * pwd complexity
2557 * pwd history
2559 Guenther */
2561 if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
2562 (last_password_change - dominfo->min_password_age > t)) {
2564 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2565 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2566 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2567 return false;
2570 } else if ((dominfo->min_password_length > 0) &&
2571 (strlen(newpass) < dominfo->min_password_length)) {
2573 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2574 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2575 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2576 return false;
2579 } else if ((dominfo->password_history_length > 0) &&
2580 strequal(oldpass, newpass)) {
2582 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2583 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2584 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2585 return false;
2587 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2589 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2590 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2591 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2592 return false;
2597 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2598 /* retry with adjusted size */
2599 return test_ChangePasswordUser3(p, tctx, account_string,
2600 dominfo->min_password_length,
2601 password, NULL, 0, false);
2605 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2606 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2607 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2608 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2609 return false;
2611 /* Perhaps the server has a 'min password age' set? */
2613 } else {
2614 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2616 *password = talloc_strdup(tctx, newpass);
2619 return ret;
2622 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2623 const char *account_string,
2624 struct policy_handle *handle,
2625 char **password)
2627 NTSTATUS status;
2628 struct samr_ChangePasswordUser3 r;
2629 struct samr_SetUserInfo s;
2630 union samr_UserInfo u;
2631 DATA_BLOB session_key;
2632 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2633 uint8_t confounder[16];
2634 MD5_CTX ctx;
2636 bool ret = true;
2637 struct lsa_String server, account;
2638 struct samr_CryptPassword nt_pass;
2639 struct samr_Password nt_verifier;
2640 DATA_BLOB new_random_pass;
2641 char *newpass;
2642 char *oldpass;
2643 struct dcerpc_binding_handle *b = p->binding_handle;
2644 uint8_t old_nt_hash[16], new_nt_hash[16];
2645 NTTIME t;
2646 struct samr_DomInfo1 *dominfo = NULL;
2647 struct userPwdChangeFailureInformation *reject = NULL;
2649 new_random_pass = samr_very_rand_pass(tctx, 128);
2651 torture_assert(tctx, *password != NULL,
2652 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2654 oldpass = *password;
2655 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2656 init_lsa_String(&account, account_string);
2658 s.in.user_handle = handle;
2659 s.in.info = &u;
2660 s.in.level = 25;
2662 ZERO_STRUCT(u);
2664 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2666 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2668 status = dcerpc_fetch_session_key(p, &session_key);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
2671 s.in.level, nt_errstr(status));
2672 return false;
2675 generate_random_buffer((uint8_t *)confounder, 16);
2677 MD5Init(&ctx);
2678 MD5Update(&ctx, confounder, 16);
2679 MD5Update(&ctx, session_key.data, session_key.length);
2680 MD5Final(confounded_session_key.data, &ctx);
2682 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2683 memcpy(&u.info25.password.data[516], confounder, 16);
2685 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2687 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2688 "SetUserInfo failed");
2689 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2690 __location__, __FUNCTION__,
2691 oldpass, "RANDOM", nt_errstr(s.out.result));
2692 if (!NT_STATUS_IS_OK(s.out.result)) {
2693 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
2694 s.in.level, nt_errstr(s.out.result));
2695 ret = false;
2698 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2700 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2702 new_random_pass = samr_very_rand_pass(tctx, 128);
2704 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2706 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2707 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2708 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2710 r.in.server = &server;
2711 r.in.account = &account;
2712 r.in.nt_password = &nt_pass;
2713 r.in.nt_verifier = &nt_verifier;
2714 r.in.lm_change = 0;
2715 r.in.lm_password = NULL;
2716 r.in.lm_verifier = NULL;
2717 r.in.password3 = NULL;
2718 r.out.dominfo = &dominfo;
2719 r.out.reject = &reject;
2721 unix_to_nt_time(&t, time(NULL));
2723 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2724 "ChangePasswordUser3 failed");
2725 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2726 __location__, __FUNCTION__,
2727 oldpass, "RANDOM", nt_errstr(r.out.result));
2729 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2730 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2731 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2732 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2733 return false;
2735 /* Perhaps the server has a 'min password age' set? */
2737 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2738 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2739 ret = false;
2742 newpass = samr_rand_pass(tctx, 128);
2744 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2746 E_md4hash(newpass, new_nt_hash);
2748 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2749 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2750 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2752 r.in.server = &server;
2753 r.in.account = &account;
2754 r.in.nt_password = &nt_pass;
2755 r.in.nt_verifier = &nt_verifier;
2756 r.in.lm_change = 0;
2757 r.in.lm_password = NULL;
2758 r.in.lm_verifier = NULL;
2759 r.in.password3 = NULL;
2760 r.out.dominfo = &dominfo;
2761 r.out.reject = &reject;
2763 unix_to_nt_time(&t, time(NULL));
2765 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2766 "ChangePasswordUser3 failed");
2767 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2768 __location__, __FUNCTION__,
2769 oldpass, newpass, nt_errstr(r.out.result));
2771 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2772 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2773 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2774 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2775 return false;
2777 /* Perhaps the server has a 'min password age' set? */
2779 } else {
2780 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2781 *password = talloc_strdup(tctx, newpass);
2784 return ret;
2788 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2789 struct torture_context *tctx,
2790 struct policy_handle *alias_handle)
2792 struct samr_GetMembersInAlias r;
2793 struct lsa_SidArray sids;
2795 torture_comment(tctx, "Testing GetMembersInAlias\n");
2797 r.in.alias_handle = alias_handle;
2798 r.out.sids = &sids;
2800 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2801 "GetMembersInAlias failed");
2802 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2804 return true;
2807 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2808 struct torture_context *tctx,
2809 struct policy_handle *alias_handle,
2810 const struct dom_sid *domain_sid)
2812 struct samr_AddAliasMember r;
2813 struct samr_DeleteAliasMember d;
2814 struct dom_sid *sid;
2816 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2818 torture_comment(tctx, "Testing AddAliasMember\n");
2819 r.in.alias_handle = alias_handle;
2820 r.in.sid = sid;
2822 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2823 "AddAliasMember failed");
2824 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2826 d.in.alias_handle = alias_handle;
2827 d.in.sid = sid;
2829 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2830 "DeleteAliasMember failed");
2831 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2833 return true;
2836 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2837 struct torture_context *tctx,
2838 struct policy_handle *alias_handle)
2840 struct samr_AddMultipleMembersToAlias a;
2841 struct samr_RemoveMultipleMembersFromAlias r;
2842 struct lsa_SidArray sids;
2844 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2845 a.in.alias_handle = alias_handle;
2846 a.in.sids = &sids;
2848 sids.num_sids = 3;
2849 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2851 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2852 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2853 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2855 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2856 "AddMultipleMembersToAlias failed");
2857 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2860 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2861 r.in.alias_handle = alias_handle;
2862 r.in.sids = &sids;
2864 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2865 "RemoveMultipleMembersFromAlias failed");
2866 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2868 /* strange! removing twice doesn't give any error */
2869 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2870 "RemoveMultipleMembersFromAlias failed");
2871 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2873 /* but removing an alias that isn't there does */
2874 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2876 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2877 "RemoveMultipleMembersFromAlias failed");
2878 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2880 return true;
2883 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2884 struct torture_context *tctx,
2885 struct policy_handle *domain_handle)
2887 struct samr_GetAliasMembership r;
2888 struct lsa_SidArray sids;
2889 struct samr_Ids rids;
2891 torture_comment(tctx, "Testing GetAliasMembership\n");
2893 r.in.domain_handle = domain_handle;
2894 r.in.sids = &sids;
2895 r.out.rids = &rids;
2897 sids.num_sids = 0;
2898 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2900 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2901 "GetAliasMembership failed");
2902 torture_assert_ntstatus_ok(tctx, r.out.result,
2903 "samr_GetAliasMembership failed");
2905 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2906 "protocol misbehaviour");
2908 sids.num_sids = 1;
2909 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2910 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2912 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2913 "samr_GetAliasMembership failed");
2914 torture_assert_ntstatus_ok(tctx, r.out.result,
2915 "samr_GetAliasMembership failed");
2917 #if 0
2918 /* only true for w2k8 it seems
2919 * win7, xp, w2k3 will return a 0 length array pointer */
2921 if (rids.ids && (rids.count == 0)) {
2922 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2924 #endif
2925 if (!rids.ids && rids.count) {
2926 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2929 return true;
2932 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2933 struct torture_context *tctx,
2934 struct policy_handle *user_handle)
2936 struct samr_TestPrivateFunctionsUser r;
2938 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2940 r.in.user_handle = user_handle;
2942 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2943 "TestPrivateFunctionsUser failed");
2944 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2946 return true;
2949 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2950 struct torture_context *tctx,
2951 struct policy_handle *handle,
2952 bool use_info2,
2953 NTTIME *pwdlastset)
2955 NTSTATUS status;
2956 uint16_t levels[] = { /* 3, */ 5, 21 };
2957 int i;
2958 /* NTTIME pwdlastset3 = 0; */
2959 NTTIME pwdlastset5 = 0;
2960 NTTIME pwdlastset21 = 0;
2962 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2963 use_info2 ? "2":"");
2965 for (i=0; i<ARRAY_SIZE(levels); i++) {
2967 struct samr_QueryUserInfo r;
2968 struct samr_QueryUserInfo2 r2;
2969 union samr_UserInfo *info;
2971 if (use_info2) {
2972 r2.in.user_handle = handle;
2973 r2.in.level = levels[i];
2974 r2.out.info = &info;
2975 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2976 "QueryUserInfo2 failed");
2977 status = r2.out.result;
2979 } else {
2980 r.in.user_handle = handle;
2981 r.in.level = levels[i];
2982 r.out.info = &info;
2983 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2984 "QueryUserInfo failed");
2985 status = r.out.result;
2988 if (!NT_STATUS_IS_OK(status) &&
2989 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2990 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo%s level %u failed - %s\n",
2991 use_info2 ? "2":"", levels[i], nt_errstr(status));
2992 return false;
2995 switch (levels[i]) {
2996 case 3:
2997 /* pwdlastset3 = info->info3.last_password_change; */
2998 break;
2999 case 5:
3000 pwdlastset5 = info->info5.last_password_change;
3001 break;
3002 case 21:
3003 pwdlastset21 = info->info21.last_password_change;
3004 break;
3005 default:
3006 return false;
3009 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
3010 "pwdlastset mixup"); */
3011 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
3012 "pwdlastset mixup");
3014 *pwdlastset = pwdlastset21;
3016 torture_comment(tctx, "(pwdlastset: %llu)\n",
3017 (unsigned long long) *pwdlastset);
3019 return true;
3022 static bool test_SamLogon(struct torture_context *tctx,
3023 struct dcerpc_pipe *p,
3024 struct cli_credentials *machine_credentials,
3025 struct cli_credentials *test_credentials,
3026 NTSTATUS expected_result,
3027 bool interactive)
3029 NTSTATUS status;
3030 struct netr_LogonSamLogonEx r;
3031 union netr_LogonLevel logon;
3032 union netr_Validation validation;
3033 uint8_t authoritative;
3034 struct netr_IdentityInfo identity;
3035 struct netr_NetworkInfo ninfo;
3036 struct netr_PasswordInfo pinfo;
3037 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
3038 int flags = CLI_CRED_NTLM_AUTH;
3039 uint32_t samlogon_flags = 0;
3040 struct netlogon_creds_CredentialState *creds;
3041 struct netr_Authenticator a;
3042 struct dcerpc_binding_handle *b = p->binding_handle;
3044 torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), "");
3046 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
3047 flags |= CLI_CRED_LANMAN_AUTH;
3050 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
3051 flags |= CLI_CRED_NTLMv2_AUTH;
3054 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
3055 &identity.account_name.string,
3056 &identity.domain_name.string);
3058 identity.parameter_control =
3059 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
3060 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
3061 identity.logon_id_low = 0;
3062 identity.logon_id_high = 0;
3063 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
3065 if (interactive) {
3066 netlogon_creds_client_authenticator(creds, &a);
3068 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
3069 ZERO_STRUCT(pinfo.lmpassword.hash);
3071 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
3073 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3074 netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
3075 netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
3076 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
3077 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
3078 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
3079 } else {
3080 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
3081 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
3084 pinfo.identity_info = identity;
3085 logon.password = &pinfo;
3087 r.in.logon_level = NetlogonInteractiveInformation;
3088 } else {
3089 generate_random_buffer(ninfo.challenge,
3090 sizeof(ninfo.challenge));
3091 chal = data_blob_const(ninfo.challenge,
3092 sizeof(ninfo.challenge));
3094 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3095 cli_credentials_get_domain(test_credentials));
3097 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3098 &flags,
3099 chal,
3100 NULL, /* server_timestamp */
3101 names_blob,
3102 &lm_resp, &nt_resp,
3103 NULL, NULL);
3104 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3106 ninfo.lm.data = lm_resp.data;
3107 ninfo.lm.length = lm_resp.length;
3109 ninfo.nt.data = nt_resp.data;
3110 ninfo.nt.length = nt_resp.length;
3112 ninfo.identity_info = identity;
3113 logon.network = &ninfo;
3115 r.in.logon_level = NetlogonNetworkInformation;
3118 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3119 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3120 r.in.logon = &logon;
3121 r.in.flags = &samlogon_flags;
3122 r.out.flags = &samlogon_flags;
3123 r.out.validation = &validation;
3124 r.out.authoritative = &authoritative;
3126 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3128 r.in.validation_level = 6;
3130 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3131 "netr_LogonSamLogonEx failed");
3132 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3133 r.in.validation_level = 3;
3134 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3135 "netr_LogonSamLogonEx failed");
3137 if (!NT_STATUS_IS_OK(r.out.result)) {
3138 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3139 return true;
3140 } else {
3141 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3144 return true;
3147 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3148 struct dcerpc_pipe *p,
3149 struct cli_credentials *machine_creds,
3150 const char *acct_name,
3151 const char *password,
3152 NTSTATUS expected_samlogon_result,
3153 bool interactive)
3155 bool ret = true;
3156 struct cli_credentials *test_credentials;
3158 test_credentials = cli_credentials_init(tctx);
3160 cli_credentials_set_workstation(test_credentials,
3161 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3162 cli_credentials_set_domain(test_credentials,
3163 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3164 cli_credentials_set_username(test_credentials,
3165 acct_name, CRED_SPECIFIED);
3166 cli_credentials_set_password(test_credentials,
3167 password, CRED_SPECIFIED);
3169 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3170 interactive ? "interactive" : "network", acct_name, password);
3172 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
3173 expected_samlogon_result, interactive)) {
3174 torture_result(tctx, TORTURE_FAIL, "new password did not work\n");
3175 ret = false;
3178 return ret;
3181 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3182 struct dcerpc_pipe *np,
3183 struct torture_context *tctx,
3184 struct policy_handle *handle,
3185 uint16_t level,
3186 uint32_t fields_present,
3187 uint8_t password_expired,
3188 bool *matched_expected_error,
3189 bool use_setinfo2,
3190 const char *acct_name,
3191 char **password,
3192 struct cli_credentials *machine_creds,
3193 bool use_queryinfo2,
3194 NTTIME *pwdlastset,
3195 NTSTATUS expected_samlogon_result)
3197 const char *fields = NULL;
3198 bool ret = true;
3199 struct dcerpc_binding_handle *b = p->binding_handle;
3201 switch (level) {
3202 case 21:
3203 case 23:
3204 case 25:
3205 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3206 fields_present);
3207 break;
3208 default:
3209 break;
3212 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3213 "(password_expired: %d) %s\n",
3214 use_setinfo2 ? "2":"", level, password_expired,
3215 fields ? fields : "");
3217 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3218 fields_present,
3219 password,
3220 password_expired,
3221 use_setinfo2,
3222 matched_expected_error)) {
3223 ret = false;
3226 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3227 use_queryinfo2,
3228 pwdlastset)) {
3229 ret = false;
3232 if (*matched_expected_error == true) {
3233 return ret;
3236 if (!test_SamLogon_with_creds(tctx, np,
3237 machine_creds,
3238 acct_name,
3239 *password,
3240 expected_samlogon_result,
3241 false)) {
3242 ret = false;
3245 return ret;
3248 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3249 struct cli_credentials *credentials,
3250 struct dcerpc_pipe **p)
3252 struct dcerpc_binding *b;
3253 NTSTATUS status;
3255 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3256 "failed to get rpc binding");
3258 /* We have to use schannel, otherwise the SamLogonEx fails
3259 * with INTERNAL_ERROR */
3261 status = dcerpc_binding_set_flags(b,
3262 DCERPC_SCHANNEL |
3263 DCERPC_SIGN | DCERPC_SEAL |
3264 DCERPC_SCHANNEL_AUTO,
3265 DCERPC_AUTH_OPTIONS);
3266 torture_assert_ntstatus_ok(tctx, status, "set flags");
3268 torture_assert_ntstatus_ok(tctx,
3269 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3270 credentials, tctx->ev, tctx->lp_ctx),
3271 "failed to bind to netlogon");
3273 return true;
3276 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3277 struct torture_context *tctx,
3278 uint32_t acct_flags,
3279 const char *acct_name,
3280 struct policy_handle *handle,
3281 char **password,
3282 struct cli_credentials *machine_credentials)
3284 int s = 0, q = 0, f = 0, l = 0, z = 0;
3285 bool ret = true;
3286 int delay = 50000;
3287 bool set_levels[] = { false, true };
3288 bool query_levels[] = { false, true };
3289 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3290 uint32_t nonzeros[] = { 1, 24 };
3291 uint32_t fields_present[] = {
3293 SAMR_FIELD_EXPIRED_FLAG,
3294 SAMR_FIELD_LAST_PWD_CHANGE,
3295 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3296 SAMR_FIELD_COMMENT,
3297 SAMR_FIELD_NT_PASSWORD_PRESENT,
3298 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3299 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3300 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3301 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3302 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3303 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3305 struct dcerpc_pipe *np = NULL;
3307 if (torture_setting_bool(tctx, "samba3", false) ||
3308 torture_setting_bool(tctx, "samba4", false)) {
3309 delay = 999999;
3310 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3311 delay);
3314 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3316 /* set to 1 to enable testing for all possible opcode
3317 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3318 combinations */
3319 #if 0
3320 #define TEST_ALL_LEVELS 1
3321 #define TEST_SET_LEVELS 1
3322 #define TEST_QUERY_LEVELS 1
3323 #endif
3324 #ifdef TEST_ALL_LEVELS
3325 for (l=0; l<ARRAY_SIZE(levels); l++) {
3326 #else
3327 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3328 #endif
3329 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3330 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3331 #ifdef TEST_SET_LEVELS
3332 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3333 #endif
3334 #ifdef TEST_QUERY_LEVELS
3335 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3336 #endif
3337 NTTIME pwdlastset_old = 0;
3338 NTTIME pwdlastset_new = 0;
3339 bool matched_expected_error = false;
3340 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3342 torture_comment(tctx, "------------------------------\n"
3343 "Testing pwdLastSet attribute for flags: 0x%08x "
3344 "(s: %d (l: %d), q: %d)\n",
3345 acct_flags, s, levels[l], q);
3347 switch (levels[l]) {
3348 case 21:
3349 case 23:
3350 case 25:
3351 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3352 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3353 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3355 break;
3359 /* set #1 */
3361 /* set a password and force password change (pwdlastset 0) by
3362 * setting the password expired flag to a non-0 value */
3364 if (!test_SetPassword_level(p, np, tctx, handle,
3365 levels[l],
3366 fields_present[f],
3367 nonzeros[z],
3368 &matched_expected_error,
3369 set_levels[s],
3370 acct_name,
3371 password,
3372 machine_credentials,
3373 query_levels[q],
3374 &pwdlastset_new,
3375 expected_samlogon_result)) {
3376 ret = false;
3379 if (matched_expected_error == true) {
3380 /* skipping on expected failure */
3381 continue;
3384 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3385 * set without the SAMR_FIELD_EXPIRED_FLAG */
3387 switch (levels[l]) {
3388 case 21:
3389 case 23:
3390 case 25:
3391 if ((pwdlastset_new != 0) &&
3392 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3393 torture_comment(tctx, "not considering a non-0 "
3394 "pwdLastSet as a an error as the "
3395 "SAMR_FIELD_EXPIRED_FLAG has not "
3396 "been set\n");
3397 break;
3399 break;
3400 default:
3401 if (pwdlastset_new != 0) {
3402 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3403 "expected pwdLastSet 0 but got %llu\n",
3404 (unsigned long long) pwdlastset_old);
3405 ret = false;
3407 break;
3410 switch (levels[l]) {
3411 case 21:
3412 case 23:
3413 case 25:
3414 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3415 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3416 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3417 (pwdlastset_old >= pwdlastset_new)) {
3418 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3419 ret = false;
3421 break;
3424 pwdlastset_old = pwdlastset_new;
3426 usleep(delay);
3428 /* set #2 */
3430 /* set a password, pwdlastset needs to get updated (increased
3431 * value), password_expired value used here is 0 */
3433 if (!test_SetPassword_level(p, np, tctx, handle,
3434 levels[l],
3435 fields_present[f],
3437 &matched_expected_error,
3438 set_levels[s],
3439 acct_name,
3440 password,
3441 machine_credentials,
3442 query_levels[q],
3443 &pwdlastset_new,
3444 expected_samlogon_result)) {
3445 ret = false;
3448 /* when a password has been changed, pwdlastset must not be 0 afterwards
3449 * and must be larger then the old value */
3451 switch (levels[l]) {
3452 case 21:
3453 case 23:
3454 case 25:
3455 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3456 * password has been changed, old and new pwdlastset
3457 * need to be the same value */
3459 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3460 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3461 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3463 torture_assert_int_equal(tctx, pwdlastset_old,
3464 pwdlastset_new, "pwdlastset must be equal");
3465 break;
3467 break;
3468 default:
3469 if (pwdlastset_old >= pwdlastset_new) {
3470 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3471 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3472 (unsigned long long) pwdlastset_old,
3473 (unsigned long long) pwdlastset_new);
3474 ret = false;
3476 if (pwdlastset_new == 0) {
3477 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3478 "expected non-0 pwdlastset, got: %llu\n",
3479 (unsigned long long) pwdlastset_new);
3480 ret = false;
3482 break;
3485 switch (levels[l]) {
3486 case 21:
3487 case 23:
3488 case 25:
3489 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3490 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3491 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3492 (pwdlastset_old >= pwdlastset_new)) {
3493 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3494 ret = false;
3496 break;
3499 pwdlastset_old = pwdlastset_new;
3501 usleep(delay);
3503 /* set #2b */
3505 /* set a password, pwdlastset needs to get updated (increased
3506 * value), password_expired value used here is 0 */
3508 if (!test_SetPassword_level(p, np, tctx, handle,
3509 levels[l],
3510 fields_present[f],
3512 &matched_expected_error,
3513 set_levels[s],
3514 acct_name,
3515 password,
3516 machine_credentials,
3517 query_levels[q],
3518 &pwdlastset_new,
3519 expected_samlogon_result)) {
3520 ret = false;
3523 /* when a password has been changed, pwdlastset must not be 0 afterwards
3524 * and must be larger then the old value */
3526 switch (levels[l]) {
3527 case 21:
3528 case 23:
3529 case 25:
3531 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3532 * password has been changed, old and new pwdlastset
3533 * need to be the same value */
3535 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3536 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3537 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3539 torture_assert_int_equal(tctx, pwdlastset_old,
3540 pwdlastset_new, "pwdlastset must be equal");
3541 break;
3543 break;
3544 default:
3545 if (pwdlastset_old >= pwdlastset_new) {
3546 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3547 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3548 (unsigned long long) pwdlastset_old,
3549 (unsigned long long) pwdlastset_new);
3550 ret = false;
3552 if (pwdlastset_new == 0) {
3553 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3554 "expected non-0 pwdlastset, got: %llu\n",
3555 (unsigned long long) pwdlastset_new);
3556 ret = false;
3558 break;
3561 switch (levels[l]) {
3562 case 21:
3563 case 23:
3564 case 25:
3565 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3566 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3567 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3568 (pwdlastset_old >= pwdlastset_new)) {
3569 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3570 ret = false;
3572 break;
3575 pwdlastset_old = pwdlastset_new;
3577 usleep(delay);
3579 /* set #3 */
3581 /* set a password and force password change (pwdlastset 0) by
3582 * setting the password expired flag to a non-0 value */
3584 if (!test_SetPassword_level(p, np, tctx, handle,
3585 levels[l],
3586 fields_present[f],
3587 nonzeros[z],
3588 &matched_expected_error,
3589 set_levels[s],
3590 acct_name,
3591 password,
3592 machine_credentials,
3593 query_levels[q],
3594 &pwdlastset_new,
3595 expected_samlogon_result)) {
3596 ret = false;
3599 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3600 * set without the SAMR_FIELD_EXPIRED_FLAG */
3602 switch (levels[l]) {
3603 case 21:
3604 case 23:
3605 case 25:
3606 if ((pwdlastset_new != 0) &&
3607 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3608 torture_comment(tctx, "not considering a non-0 "
3609 "pwdLastSet as a an error as the "
3610 "SAMR_FIELD_EXPIRED_FLAG has not "
3611 "been set\n");
3612 break;
3615 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3616 * password has been changed, old and new pwdlastset
3617 * need to be the same value */
3619 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3620 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3621 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3623 torture_assert_int_equal(tctx, pwdlastset_old,
3624 pwdlastset_new, "pwdlastset must be equal");
3625 break;
3627 break;
3628 default:
3629 if (pwdlastset_new != 0) {
3630 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3631 "expected pwdLastSet 0, got %llu\n",
3632 (unsigned long long) pwdlastset_old);
3633 ret = false;
3635 break;
3638 switch (levels[l]) {
3639 case 21:
3640 case 23:
3641 case 25:
3642 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3643 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3644 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3645 (pwdlastset_old >= pwdlastset_new)) {
3646 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3647 ret = false;
3649 break;
3652 /* if the level we are testing does not have a fields_present
3653 * field, skip all fields present tests by setting f to to
3654 * arraysize */
3655 switch (levels[l]) {
3656 case 18:
3657 case 24:
3658 case 26:
3659 f = ARRAY_SIZE(fields_present);
3660 break;
3663 #ifdef TEST_QUERY_LEVELS
3665 #endif
3666 #ifdef TEST_SET_LEVELS
3668 #endif
3669 } /* fields present */
3670 } /* nonzeros */
3671 } /* levels */
3673 #undef TEST_SET_LEVELS
3674 #undef TEST_QUERY_LEVELS
3676 talloc_free(np);
3678 return ret;
3681 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3682 struct torture_context *tctx,
3683 struct policy_handle *handle,
3684 uint32_t *badpwdcount)
3686 union samr_UserInfo *info;
3687 struct samr_QueryUserInfo r;
3689 r.in.user_handle = handle;
3690 r.in.level = 3;
3691 r.out.info = &info;
3693 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3695 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3696 "failed to query userinfo");
3697 torture_assert_ntstatus_ok(tctx, r.out.result,
3698 "failed to query userinfo");
3700 *badpwdcount = info->info3.bad_password_count;
3702 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3704 return true;
3707 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3708 struct torture_context *tctx,
3709 struct policy_handle *user_handle,
3710 uint32_t acct_flags)
3712 struct samr_SetUserInfo r;
3713 union samr_UserInfo user_info;
3715 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3717 user_info.info16.acct_flags = acct_flags;
3719 r.in.user_handle = user_handle;
3720 r.in.level = 16;
3721 r.in.info = &user_info;
3723 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3724 "failed to set account flags");
3725 torture_assert_ntstatus_ok(tctx, r.out.result,
3726 "failed to set account flags");
3728 return true;
3731 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3732 struct torture_context *tctx,
3733 struct policy_handle *user_handle,
3734 uint32_t acct_flags,
3735 char **password)
3737 struct dcerpc_binding_handle *b = p->binding_handle;
3739 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3740 "failed to set password");
3742 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3744 torture_assert(tctx,
3745 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3746 acct_flags & ~ACB_DISABLED),
3747 "failed to enable user");
3749 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3750 "failed to set password");
3752 return true;
3755 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3756 struct torture_context *tctx,
3757 struct policy_handle *domain_handle,
3758 enum samr_DomainInfoClass level,
3759 union samr_DomainInfo *info)
3761 struct samr_SetDomainInfo r;
3763 r.in.domain_handle = domain_handle;
3764 r.in.level = level;
3765 r.in.info = info;
3767 torture_assert_ntstatus_ok(tctx,
3768 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3769 "failed to set domain info");
3770 torture_assert_ntstatus_ok(tctx, r.out.result,
3771 "failed to set domain info");
3773 return true;
3776 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3777 struct torture_context *tctx,
3778 struct policy_handle *domain_handle,
3779 enum samr_DomainInfoClass level,
3780 union samr_DomainInfo *info,
3781 NTSTATUS expected)
3783 struct samr_SetDomainInfo r;
3785 r.in.domain_handle = domain_handle;
3786 r.in.level = level;
3787 r.in.info = info;
3789 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3790 "SetDomainInfo failed");
3791 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3793 return true;
3796 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3797 struct torture_context *tctx,
3798 struct policy_handle *domain_handle,
3799 enum samr_DomainInfoClass level,
3800 union samr_DomainInfo **q_info)
3802 struct samr_QueryDomainInfo2 r;
3804 r.in.domain_handle = domain_handle;
3805 r.in.level = level;
3806 r.out.info = q_info;
3808 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3809 "failed to query domain info");
3810 torture_assert_ntstatus_ok(tctx, r.out.result,
3811 "failed to query domain info");
3813 return true;
3816 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3817 struct dcerpc_pipe *np,
3818 struct torture_context *tctx,
3819 uint32_t acct_flags,
3820 const char *acct_name,
3821 struct policy_handle *domain_handle,
3822 struct policy_handle *user_handle,
3823 char **password,
3824 struct cli_credentials *machine_credentials,
3825 const char *comment,
3826 bool disable,
3827 bool interactive,
3828 NTSTATUS expected_success_status,
3829 struct samr_DomInfo1 *info1,
3830 struct samr_DomInfo12 *info12)
3832 union samr_DomainInfo info;
3833 char **passwords;
3834 int i;
3835 uint32_t badpwdcount, tmp;
3836 uint32_t password_history_length = 12;
3837 uint32_t lockout_threshold = 15;
3838 uint32_t lockout_seconds = 5;
3839 uint64_t delta_time_factor = 10 * 1000 * 1000;
3840 struct dcerpc_binding_handle *b = p->binding_handle;
3842 if (torture_setting_bool(tctx, "samba3", false)) {
3843 lockout_seconds = 60;
3846 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3848 torture_assert(tctx, password_history_length < lockout_threshold,
3849 "password history length needs to be smaller than account lockout threshold for this test");
3852 /* set policies */
3854 info.info1 = *info1;
3855 info.info1.password_history_length = password_history_length;
3856 info.info1.min_password_age = 0;
3858 torture_assert(tctx,
3859 test_SetDomainInfo(b, tctx, domain_handle,
3860 DomainPasswordInformation, &info),
3861 "failed to set password history length and min passwd age");
3863 info.info12 = *info12;
3864 info.info12.lockout_threshold = lockout_threshold;
3866 /* set lockout duration of 5 seconds */
3867 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3868 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
3870 torture_assert(tctx,
3871 test_SetDomainInfo(b, tctx, domain_handle,
3872 DomainLockoutInformation, &info),
3873 "failed to set lockout threshold");
3875 /* reset bad pwd count */
3877 torture_assert(tctx,
3878 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3881 /* enable or disable account */
3882 if (disable) {
3883 torture_assert(tctx,
3884 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3885 acct_flags | ACB_DISABLED),
3886 "failed to disable user");
3887 } else {
3888 torture_assert(tctx,
3889 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3890 acct_flags & ~ACB_DISABLED),
3891 "failed to enable user");
3895 /* setup password history */
3897 passwords = talloc_array(tctx, char *, password_history_length);
3899 for (i=0; i < password_history_length; i++) {
3901 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3902 "failed to set password");
3903 passwords[i] = talloc_strdup(tctx, *password);
3905 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3906 acct_name, passwords[i],
3907 expected_success_status, interactive)) {
3908 torture_fail(tctx, "failed to auth with latest password");
3911 torture_assert(tctx,
3912 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3914 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3918 /* test with wrong password */
3920 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3921 acct_name, "random_crap",
3922 NT_STATUS_WRONG_PASSWORD, interactive)) {
3923 torture_fail(tctx, "succeeded to authenticate with wrong password");
3926 torture_assert(tctx,
3927 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3929 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3932 /* test with latest good password */
3934 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3935 passwords[password_history_length-1],
3936 expected_success_status, interactive)) {
3937 torture_fail(tctx, "succeeded to authenticate with wrong password");
3940 torture_assert(tctx,
3941 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3943 if (disable) {
3944 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3945 } else {
3946 /* only enabled accounts get the bad pwd count reset upon
3947 * successful logon */
3948 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3951 tmp = badpwdcount;
3954 /* test password history */
3956 for (i=0; i < password_history_length; i++) {
3958 torture_comment(tctx, "Testing bad password count behavior with "
3959 "password #%d of #%d\n", i, password_history_length);
3961 /* - network samlogon will succeed auth and not
3962 * increase badpwdcount for 2 last entries
3963 * - interactive samlogon only for the last one */
3965 if (i == password_history_length - 1 ||
3966 (i == password_history_length - 2 && !interactive)) {
3968 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3969 acct_name, passwords[i],
3970 expected_success_status, interactive)) {
3971 torture_fail(tctx, talloc_asprintf(tctx, "did not successfully to obtain %s for %s login with old password (#%d of #%d in history)",
3972 nt_errstr(expected_success_status),
3973 interactive ? "interactive" : "network", i, password_history_length));
3976 torture_assert(tctx,
3977 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3979 if (disable) {
3980 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3981 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3982 } else {
3983 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3984 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3987 tmp = badpwdcount;
3989 continue;
3992 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3993 acct_name, passwords[i],
3994 NT_STATUS_WRONG_PASSWORD, interactive)) {
3995 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3998 torture_assert(tctx,
3999 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4001 /* - network samlogon will fail auth but not increase
4002 * badpwdcount for 3rd last entry
4003 * - interactive samlogon for 3rd and 2nd last entry */
4005 if (i == password_history_length - 3 ||
4006 (i == password_history_length - 2 && interactive)) {
4007 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
4008 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
4009 } else {
4010 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
4011 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
4014 tmp = badpwdcount;
4017 return true;
4020 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
4021 struct torture_context *tctx,
4022 uint32_t acct_flags,
4023 const char *acct_name,
4024 struct policy_handle *domain_handle,
4025 struct policy_handle *user_handle,
4026 char **password,
4027 struct cli_credentials *machine_credentials)
4029 union samr_DomainInfo *q_info, s_info;
4030 struct samr_DomInfo1 info1, _info1;
4031 struct samr_DomInfo12 info12, _info12;
4032 bool ret = true;
4033 struct dcerpc_binding_handle *b = p->binding_handle;
4034 struct dcerpc_pipe *np;
4035 int i;
4037 struct {
4038 const char *comment;
4039 bool disabled;
4040 bool interactive;
4041 NTSTATUS expected_success_status;
4042 } creds[] = {
4044 .comment = "network logon (disabled account)",
4045 .disabled = true,
4046 .interactive = false,
4047 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4050 .comment = "network logon (enabled account)",
4051 .disabled = false,
4052 .interactive = false,
4053 .expected_success_status= NT_STATUS_OK
4056 .comment = "interactive logon (disabled account)",
4057 .disabled = true,
4058 .interactive = true,
4059 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4062 .comment = "interactive logon (enabled account)",
4063 .disabled = false,
4064 .interactive = true,
4065 .expected_success_status= NT_STATUS_OK
4069 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4071 /* backup old policies */
4073 torture_assert(tctx,
4074 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4075 DomainPasswordInformation, &q_info),
4076 "failed to query domain info level 1");
4078 info1 = q_info->info1;
4079 _info1 = info1;
4081 torture_assert(tctx,
4082 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4083 DomainLockoutInformation, &q_info),
4084 "failed to query domain info level 12");
4086 info12 = q_info->info12;
4087 _info12 = info12;
4089 /* run tests */
4091 for (i=0; i < ARRAY_SIZE(creds); i++) {
4093 /* skip trust tests for now */
4094 if (acct_flags & ACB_WSTRUST ||
4095 acct_flags & ACB_SVRTRUST ||
4096 acct_flags & ACB_DOMTRUST) {
4097 continue;
4100 if (!test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4101 domain_handle, user_handle, password,
4102 machine_credentials,
4103 creds[i].comment,
4104 creds[i].disabled,
4105 creds[i].interactive,
4106 creds[i].expected_success_status,
4107 &_info1, &_info12)) {
4108 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4109 ret = false;
4110 } else {
4111 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4115 /* restore policies */
4117 s_info.info1 = info1;
4119 torture_assert(tctx,
4120 test_SetDomainInfo(b, tctx, domain_handle,
4121 DomainPasswordInformation, &s_info),
4122 "failed to set password information");
4124 s_info.info12 = info12;
4126 torture_assert(tctx,
4127 test_SetDomainInfo(b, tctx, domain_handle,
4128 DomainLockoutInformation, &s_info),
4129 "failed to set lockout information");
4131 return ret;
4134 static bool test_QueryUserInfo_lockout(struct dcerpc_binding_handle *b,
4135 struct torture_context *tctx,
4136 struct policy_handle *domain_handle,
4137 const char *acct_name,
4138 uint16_t raw_bad_password_count,
4139 uint16_t effective_bad_password_count,
4140 uint32_t effective_acb_lockout)
4142 struct policy_handle user_handle;
4143 union samr_UserInfo *i;
4144 struct samr_QueryUserInfo r;
4146 NTSTATUS status = test_OpenUser_byname(b, tctx, domain_handle, acct_name, &user_handle);
4147 if (!NT_STATUS_IS_OK(status)) {
4148 return false;
4151 r.in.user_handle = &user_handle;
4152 r.in.level = 3;
4153 r.out.info = &i;
4154 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4155 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4156 "failed to query userinfo");
4157 torture_assert_ntstatus_ok(tctx, r.out.result,
4158 "failed to query userinfo");
4159 torture_comment(tctx, " (acct_flags: 0x%08x) (raw_bad_pwd_count: %u)\n",
4160 i->info3.acct_flags, i->info3.bad_password_count);
4161 torture_assert_int_equal(tctx, i->info3.bad_password_count,
4162 raw_bad_password_count,
4163 "raw badpwdcount");
4164 torture_assert_int_equal(tctx, i->info3.acct_flags & ACB_AUTOLOCK,
4165 effective_acb_lockout,
4166 "effective acb_lockout");
4167 TALLOC_FREE(i);
4169 r.in.user_handle = &user_handle;
4170 r.in.level = 5;
4171 r.out.info = &i;
4172 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4173 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4174 "failed to query userinfo");
4175 torture_assert_ntstatus_ok(tctx, r.out.result,
4176 "failed to query userinfo");
4177 torture_comment(tctx, " (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
4178 i->info5.acct_flags, i->info5.bad_password_count);
4179 torture_assert_int_equal(tctx, i->info5.bad_password_count,
4180 effective_bad_password_count,
4181 "effective badpwdcount");
4182 torture_assert_int_equal(tctx, i->info5.acct_flags & ACB_AUTOLOCK,
4183 effective_acb_lockout,
4184 "effective acb_lockout");
4185 TALLOC_FREE(i);
4187 r.in.user_handle = &user_handle;
4188 r.in.level = 16;
4189 r.out.info = &i;
4190 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4191 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4192 "failed to query userinfo");
4193 torture_assert_ntstatus_ok(tctx, r.out.result,
4194 "failed to query userinfo");
4195 torture_comment(tctx, " (acct_flags: 0x%08x)\n",
4196 i->info16.acct_flags);
4197 torture_assert_int_equal(tctx, i->info16.acct_flags & ACB_AUTOLOCK,
4198 effective_acb_lockout,
4199 "effective acb_lockout");
4200 TALLOC_FREE(i);
4202 r.in.user_handle = &user_handle;
4203 r.in.level = 21;
4204 r.out.info = &i;
4205 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4206 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4207 "failed to query userinfo");
4208 torture_assert_ntstatus_ok(tctx, r.out.result,
4209 "failed to query userinfo");
4210 torture_comment(tctx, " (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
4211 i->info21.acct_flags, i->info21.bad_password_count);
4212 torture_assert_int_equal(tctx, i->info21.bad_password_count,
4213 effective_bad_password_count,
4214 "effective badpwdcount");
4215 torture_assert_int_equal(tctx, i->info21.acct_flags & ACB_AUTOLOCK,
4216 effective_acb_lockout,
4217 "effective acb_lockout");
4218 TALLOC_FREE(i);
4220 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
4221 return false;
4224 return true;
4227 static bool test_Password_lockout(struct dcerpc_pipe *p,
4228 struct dcerpc_pipe *np,
4229 struct torture_context *tctx,
4230 uint32_t acct_flags,
4231 const char *acct_name,
4232 struct policy_handle *domain_handle,
4233 struct policy_handle *user_handle,
4234 char **password,
4235 struct cli_credentials *machine_credentials,
4236 const char *comment,
4237 bool disable,
4238 bool interactive,
4239 uint32_t password_history_length,
4240 NTSTATUS expected_success_status,
4241 struct samr_DomInfo1 *info1,
4242 struct samr_DomInfo12 *info12)
4244 union samr_DomainInfo info;
4245 uint64_t lockout_threshold = 1;
4246 uint32_t lockout_seconds = 5;
4247 uint64_t delta_time_factor = 10 * 1000 * 1000;
4248 struct dcerpc_binding_handle *b = p->binding_handle;
4250 if (torture_setting_bool(tctx, "samba3", false)) {
4251 lockout_seconds = 60;
4254 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4256 /* set policies */
4258 info.info1 = *info1;
4260 torture_comment(tctx, "setting password history length to %d.\n", password_history_length);
4261 info.info1.password_history_length = password_history_length;
4263 torture_comment(tctx, "setting min password again.\n");
4264 info.info1.min_password_age = 0;
4266 torture_assert(tctx,
4267 test_SetDomainInfo(b, tctx, domain_handle,
4268 DomainPasswordInformation, &info),
4269 "failed to set password history length");
4271 info.info12 = *info12;
4272 info.info12.lockout_threshold = lockout_threshold;
4274 /* set lockout duration < lockout window: should fail */
4275 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4276 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4278 torture_assert(tctx,
4279 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4280 DomainLockoutInformation, &info,
4281 NT_STATUS_INVALID_PARAMETER),
4282 "setting lockout duration < lockout window gave unexpected result");
4284 info.info12.lockout_duration = 0;
4285 info.info12.lockout_window = 0;
4287 torture_assert(tctx,
4288 test_SetDomainInfo(b, tctx, domain_handle,
4289 DomainLockoutInformation, &info),
4290 "failed to set lockout window and duration to 0");
4293 /* set lockout duration of 5 seconds */
4294 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4295 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4297 torture_assert(tctx,
4298 test_SetDomainInfo(b, tctx, domain_handle,
4299 DomainLockoutInformation, &info),
4300 "failed to set lockout window and duration to 5 seconds");
4302 /* reset bad pwd count */
4304 torture_assert(tctx,
4305 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4308 /* enable or disable account */
4310 if (disable) {
4311 torture_assert(tctx,
4312 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4313 acct_flags | ACB_DISABLED),
4314 "failed to disable user");
4315 } else {
4316 torture_assert(tctx,
4317 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4318 acct_flags & ~ACB_DISABLED),
4319 "failed to enable user");
4323 /* test logon with right password */
4325 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4326 acct_name, *password,
4327 expected_success_status, interactive)) {
4328 torture_fail(tctx, "failed to auth with latest password");
4331 torture_assert(tctx,
4332 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4333 0, 0, 0),
4334 "expected account to not be locked");
4336 /* test with wrong password ==> lockout */
4338 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4339 acct_name, "random_crap",
4340 NT_STATUS_WRONG_PASSWORD, interactive)) {
4341 torture_fail(tctx, "succeeded to authenticate with wrong password");
4345 * curiously, windows does _not_ return fresh values of
4346 * effective bad_password_count and ACB_AUTOLOCK.
4348 torture_assert(tctx,
4349 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4350 1, 1, ACB_AUTOLOCK),
4351 "expected account to not be locked");
4353 /* test with good password */
4355 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4356 *password,
4357 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4359 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4362 /* bad pwd count should not get updated */
4363 torture_assert(tctx,
4364 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4365 1, 1, ACB_AUTOLOCK),
4366 "expected account to be locked");
4368 torture_assert(tctx,
4369 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password,
4370 NT_STATUS_ACCOUNT_LOCKED_OUT),
4371 "got wrong status from ChangePasswordUser2");
4373 /* bad pwd count should not get updated */
4374 torture_assert(tctx,
4375 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4376 1, 1, ACB_AUTOLOCK),
4377 "expected account to be locked");
4379 torture_assert(tctx,
4380 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
4381 "got wrong status from ChangePasswordUser2");
4383 /* bad pwd count should not get updated */
4384 torture_assert(tctx,
4385 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4386 1, 1, ACB_AUTOLOCK),
4387 "expected account to be locked");
4389 /* with bad password */
4391 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4392 acct_name, "random_crap2",
4393 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4395 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4398 /* bad pwd count should not get updated */
4399 torture_assert(tctx,
4400 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4401 1, 1, ACB_AUTOLOCK),
4402 "expected account to be locked");
4404 /* let lockout duration expire ==> unlock */
4406 torture_comment(tctx, "let lockout duration expire...\n");
4407 sleep(lockout_seconds + 1);
4409 torture_assert(tctx,
4410 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4411 1, 0, 0),
4412 "expected account to not be locked");
4414 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4415 *password,
4416 expected_success_status, interactive))
4418 torture_fail(tctx, "failed to authenticate after lockout expired");
4421 if (NT_STATUS_IS_OK(expected_success_status)) {
4422 torture_assert(tctx,
4423 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4424 0, 0, 0),
4425 "expected account to not be locked");
4426 } else {
4427 torture_assert(tctx,
4428 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4429 1, 0, 0),
4430 "expected account to not be locked");
4433 torture_assert(tctx,
4434 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4435 "got wrong status from ChangePasswordUser2");
4437 torture_assert(tctx,
4438 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4439 1, 1, ACB_AUTOLOCK),
4440 "expected account to be locked");
4442 torture_assert(tctx,
4443 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
4444 "got wrong status from ChangePasswordUser2");
4446 torture_assert(tctx,
4447 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4448 1, 1, ACB_AUTOLOCK),
4449 "expected account to be locked");
4451 torture_assert(tctx,
4452 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
4453 "got wrong status from ChangePasswordUser2");
4455 torture_assert(tctx,
4456 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4457 1, 1, ACB_AUTOLOCK),
4458 "expected account to be locked");
4460 /* let lockout duration expire ==> unlock */
4462 torture_comment(tctx, "let lockout duration expire...\n");
4463 sleep(lockout_seconds + 1);
4465 torture_assert(tctx,
4466 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4467 1, 0, 0),
4468 "expected account to not be locked");
4470 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4471 *password,
4472 expected_success_status, interactive))
4474 torture_fail(tctx, "failed to authenticate after lockout expired");
4477 if (NT_STATUS_IS_OK(expected_success_status)) {
4478 torture_assert(tctx,
4479 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4480 0, 0, 0),
4481 "expected account to not be locked");
4482 } else {
4483 torture_assert(tctx,
4484 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4485 1, 0, 0),
4486 "expected account to not be locked");
4489 /* Testing ChangePasswordUser behaviour with 3 attempts */
4490 info.info12.lockout_threshold = 3;
4492 torture_assert(tctx,
4493 test_SetDomainInfo(b, tctx, domain_handle,
4494 DomainLockoutInformation, &info),
4495 "failed to set lockout threshold to 3");
4497 if (NT_STATUS_IS_OK(expected_success_status)) {
4498 torture_assert(tctx,
4499 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4500 0, 0, 0),
4501 "expected account to not be locked");
4502 } else {
4503 torture_assert(tctx,
4504 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4505 1, 0, 0),
4506 "expected account to not be locked");
4509 torture_assert(tctx,
4510 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4511 "got wrong status from ChangePasswordUser2");
4513 /* bad pwd count will get updated */
4514 torture_assert(tctx,
4515 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4516 1, 1, 0),
4517 "expected account to not be locked");
4519 torture_assert(tctx,
4520 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4521 "got wrong status from ChangePasswordUser2");
4523 /* bad pwd count will get updated */
4524 torture_assert(tctx,
4525 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4526 2, 2, 0),
4527 "expected account to not be locked");
4529 torture_assert(tctx,
4530 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
4531 "got wrong status from ChangePasswordUser2");
4533 /* bad pwd count should get updated */
4534 torture_assert(tctx,
4535 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4536 3, 3, ACB_AUTOLOCK),
4537 "expected account to be locked");
4539 torture_assert(tctx,
4540 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
4541 "got wrong status from ChangePasswordUser2");
4543 /* bad pwd count should not get updated */
4544 torture_assert(tctx,
4545 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4546 3, 3, ACB_AUTOLOCK),
4547 "expected account to be locked");
4549 /* let lockout duration expire ==> unlock */
4551 torture_comment(tctx, "let lockout duration expire...\n");
4552 sleep(lockout_seconds + 1);
4554 torture_assert(tctx,
4555 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4556 3, 0, 0),
4557 "expected account to not be locked");
4559 torture_assert(tctx,
4560 test_ChangePasswordUser2(p, tctx, acct_name, password, NULL, false),
4561 "got wrong status from ChangePasswordUser2");
4563 torture_assert(tctx,
4564 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4565 3, 0, 0),
4566 "expected account to not be locked");
4568 /* Used to reset the badPwdCount for the other tests */
4569 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4570 *password,
4571 expected_success_status, interactive))
4573 torture_fail(tctx, "failed to authenticate after lockout expired");
4576 if (NT_STATUS_IS_OK(expected_success_status)) {
4577 torture_assert(tctx,
4578 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4579 0, 0, 0),
4580 "expected account to not be locked");
4581 } else {
4582 torture_assert(tctx,
4583 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4584 3, 0, 0),
4585 "expected account to not be locked");
4588 return true;
4591 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4592 struct torture_context *tctx,
4593 uint32_t acct_flags,
4594 const char *acct_name,
4595 struct policy_handle *domain_handle,
4596 struct policy_handle *user_handle,
4597 char **password,
4598 struct cli_credentials *machine_credentials)
4600 union samr_DomainInfo *q_info, s_info;
4601 struct samr_DomInfo1 info1, _info1;
4602 struct samr_DomInfo12 info12, _info12;
4603 bool ret = true;
4604 struct dcerpc_binding_handle *b = p->binding_handle;
4605 struct dcerpc_pipe *np;
4606 int i;
4608 struct {
4609 const char *comment;
4610 bool disabled;
4611 bool interactive;
4612 uint32_t password_history_length;
4613 NTSTATUS expected_success_status;
4614 } creds[] = {
4616 .comment = "network logon (disabled account)",
4617 .disabled = true,
4618 .interactive = false,
4619 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4622 .comment = "network logon (enabled account)",
4623 .disabled = false,
4624 .interactive = false,
4625 .expected_success_status= NT_STATUS_OK
4628 .comment = "network logon (enabled account, history len = 1)",
4629 .disabled = false,
4630 .interactive = false,
4631 .expected_success_status= NT_STATUS_OK,
4632 .password_history_length = 1
4635 .comment = "interactive logon (disabled account)",
4636 .disabled = true,
4637 .interactive = true,
4638 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4641 .comment = "interactive logon (enabled account)",
4642 .disabled = false,
4643 .interactive = true,
4644 .expected_success_status= NT_STATUS_OK
4647 .comment = "interactive logon (enabled account, history len = 1)",
4648 .disabled = false,
4649 .interactive = true,
4650 .expected_success_status= NT_STATUS_OK,
4651 .password_history_length = 1
4655 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4657 /* backup old policies */
4659 torture_assert(tctx,
4660 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4661 DomainPasswordInformation, &q_info),
4662 "failed to query domain info level 1");
4664 info1 = q_info->info1;
4665 _info1 = info1;
4667 torture_assert(tctx,
4668 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4669 DomainLockoutInformation, &q_info),
4670 "failed to query domain info level 12");
4672 info12 = q_info->info12;
4673 _info12 = info12;
4675 /* run tests */
4677 for (i=0; i < ARRAY_SIZE(creds); i++) {
4678 bool test_passed;
4679 /* skip trust tests for now */
4680 if (acct_flags & ACB_WSTRUST ||
4681 acct_flags & ACB_SVRTRUST ||
4682 acct_flags & ACB_DOMTRUST) {
4683 continue;
4686 test_passed = test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4687 domain_handle, user_handle, password,
4688 machine_credentials,
4689 creds[i].comment,
4690 creds[i].disabled,
4691 creds[i].interactive,
4692 creds[i].password_history_length,
4693 creds[i].expected_success_status,
4694 &_info1, &_info12);
4695 ret &= test_passed;
4696 if (!test_passed) {
4697 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4698 break;
4699 } else {
4700 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4704 /* restore policies */
4706 s_info.info1 = info1;
4708 torture_assert(tctx,
4709 test_SetDomainInfo(b, tctx, domain_handle,
4710 DomainPasswordInformation, &s_info),
4711 "failed to set password information");
4713 s_info.info12 = info12;
4715 torture_assert(tctx,
4716 test_SetDomainInfo(b, tctx, domain_handle,
4717 DomainLockoutInformation, &s_info),
4718 "failed to set lockout information");
4720 return ret;
4723 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4724 struct dcerpc_pipe *lp,
4725 struct torture_context *tctx,
4726 struct policy_handle *domain_handle,
4727 struct policy_handle *lsa_handle,
4728 struct policy_handle *user_handle,
4729 const struct dom_sid *domain_sid,
4730 uint32_t rid,
4731 struct cli_credentials *machine_credentials)
4733 bool ret = true;
4734 struct dcerpc_binding_handle *b = p->binding_handle;
4735 struct dcerpc_binding_handle *lb = lp->binding_handle;
4737 struct policy_handle lsa_acct_handle;
4738 struct dom_sid *user_sid;
4740 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4743 struct lsa_EnumAccountRights r;
4744 struct lsa_RightSet rights;
4746 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4748 r.in.handle = lsa_handle;
4749 r.in.sid = user_sid;
4750 r.out.rights = &rights;
4752 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4753 "lsa_EnumAccountRights failed");
4754 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4755 "Expected enum rights for account to fail");
4759 struct lsa_RightSet rights;
4760 struct lsa_StringLarge names[2];
4761 struct lsa_AddAccountRights r;
4763 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4765 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4766 init_lsa_StringLarge(&names[1], NULL);
4768 rights.count = 1;
4769 rights.names = names;
4771 r.in.handle = lsa_handle;
4772 r.in.sid = user_sid;
4773 r.in.rights = &rights;
4775 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4776 "lsa_AddAccountRights failed");
4777 torture_assert_ntstatus_ok(tctx, r.out.result,
4778 "Failed to add privileges");
4782 struct lsa_RightSet rights;
4783 struct lsa_StringLarge names[2];
4784 struct lsa_AddAccountRights r;
4786 torture_comment(tctx, "Testing LSA AddAccountRights 1\n");
4788 init_lsa_StringLarge(&names[0], "SeInteractiveLogonRight");
4789 init_lsa_StringLarge(&names[1], NULL);
4791 rights.count = 1;
4792 rights.names = names;
4794 r.in.handle = lsa_handle;
4795 r.in.sid = user_sid;
4796 r.in.rights = &rights;
4798 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4799 "lsa_AddAccountRights 1 failed");
4801 if (torture_setting_bool(tctx, "nt4_dc", false)) {
4803 * The NT4 DC doesn't implement Rights.
4805 torture_assert_ntstatus_equal(tctx, r.out.result,
4806 NT_STATUS_NO_SUCH_PRIVILEGE,
4807 "Add rights failed with incorrect error");
4808 } else {
4809 torture_assert_ntstatus_ok(tctx, r.out.result,
4810 "Failed to add rights");
4817 struct lsa_EnumAccounts r;
4818 uint32_t resume_handle = 0;
4819 struct lsa_SidArray lsa_sid_array;
4820 int i;
4821 bool found_sid = false;
4823 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4825 r.in.handle = lsa_handle;
4826 r.in.num_entries = 0x1000;
4827 r.in.resume_handle = &resume_handle;
4828 r.out.sids = &lsa_sid_array;
4829 r.out.resume_handle = &resume_handle;
4831 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4832 "lsa_EnumAccounts failed");
4833 torture_assert_ntstatus_ok(tctx, r.out.result,
4834 "Failed to enum accounts");
4836 for (i=0; i < lsa_sid_array.num_sids; i++) {
4837 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4838 found_sid = true;
4842 torture_assert(tctx, found_sid,
4843 "failed to list privileged account");
4847 struct lsa_EnumAccountRights r;
4848 struct lsa_RightSet user_rights;
4849 uint32_t expected_count = 2;
4851 if (torture_setting_bool(tctx, "nt4_dc", false)) {
4853 * NT4 DC doesn't store rights.
4855 expected_count = 1;
4858 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4860 r.in.handle = lsa_handle;
4861 r.in.sid = user_sid;
4862 r.out.rights = &user_rights;
4864 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4865 "lsa_EnumAccountRights failed");
4866 torture_assert_ntstatus_ok(tctx, r.out.result,
4867 "Failed to enum rights for account");
4869 if (user_rights.count < expected_count) {
4870 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4871 return false;
4876 struct lsa_OpenAccount r;
4878 torture_comment(tctx, "Testing LSA OpenAccount\n");
4880 r.in.handle = lsa_handle;
4881 r.in.sid = user_sid;
4882 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4883 r.out.acct_handle = &lsa_acct_handle;
4885 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4886 "lsa_OpenAccount failed");
4887 torture_assert_ntstatus_ok(tctx, r.out.result,
4888 "Failed to open lsa account");
4892 struct lsa_GetSystemAccessAccount r;
4893 uint32_t access_mask;
4895 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4897 r.in.handle = &lsa_acct_handle;
4898 r.out.access_mask = &access_mask;
4900 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4901 "lsa_GetSystemAccessAccount failed");
4902 torture_assert_ntstatus_ok(tctx, r.out.result,
4903 "Failed to get lsa system access account");
4907 struct lsa_Close r;
4909 torture_comment(tctx, "Testing LSA Close\n");
4911 r.in.handle = &lsa_acct_handle;
4912 r.out.handle = &lsa_acct_handle;
4914 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4915 "lsa_Close failed");
4916 torture_assert_ntstatus_ok(tctx, r.out.result,
4917 "Failed to close lsa");
4921 struct samr_DeleteUser r;
4923 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4925 r.in.user_handle = user_handle;
4926 r.out.user_handle = user_handle;
4928 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4929 "DeleteUser failed");
4930 torture_assert_ntstatus_ok(tctx, r.out.result,
4931 "DeleteUser failed");
4935 struct lsa_EnumAccounts r;
4936 uint32_t resume_handle = 0;
4937 struct lsa_SidArray lsa_sid_array;
4938 int i;
4939 bool found_sid = false;
4941 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4943 r.in.handle = lsa_handle;
4944 r.in.num_entries = 0x1000;
4945 r.in.resume_handle = &resume_handle;
4946 r.out.sids = &lsa_sid_array;
4947 r.out.resume_handle = &resume_handle;
4949 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4950 "lsa_EnumAccounts failed");
4951 torture_assert_ntstatus_ok(tctx, r.out.result,
4952 "Failed to enum accounts");
4954 for (i=0; i < lsa_sid_array.num_sids; i++) {
4955 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4956 found_sid = true;
4960 torture_assert(tctx, found_sid,
4961 "failed to list privileged account");
4965 struct lsa_EnumAccountRights r;
4966 struct lsa_RightSet user_rights;
4968 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4970 r.in.handle = lsa_handle;
4971 r.in.sid = user_sid;
4972 r.out.rights = &user_rights;
4974 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4975 "lsa_EnumAccountRights failed");
4976 torture_assert_ntstatus_ok(tctx, r.out.result,
4977 "Failed to enum rights for account");
4979 if (user_rights.count < 1) {
4980 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
4981 return false;
4986 struct lsa_OpenAccount r;
4988 torture_comment(tctx, "Testing LSA OpenAccount\n");
4990 r.in.handle = lsa_handle;
4991 r.in.sid = user_sid;
4992 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4993 r.out.acct_handle = &lsa_acct_handle;
4995 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4996 "lsa_OpenAccount failed");
4997 torture_assert_ntstatus_ok(tctx, r.out.result,
4998 "Failed to open lsa account");
5002 struct lsa_GetSystemAccessAccount r;
5003 uint32_t access_mask;
5005 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
5007 r.in.handle = &lsa_acct_handle;
5008 r.out.access_mask = &access_mask;
5010 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
5011 "lsa_GetSystemAccessAccount failed");
5012 torture_assert_ntstatus_ok(tctx, r.out.result,
5013 "Failed to get lsa system access account");
5017 struct lsa_DeleteObject r;
5019 torture_comment(tctx, "Testing LSA DeleteObject\n");
5021 r.in.handle = &lsa_acct_handle;
5022 r.out.handle = &lsa_acct_handle;
5024 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
5025 "lsa_DeleteObject failed");
5026 torture_assert_ntstatus_ok(tctx, r.out.result,
5027 "Failed to delete object");
5031 struct lsa_EnumAccounts r;
5032 uint32_t resume_handle = 0;
5033 struct lsa_SidArray lsa_sid_array;
5034 int i;
5035 bool found_sid = false;
5037 torture_comment(tctx, "Testing LSA EnumAccounts\n");
5039 r.in.handle = lsa_handle;
5040 r.in.num_entries = 0x1000;
5041 r.in.resume_handle = &resume_handle;
5042 r.out.sids = &lsa_sid_array;
5043 r.out.resume_handle = &resume_handle;
5045 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
5046 "lsa_EnumAccounts failed");
5047 torture_assert_ntstatus_ok(tctx, r.out.result,
5048 "Failed to enum accounts");
5050 for (i=0; i < lsa_sid_array.num_sids; i++) {
5051 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
5052 found_sid = true;
5056 torture_assert(tctx, !found_sid,
5057 "should not have listed privileged account");
5061 struct lsa_EnumAccountRights r;
5062 struct lsa_RightSet user_rights;
5064 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
5066 r.in.handle = lsa_handle;
5067 r.in.sid = user_sid;
5068 r.out.rights = &user_rights;
5070 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
5071 "lsa_EnumAccountRights failed");
5072 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
5073 "Failed to enum rights for account");
5076 return ret;
5079 static bool test_user_ops(struct dcerpc_pipe *p,
5080 struct torture_context *tctx,
5081 struct policy_handle *user_handle,
5082 struct policy_handle *domain_handle,
5083 const struct dom_sid *domain_sid,
5084 uint32_t base_acct_flags,
5085 const char *base_acct_name, enum torture_samr_choice which_ops,
5086 struct cli_credentials *machine_credentials)
5088 char *password = NULL;
5089 struct samr_QueryUserInfo q;
5090 union samr_UserInfo *info;
5091 NTSTATUS status;
5092 struct dcerpc_binding_handle *b = p->binding_handle;
5094 bool ret = true;
5095 int i;
5096 uint32_t rid;
5097 const uint32_t password_fields[] = {
5098 SAMR_FIELD_NT_PASSWORD_PRESENT,
5099 SAMR_FIELD_LM_PASSWORD_PRESENT,
5100 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
5104 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
5105 if (!NT_STATUS_IS_OK(status)) {
5106 ret = false;
5109 switch (which_ops) {
5110 case TORTURE_SAMR_USER_ATTRIBUTES:
5111 if (!test_QuerySecurity(b, tctx, user_handle)) {
5112 ret = false;
5115 if (!test_QueryUserInfo(b, tctx, user_handle)) {
5116 ret = false;
5119 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
5120 ret = false;
5123 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
5124 base_acct_name)) {
5125 ret = false;
5128 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
5129 ret = false;
5132 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
5133 ret = false;
5136 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
5137 ret = false;
5139 break;
5140 case TORTURE_SAMR_PASSWORDS:
5141 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
5142 char simple_pass[9];
5143 char *v = generate_random_str(tctx, 1);
5145 ZERO_STRUCT(simple_pass);
5146 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5148 torture_comment(tctx, "Testing machine account password policy rules\n");
5150 /* Workstation trust accounts don't seem to need to honour password quality policy */
5151 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
5152 ret = false;
5155 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
5156 ret = false;
5159 /* reset again, to allow another 'user' password change */
5160 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
5161 ret = false;
5164 /* Try a 'short' password */
5165 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
5166 ret = false;
5169 /* Try a compleatly random password */
5170 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
5171 ret = false;
5175 for (i = 0; password_fields[i]; i++) {
5176 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
5177 ret = false;
5180 /* check it was set right */
5181 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5182 ret = false;
5186 for (i = 0; password_fields[i]; i++) {
5187 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
5188 ret = false;
5191 /* check it was set right */
5192 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5193 ret = false;
5197 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
5198 ret = false;
5201 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
5202 ret = false;
5205 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
5206 ret = false;
5209 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5210 ret = false;
5213 for (i = 0; password_fields[i]; i++) {
5215 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
5216 /* we need to skip as that would break
5217 * the ChangePasswordUser3 verify */
5218 continue;
5221 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
5222 ret = false;
5225 /* check it was set right */
5226 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5227 ret = false;
5231 q.in.user_handle = user_handle;
5232 q.in.level = 5;
5233 q.out.info = &info;
5235 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5236 "QueryUserInfo failed");
5237 if (!NT_STATUS_IS_OK(q.out.result)) {
5238 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5239 q.in.level, nt_errstr(q.out.result));
5240 ret = false;
5241 } else {
5242 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5243 if ((info->info5.acct_flags) != expected_flags) {
5244 /* FIXME: GD */
5245 if (!torture_setting_bool(tctx, "samba3", false)) {
5246 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5247 info->info5.acct_flags,
5248 expected_flags);
5249 ret = false;
5252 if (info->info5.rid != rid) {
5253 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
5254 info->info5.rid, rid);
5259 break;
5261 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
5263 /* test last password change timestamp behaviour */
5264 torture_assert(tctx, test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
5265 base_acct_name,
5266 user_handle, &password,
5267 machine_credentials),
5268 "pwdLastSet test failed\n");
5269 break;
5271 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
5273 /* test bad pwd count change behaviour */
5274 torture_assert(tctx, test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
5275 base_acct_name,
5276 domain_handle,
5277 user_handle, &password,
5278 machine_credentials),
5279 "badPwdCount test failed\n");
5280 break;
5282 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
5284 torture_assert(tctx, test_Password_lockout_wrap(p, tctx, base_acct_flags,
5285 base_acct_name,
5286 domain_handle,
5287 user_handle, &password,
5288 machine_credentials),
5289 "Lockout test failed");
5290 break;
5293 case TORTURE_SAMR_USER_PRIVILEGES: {
5295 struct dcerpc_pipe *lp;
5296 struct policy_handle *lsa_handle;
5297 struct dcerpc_binding_handle *lb;
5299 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
5300 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
5301 lb = lp->binding_handle;
5303 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
5304 ret = false;
5307 if (!test_DeleteUser_with_privs(p, lp, tctx,
5308 domain_handle, lsa_handle, user_handle,
5309 domain_sid, rid,
5310 machine_credentials)) {
5311 ret = false;
5314 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
5315 ret = false;
5318 if (!ret) {
5319 torture_result(tctx, TORTURE_FAIL, "privileged user delete test failed\n");
5322 break;
5324 case TORTURE_SAMR_OTHER:
5325 case TORTURE_SAMR_MANY_ACCOUNTS:
5326 case TORTURE_SAMR_MANY_GROUPS:
5327 case TORTURE_SAMR_MANY_ALIASES:
5328 /* We just need the account to exist */
5329 break;
5331 return ret;
5334 static bool test_alias_ops(struct dcerpc_binding_handle *b,
5335 struct torture_context *tctx,
5336 struct policy_handle *alias_handle,
5337 const struct dom_sid *domain_sid)
5339 bool ret = true;
5341 if (!torture_setting_bool(tctx, "samba3", false)) {
5342 if (!test_QuerySecurity(b, tctx, alias_handle)) {
5343 ret = false;
5347 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
5348 ret = false;
5351 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
5352 ret = false;
5355 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
5356 ret = false;
5359 if (torture_setting_bool(tctx, "samba3", false) ||
5360 torture_setting_bool(tctx, "samba4", false)) {
5361 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
5362 return ret;
5365 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
5366 ret = false;
5369 return ret;
5373 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
5374 struct torture_context *tctx,
5375 struct policy_handle *user_handle)
5377 struct samr_DeleteUser d;
5378 torture_comment(tctx, "Testing DeleteUser\n");
5380 d.in.user_handle = user_handle;
5381 d.out.user_handle = user_handle;
5383 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5384 "DeleteUser failed");
5385 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5387 return true;
5390 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5391 struct torture_context *tctx,
5392 struct policy_handle *handle, const char *name)
5394 NTSTATUS status;
5395 struct samr_DeleteUser d;
5396 struct policy_handle user_handle;
5397 uint32_t rid;
5399 status = test_LookupName(b, tctx, handle, name, &rid);
5400 if (!NT_STATUS_IS_OK(status)) {
5401 goto failed;
5404 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5405 if (!NT_STATUS_IS_OK(status)) {
5406 goto failed;
5409 d.in.user_handle = &user_handle;
5410 d.out.user_handle = &user_handle;
5411 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5412 "DeleteUser failed");
5413 if (!NT_STATUS_IS_OK(d.out.result)) {
5414 status = d.out.result;
5415 goto failed;
5418 return true;
5420 failed:
5421 torture_result(tctx, TORTURE_FAIL, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
5422 return false;
5426 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
5427 struct torture_context *tctx,
5428 struct policy_handle *handle, const char *name)
5430 NTSTATUS status;
5431 struct samr_OpenGroup r;
5432 struct samr_DeleteDomainGroup d;
5433 struct policy_handle group_handle;
5434 uint32_t rid;
5436 status = test_LookupName(b, tctx, handle, name, &rid);
5437 if (!NT_STATUS_IS_OK(status)) {
5438 goto failed;
5441 r.in.domain_handle = handle;
5442 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5443 r.in.rid = rid;
5444 r.out.group_handle = &group_handle;
5445 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5446 "OpenGroup failed");
5447 if (!NT_STATUS_IS_OK(r.out.result)) {
5448 status = r.out.result;
5449 goto failed;
5452 d.in.group_handle = &group_handle;
5453 d.out.group_handle = &group_handle;
5454 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
5455 "DeleteDomainGroup 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, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
5465 return false;
5469 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
5470 struct torture_context *tctx,
5471 struct policy_handle *domain_handle,
5472 const char *name)
5474 NTSTATUS status;
5475 struct samr_OpenAlias r;
5476 struct samr_DeleteDomAlias d;
5477 struct policy_handle alias_handle;
5478 uint32_t rid;
5480 torture_comment(tctx, "Testing DeleteAlias_byname\n");
5482 status = test_LookupName(b, tctx, domain_handle, name, &rid);
5483 if (!NT_STATUS_IS_OK(status)) {
5484 goto failed;
5487 r.in.domain_handle = domain_handle;
5488 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5489 r.in.rid = rid;
5490 r.out.alias_handle = &alias_handle;
5491 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5492 "OpenAlias failed");
5493 if (!NT_STATUS_IS_OK(r.out.result)) {
5494 status = r.out.result;
5495 goto failed;
5498 d.in.alias_handle = &alias_handle;
5499 d.out.alias_handle = &alias_handle;
5500 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5501 "DeleteDomAlias failed");
5502 if (!NT_STATUS_IS_OK(d.out.result)) {
5503 status = d.out.result;
5504 goto failed;
5507 return true;
5509 failed:
5510 torture_result(tctx, TORTURE_FAIL, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5511 return false;
5514 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5515 struct torture_context *tctx,
5516 struct policy_handle *alias_handle)
5518 struct samr_DeleteDomAlias d;
5519 bool ret = true;
5521 torture_comment(tctx, "Testing DeleteAlias\n");
5523 d.in.alias_handle = alias_handle;
5524 d.out.alias_handle = alias_handle;
5526 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5527 "DeleteDomAlias failed");
5528 if (!NT_STATUS_IS_OK(d.out.result)) {
5529 torture_result(tctx, TORTURE_FAIL, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5530 ret = false;
5533 return ret;
5536 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5537 struct torture_context *tctx,
5538 struct policy_handle *domain_handle,
5539 const char *alias_name,
5540 struct policy_handle *alias_handle,
5541 const struct dom_sid *domain_sid,
5542 bool test_alias)
5544 struct samr_CreateDomAlias r;
5545 struct lsa_String name;
5546 uint32_t rid;
5547 bool ret = true;
5549 init_lsa_String(&name, alias_name);
5550 r.in.domain_handle = domain_handle;
5551 r.in.alias_name = &name;
5552 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5553 r.out.alias_handle = alias_handle;
5554 r.out.rid = &rid;
5556 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5558 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5559 "CreateDomAlias failed");
5561 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5562 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5563 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5564 return true;
5565 } else {
5566 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5567 nt_errstr(r.out.result));
5568 return false;
5572 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5573 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5574 return false;
5576 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5577 "CreateDomAlias failed");
5580 if (!NT_STATUS_IS_OK(r.out.result)) {
5581 torture_result(tctx, TORTURE_FAIL, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5582 return false;
5585 if (!test_alias) {
5586 return ret;
5589 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5590 ret = false;
5593 return ret;
5596 static bool test_ChangePassword(struct dcerpc_pipe *p,
5597 struct torture_context *tctx,
5598 const char *acct_name,
5599 struct policy_handle *domain_handle, char **password)
5601 bool ret = true;
5602 struct dcerpc_binding_handle *b = p->binding_handle;
5604 if (!*password) {
5605 return false;
5608 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5609 ret = false;
5612 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5613 ret = false;
5616 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5617 ret = false;
5620 /* test what happens when setting the old password again */
5621 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5622 ret = false;
5626 char simple_pass[9];
5627 char *v = generate_random_str(tctx, 1);
5629 ZERO_STRUCT(simple_pass);
5630 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5632 /* test what happens when picking a simple password */
5633 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5634 ret = false;
5638 /* set samr_SetDomainInfo level 1 with min_length 5 */
5640 struct samr_QueryDomainInfo r;
5641 union samr_DomainInfo *info = NULL;
5642 struct samr_SetDomainInfo s;
5643 uint16_t len_old, len;
5644 uint32_t pwd_prop_old;
5645 int64_t min_pwd_age_old;
5647 len = 5;
5649 r.in.domain_handle = domain_handle;
5650 r.in.level = 1;
5651 r.out.info = &info;
5653 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5654 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5655 "QueryDomainInfo failed");
5656 if (!NT_STATUS_IS_OK(r.out.result)) {
5657 return false;
5660 s.in.domain_handle = domain_handle;
5661 s.in.level = 1;
5662 s.in.info = info;
5664 /* remember the old min length, so we can reset it */
5665 len_old = s.in.info->info1.min_password_length;
5666 s.in.info->info1.min_password_length = len;
5667 pwd_prop_old = s.in.info->info1.password_properties;
5668 /* turn off password complexity checks for this test */
5669 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5671 min_pwd_age_old = s.in.info->info1.min_password_age;
5672 s.in.info->info1.min_password_age = 0;
5674 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5675 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5676 "SetDomainInfo failed");
5677 if (!NT_STATUS_IS_OK(s.out.result)) {
5678 return false;
5681 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5683 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5684 ret = false;
5687 s.in.info->info1.min_password_length = len_old;
5688 s.in.info->info1.password_properties = pwd_prop_old;
5689 s.in.info->info1.min_password_age = min_pwd_age_old;
5691 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5692 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5693 "SetDomainInfo failed");
5694 if (!NT_STATUS_IS_OK(s.out.result)) {
5695 return false;
5701 struct samr_OpenUser r;
5702 struct samr_QueryUserInfo q;
5703 union samr_UserInfo *info;
5704 struct samr_LookupNames n;
5705 struct policy_handle user_handle;
5706 struct samr_Ids rids, types;
5708 n.in.domain_handle = domain_handle;
5709 n.in.num_names = 1;
5710 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5711 n.in.names[0].string = acct_name;
5712 n.out.rids = &rids;
5713 n.out.types = &types;
5715 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5716 "LookupNames failed");
5717 if (!NT_STATUS_IS_OK(n.out.result)) {
5718 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5719 return false;
5722 r.in.domain_handle = domain_handle;
5723 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5724 r.in.rid = n.out.rids->ids[0];
5725 r.out.user_handle = &user_handle;
5727 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5728 "OpenUser failed");
5729 if (!NT_STATUS_IS_OK(r.out.result)) {
5730 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5731 return false;
5734 q.in.user_handle = &user_handle;
5735 q.in.level = 5;
5736 q.out.info = &info;
5738 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5739 "QueryUserInfo failed");
5740 if (!NT_STATUS_IS_OK(q.out.result)) {
5741 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5742 return false;
5745 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5747 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5748 info->info5.last_password_change, true)) {
5749 ret = false;
5753 /* we change passwords twice - this has the effect of verifying
5754 they were changed correctly for the final call */
5755 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5756 ret = false;
5759 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5760 ret = false;
5763 return ret;
5766 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5767 struct policy_handle *domain_handle,
5768 const char *user_name,
5769 struct policy_handle *user_handle_out,
5770 struct dom_sid *domain_sid,
5771 enum torture_samr_choice which_ops,
5772 struct cli_credentials *machine_credentials,
5773 bool test_user)
5776 TALLOC_CTX *user_ctx;
5778 struct samr_CreateUser r;
5779 struct samr_QueryUserInfo q;
5780 union samr_UserInfo *info;
5781 struct samr_DeleteUser d;
5782 uint32_t rid;
5784 /* This call creates a 'normal' account - check that it really does */
5785 const uint32_t acct_flags = ACB_NORMAL;
5786 struct lsa_String name;
5787 bool ret = true;
5788 struct dcerpc_binding_handle *b = p->binding_handle;
5790 struct policy_handle user_handle;
5791 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5792 init_lsa_String(&name, user_name);
5794 r.in.domain_handle = domain_handle;
5795 r.in.account_name = &name;
5796 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5797 r.out.user_handle = &user_handle;
5798 r.out.rid = &rid;
5800 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5802 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5803 "CreateUser failed");
5805 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5806 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5807 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5808 return true;
5809 } else {
5810 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5811 nt_errstr(r.out.result));
5812 return false;
5816 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5817 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5818 talloc_free(user_ctx);
5819 return false;
5821 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5822 "CreateUser failed");
5825 if (!NT_STATUS_IS_OK(r.out.result)) {
5826 talloc_free(user_ctx);
5827 torture_result(tctx, TORTURE_FAIL, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5828 return false;
5831 if (!test_user) {
5832 if (user_handle_out) {
5833 *user_handle_out = user_handle;
5835 return ret;
5839 q.in.user_handle = &user_handle;
5840 q.in.level = 16;
5841 q.out.info = &info;
5843 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5844 "QueryUserInfo failed");
5845 if (!NT_STATUS_IS_OK(q.out.result)) {
5846 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5847 q.in.level, nt_errstr(q.out.result));
5848 ret = false;
5849 } else {
5850 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5851 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5852 info->info16.acct_flags,
5853 acct_flags);
5854 ret = false;
5858 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5859 domain_sid, acct_flags, name.string, which_ops,
5860 machine_credentials)) {
5861 ret = false;
5864 if (user_handle_out) {
5865 *user_handle_out = user_handle;
5866 } else {
5867 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5869 d.in.user_handle = &user_handle;
5870 d.out.user_handle = &user_handle;
5872 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5873 "DeleteUser failed");
5874 if (!NT_STATUS_IS_OK(d.out.result)) {
5875 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5876 ret = false;
5882 talloc_free(user_ctx);
5884 return ret;
5888 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5889 struct policy_handle *domain_handle,
5890 struct dom_sid *domain_sid,
5891 enum torture_samr_choice which_ops,
5892 struct cli_credentials *machine_credentials)
5894 struct samr_CreateUser2 r;
5895 struct samr_QueryUserInfo q;
5896 union samr_UserInfo *info;
5897 struct samr_DeleteUser d;
5898 struct policy_handle user_handle;
5899 uint32_t rid;
5900 struct lsa_String name;
5901 bool ret = true;
5902 int i;
5903 struct dcerpc_binding_handle *b = p->binding_handle;
5905 struct {
5906 uint32_t acct_flags;
5907 const char *account_name;
5908 NTSTATUS nt_status;
5909 } account_types[] = {
5910 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5911 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5912 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5913 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5914 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5915 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5916 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5917 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5918 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5919 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5920 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5921 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5922 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5923 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5924 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5927 for (i = 0; account_types[i].account_name; i++) {
5928 TALLOC_CTX *user_ctx;
5929 uint32_t acct_flags = account_types[i].acct_flags;
5930 uint32_t access_granted;
5931 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5932 init_lsa_String(&name, account_types[i].account_name);
5934 r.in.domain_handle = domain_handle;
5935 r.in.account_name = &name;
5936 r.in.acct_flags = acct_flags;
5937 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5938 r.out.user_handle = &user_handle;
5939 r.out.access_granted = &access_granted;
5940 r.out.rid = &rid;
5942 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5944 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5945 "CreateUser2 failed");
5947 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5948 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5949 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5950 continue;
5951 } else {
5952 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5953 nt_errstr(r.out.result));
5954 ret = false;
5955 continue;
5959 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5960 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5961 talloc_free(user_ctx);
5962 ret = false;
5963 continue;
5965 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5966 "CreateUser2 failed");
5969 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5970 torture_result(tctx, TORTURE_FAIL, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5971 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5972 ret = false;
5975 if (NT_STATUS_IS_OK(r.out.result)) {
5976 q.in.user_handle = &user_handle;
5977 q.in.level = 5;
5978 q.out.info = &info;
5980 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5981 "QueryUserInfo failed");
5982 if (!NT_STATUS_IS_OK(q.out.result)) {
5983 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5984 q.in.level, nt_errstr(q.out.result));
5985 ret = false;
5986 } else {
5987 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5988 if (acct_flags == ACB_NORMAL) {
5989 expected_flags |= ACB_PW_EXPIRED;
5991 if ((info->info5.acct_flags) != expected_flags) {
5992 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5993 info->info5.acct_flags,
5994 expected_flags);
5995 ret = false;
5997 switch (acct_flags) {
5998 case ACB_SVRTRUST:
5999 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
6000 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
6001 DOMAIN_RID_DCS, info->info5.primary_gid);
6002 ret = false;
6004 break;
6005 case ACB_WSTRUST:
6006 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
6007 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
6008 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
6009 ret = false;
6011 break;
6012 case ACB_NORMAL:
6013 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
6014 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
6015 DOMAIN_RID_USERS, info->info5.primary_gid);
6016 ret = false;
6018 break;
6022 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
6023 domain_sid, acct_flags, name.string, which_ops,
6024 machine_credentials)) {
6025 ret = false;
6028 if (!ndr_policy_handle_empty(&user_handle)) {
6029 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
6031 d.in.user_handle = &user_handle;
6032 d.out.user_handle = &user_handle;
6034 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
6035 "DeleteUser failed");
6036 if (!NT_STATUS_IS_OK(d.out.result)) {
6037 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
6038 ret = false;
6042 talloc_free(user_ctx);
6045 return ret;
6048 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
6049 struct torture_context *tctx,
6050 struct policy_handle *handle)
6052 struct samr_QueryAliasInfo r;
6053 union samr_AliasInfo *info;
6054 uint16_t levels[] = {1, 2, 3};
6055 int i;
6056 bool ret = true;
6058 for (i=0;i<ARRAY_SIZE(levels);i++) {
6059 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
6061 r.in.alias_handle = handle;
6062 r.in.level = levels[i];
6063 r.out.info = &info;
6065 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
6066 "QueryAliasInfo failed");
6067 if (!NT_STATUS_IS_OK(r.out.result)) {
6068 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
6069 levels[i], nt_errstr(r.out.result));
6070 ret = false;
6074 return ret;
6077 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
6078 struct torture_context *tctx,
6079 struct policy_handle *handle)
6081 struct samr_QueryGroupInfo r;
6082 union samr_GroupInfo *info;
6083 uint16_t levels[] = {1, 2, 3, 4, 5};
6084 int i;
6085 bool ret = true;
6087 for (i=0;i<ARRAY_SIZE(levels);i++) {
6088 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
6090 r.in.group_handle = handle;
6091 r.in.level = levels[i];
6092 r.out.info = &info;
6094 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
6095 "QueryGroupInfo failed");
6096 if (!NT_STATUS_IS_OK(r.out.result)) {
6097 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
6098 levels[i], nt_errstr(r.out.result));
6099 ret = false;
6103 return ret;
6106 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
6107 struct torture_context *tctx,
6108 struct policy_handle *handle)
6110 struct samr_QueryGroupMember r;
6111 struct samr_RidAttrArray *rids = NULL;
6112 bool ret = true;
6114 torture_comment(tctx, "Testing QueryGroupMember\n");
6116 r.in.group_handle = handle;
6117 r.out.rids = &rids;
6119 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
6120 "QueryGroupMember failed");
6121 if (!NT_STATUS_IS_OK(r.out.result)) {
6122 torture_result(tctx, TORTURE_FAIL, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
6123 ret = false;
6126 return ret;
6130 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
6131 struct torture_context *tctx,
6132 struct policy_handle *handle)
6134 struct samr_QueryGroupInfo r;
6135 union samr_GroupInfo *info;
6136 struct samr_SetGroupInfo s;
6137 uint16_t levels[] = {1, 2, 3, 4};
6138 uint16_t set_ok[] = {0, 1, 1, 1};
6139 int i;
6140 bool ret = true;
6142 for (i=0;i<ARRAY_SIZE(levels);i++) {
6143 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
6145 r.in.group_handle = handle;
6146 r.in.level = levels[i];
6147 r.out.info = &info;
6149 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
6150 "QueryGroupInfo failed");
6151 if (!NT_STATUS_IS_OK(r.out.result)) {
6152 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
6153 levels[i], nt_errstr(r.out.result));
6154 ret = false;
6157 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
6159 s.in.group_handle = handle;
6160 s.in.level = levels[i];
6161 s.in.info = *r.out.info;
6163 #if 0
6164 /* disabled this, as it changes the name only from the point of view of samr,
6165 but leaves the name from the point of view of w2k3 internals (and ldap). This means
6166 the name is still reserved, so creating the old name fails, but deleting by the old name
6167 also fails */
6168 if (s.in.level == 2) {
6169 init_lsa_String(&s.in.info->string, "NewName");
6171 #endif
6173 if (s.in.level == 4) {
6174 init_lsa_String(&s.in.info->description, "test description");
6177 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
6178 "SetGroupInfo failed");
6179 if (set_ok[i]) {
6180 if (!NT_STATUS_IS_OK(s.out.result)) {
6181 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u failed - %s\n",
6182 r.in.level, nt_errstr(s.out.result));
6183 ret = false;
6184 continue;
6186 } else {
6187 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6188 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6189 r.in.level, nt_errstr(s.out.result));
6190 ret = false;
6191 continue;
6196 return ret;
6199 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
6200 struct torture_context *tctx,
6201 struct policy_handle *handle)
6203 struct samr_QueryUserInfo r;
6204 union samr_UserInfo *info;
6205 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6206 11, 12, 13, 14, 16, 17, 20, 21};
6207 int i;
6208 bool ret = true;
6210 for (i=0;i<ARRAY_SIZE(levels);i++) {
6211 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
6213 r.in.user_handle = handle;
6214 r.in.level = levels[i];
6215 r.out.info = &info;
6217 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
6218 "QueryUserInfo failed");
6219 if (!NT_STATUS_IS_OK(r.out.result)) {
6220 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
6221 levels[i], nt_errstr(r.out.result));
6222 ret = false;
6226 return ret;
6229 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
6230 struct torture_context *tctx,
6231 struct policy_handle *handle)
6233 struct samr_QueryUserInfo2 r;
6234 union samr_UserInfo *info;
6235 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6236 11, 12, 13, 14, 16, 17, 20, 21};
6237 int i;
6238 bool ret = true;
6240 for (i=0;i<ARRAY_SIZE(levels);i++) {
6241 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
6243 r.in.user_handle = handle;
6244 r.in.level = levels[i];
6245 r.out.info = &info;
6247 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
6248 "QueryUserInfo2 failed");
6249 if (!NT_STATUS_IS_OK(r.out.result)) {
6250 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo2 level %u failed - %s\n",
6251 levels[i], nt_errstr(r.out.result));
6252 ret = false;
6256 return ret;
6259 static bool test_OpenUser(struct dcerpc_binding_handle *b,
6260 struct torture_context *tctx,
6261 struct policy_handle *handle, uint32_t rid)
6263 struct samr_OpenUser r;
6264 struct policy_handle user_handle;
6265 bool ret = true;
6267 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6269 r.in.domain_handle = handle;
6270 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6271 r.in.rid = rid;
6272 r.out.user_handle = &user_handle;
6274 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6275 "OpenUser failed");
6276 if (!NT_STATUS_IS_OK(r.out.result)) {
6277 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6278 return false;
6281 if (!test_QuerySecurity(b, tctx, &user_handle)) {
6282 ret = false;
6285 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
6286 ret = false;
6289 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
6290 ret = false;
6293 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
6294 ret = false;
6297 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
6298 ret = false;
6301 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6302 ret = false;
6305 return ret;
6308 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
6309 struct torture_context *tctx,
6310 struct policy_handle *handle, uint32_t rid)
6312 struct samr_OpenGroup r;
6313 struct policy_handle group_handle;
6314 bool ret = true;
6316 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
6318 r.in.domain_handle = handle;
6319 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6320 r.in.rid = rid;
6321 r.out.group_handle = &group_handle;
6323 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
6324 "OpenGroup failed");
6325 if (!NT_STATUS_IS_OK(r.out.result)) {
6326 torture_result(tctx, TORTURE_FAIL, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6327 return false;
6330 if (!torture_setting_bool(tctx, "samba3", false)) {
6331 if (!test_QuerySecurity(b, tctx, &group_handle)) {
6332 ret = false;
6336 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
6337 ret = false;
6340 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
6341 ret = false;
6344 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
6345 ret = false;
6348 return ret;
6351 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
6352 struct torture_context *tctx,
6353 struct policy_handle *handle, uint32_t rid)
6355 struct samr_OpenAlias r;
6356 struct policy_handle alias_handle;
6357 bool ret = true;
6359 torture_comment(tctx, "Testing OpenAlias(%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.alias_handle = &alias_handle;
6366 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
6367 "OpenAlias failed");
6368 if (!NT_STATUS_IS_OK(r.out.result)) {
6369 torture_result(tctx, TORTURE_FAIL, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6370 return false;
6373 if (!torture_setting_bool(tctx, "samba3", false)) {
6374 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
6375 ret = false;
6379 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6380 ret = false;
6383 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6384 ret = false;
6387 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6388 ret = false;
6391 return ret;
6394 static bool check_mask(struct dcerpc_binding_handle *b,
6395 struct torture_context *tctx,
6396 struct policy_handle *handle, uint32_t rid,
6397 uint32_t acct_flag_mask)
6399 struct samr_OpenUser r;
6400 struct samr_QueryUserInfo q;
6401 union samr_UserInfo *info;
6402 struct policy_handle user_handle;
6403 bool ret = true;
6405 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6407 r.in.domain_handle = handle;
6408 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6409 r.in.rid = rid;
6410 r.out.user_handle = &user_handle;
6412 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6413 "OpenUser failed");
6414 if (!NT_STATUS_IS_OK(r.out.result)) {
6415 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6416 return false;
6419 q.in.user_handle = &user_handle;
6420 q.in.level = 16;
6421 q.out.info = &info;
6423 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6424 "QueryUserInfo failed");
6425 if (!NT_STATUS_IS_OK(q.out.result)) {
6426 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed - %s\n",
6427 nt_errstr(q.out.result));
6428 ret = false;
6429 } else {
6430 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
6431 torture_result(tctx, TORTURE_FAIL, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
6432 acct_flag_mask, info->info16.acct_flags, rid);
6433 ret = false;
6437 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6438 ret = false;
6441 return ret;
6444 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
6445 struct torture_context *tctx,
6446 struct policy_handle *handle)
6448 struct samr_EnumDomainUsers r;
6449 uint32_t mask, resume_handle=0;
6450 int i, mask_idx;
6451 bool ret = true;
6452 struct samr_LookupNames n;
6453 struct samr_LookupRids lr ;
6454 struct lsa_Strings names;
6455 struct samr_Ids rids, types;
6456 struct samr_SamArray *sam = NULL;
6457 uint32_t num_entries = 0;
6459 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
6460 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
6461 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
6462 ACB_PWNOEXP, 0};
6464 torture_comment(tctx, "Testing EnumDomainUsers\n");
6466 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
6467 r.in.domain_handle = handle;
6468 r.in.resume_handle = &resume_handle;
6469 r.in.acct_flags = mask = masks[mask_idx];
6470 r.in.max_size = (uint32_t)-1;
6471 r.out.resume_handle = &resume_handle;
6472 r.out.num_entries = &num_entries;
6473 r.out.sam = &sam;
6475 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
6476 "EnumDomainUsers failed");
6477 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6478 !NT_STATUS_IS_OK(r.out.result)) {
6479 torture_result(tctx, TORTURE_FAIL, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
6480 return false;
6483 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6485 if (sam->count == 0) {
6486 continue;
6489 for (i=0;i<sam->count;i++) {
6490 if (mask) {
6491 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6492 ret = false;
6494 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6495 ret = false;
6500 torture_comment(tctx, "Testing LookupNames\n");
6501 n.in.domain_handle = handle;
6502 n.in.num_names = sam->count;
6503 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6504 n.out.rids = &rids;
6505 n.out.types = &types;
6506 for (i=0;i<sam->count;i++) {
6507 n.in.names[i].string = sam->entries[i].name.string;
6509 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6510 "LookupNames failed");
6511 if (!NT_STATUS_IS_OK(n.out.result)) {
6512 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6513 ret = false;
6517 torture_comment(tctx, "Testing LookupRids\n");
6518 lr.in.domain_handle = handle;
6519 lr.in.num_rids = sam->count;
6520 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6521 lr.out.names = &names;
6522 lr.out.types = &types;
6523 for (i=0;i<sam->count;i++) {
6524 lr.in.rids[i] = sam->entries[i].idx;
6526 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6527 "LookupRids failed");
6528 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6530 return ret;
6534 try blasting the server with a bunch of sync requests
6536 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6537 struct policy_handle *handle)
6539 struct samr_EnumDomainUsers r;
6540 uint32_t resume_handle=0;
6541 int i;
6542 #define ASYNC_COUNT 100
6543 struct tevent_req *req[ASYNC_COUNT];
6545 if (!torture_setting_bool(tctx, "dangerous", false)) {
6546 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6549 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6551 r.in.domain_handle = handle;
6552 r.in.resume_handle = &resume_handle;
6553 r.in.acct_flags = 0;
6554 r.in.max_size = (uint32_t)-1;
6555 r.out.resume_handle = &resume_handle;
6557 for (i=0;i<ASYNC_COUNT;i++) {
6558 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6561 for (i=0;i<ASYNC_COUNT;i++) {
6562 tevent_req_poll(req[i], tctx->ev);
6563 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6564 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6565 i, nt_errstr(r.out.result)));
6568 torture_comment(tctx, "%d async requests OK\n", i);
6570 return true;
6573 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6574 struct torture_context *tctx,
6575 struct policy_handle *handle)
6577 struct samr_EnumDomainGroups r;
6578 uint32_t resume_handle=0;
6579 struct samr_SamArray *sam = NULL;
6580 uint32_t num_entries = 0;
6581 int i;
6582 bool ret = true;
6583 bool universal_group_found = false;
6585 torture_comment(tctx, "Testing EnumDomainGroups\n");
6587 r.in.domain_handle = handle;
6588 r.in.resume_handle = &resume_handle;
6589 r.in.max_size = (uint32_t)-1;
6590 r.out.resume_handle = &resume_handle;
6591 r.out.num_entries = &num_entries;
6592 r.out.sam = &sam;
6594 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6595 "EnumDomainGroups failed");
6596 if (!NT_STATUS_IS_OK(r.out.result)) {
6597 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6598 return false;
6601 if (!sam) {
6602 return false;
6605 for (i=0;i<sam->count;i++) {
6606 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6607 ret = false;
6609 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6610 "Enterprise Admins") == 0)) {
6611 universal_group_found = true;
6615 /* when we are running this on s4 we should get back at least the
6616 * "Enterprise Admins" universal group. If we don't get a group entry
6617 * at all we probably are performing the test on the builtin domain.
6618 * So ignore this case. */
6619 if (torture_setting_bool(tctx, "samba4", false)) {
6620 if ((sam->count > 0) && (!universal_group_found)) {
6621 ret = false;
6625 return ret;
6628 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6629 struct torture_context *tctx,
6630 struct policy_handle *handle)
6632 struct samr_EnumDomainAliases r;
6633 uint32_t resume_handle=0;
6634 struct samr_SamArray *sam = NULL;
6635 uint32_t num_entries = 0;
6636 int i;
6637 bool ret = true;
6639 torture_comment(tctx, "Testing EnumDomainAliases\n");
6641 r.in.domain_handle = handle;
6642 r.in.resume_handle = &resume_handle;
6643 r.in.max_size = (uint32_t)-1;
6644 r.out.sam = &sam;
6645 r.out.num_entries = &num_entries;
6646 r.out.resume_handle = &resume_handle;
6648 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6649 "EnumDomainAliases failed");
6650 if (!NT_STATUS_IS_OK(r.out.result)) {
6651 torture_result(tctx, TORTURE_FAIL, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6652 return false;
6655 if (!sam) {
6656 return false;
6659 for (i=0;i<sam->count;i++) {
6660 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6661 ret = false;
6665 return ret;
6668 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6669 struct torture_context *tctx,
6670 struct policy_handle *handle)
6672 struct samr_GetDisplayEnumerationIndex r;
6673 bool ret = true;
6674 uint16_t levels[] = {1, 2, 3, 4, 5};
6675 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6676 struct lsa_String name;
6677 uint32_t idx = 0;
6678 int i;
6680 for (i=0;i<ARRAY_SIZE(levels);i++) {
6681 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6683 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6685 r.in.domain_handle = handle;
6686 r.in.level = levels[i];
6687 r.in.name = &name;
6688 r.out.idx = &idx;
6690 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6691 "GetDisplayEnumerationIndex failed");
6693 if (ok_lvl[i] &&
6694 !NT_STATUS_IS_OK(r.out.result) &&
6695 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6696 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6697 levels[i], nt_errstr(r.out.result));
6698 ret = false;
6701 init_lsa_String(&name, "zzzzzzzz");
6703 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6704 "GetDisplayEnumerationIndex failed");
6706 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6707 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
6708 levels[i], nt_errstr(r.out.result));
6709 ret = false;
6713 return ret;
6716 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6717 struct torture_context *tctx,
6718 struct policy_handle *handle)
6720 struct samr_GetDisplayEnumerationIndex2 r;
6721 bool ret = true;
6722 uint16_t levels[] = {1, 2, 3, 4, 5};
6723 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6724 struct lsa_String name;
6725 uint32_t idx = 0;
6726 int i;
6728 for (i=0;i<ARRAY_SIZE(levels);i++) {
6729 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6731 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6733 r.in.domain_handle = handle;
6734 r.in.level = levels[i];
6735 r.in.name = &name;
6736 r.out.idx = &idx;
6738 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6739 "GetDisplayEnumerationIndex2 failed");
6740 if (ok_lvl[i] &&
6741 !NT_STATUS_IS_OK(r.out.result) &&
6742 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6743 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6744 levels[i], nt_errstr(r.out.result));
6745 ret = false;
6748 init_lsa_String(&name, "zzzzzzzz");
6750 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6751 "GetDisplayEnumerationIndex2 failed");
6752 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6753 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6754 levels[i], nt_errstr(r.out.result));
6755 ret = false;
6759 return ret;
6762 #define STRING_EQUAL_QUERY(s1, s2, user) \
6763 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6764 /* odd, but valid */ \
6765 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6766 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: %s != %s (%s)\n", \
6767 #s1, user.string, s1.string, s2.string, __location__); \
6768 ret = false; \
6770 #define INT_EQUAL_QUERY(s1, s2, user) \
6771 if (s1 != s2) { \
6772 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6773 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6774 ret = false; \
6777 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6778 struct torture_context *tctx,
6779 struct samr_QueryDisplayInfo *querydisplayinfo,
6780 bool *seen_testuser)
6782 struct samr_OpenUser r;
6783 struct samr_QueryUserInfo q;
6784 union samr_UserInfo *info;
6785 struct policy_handle user_handle;
6786 int i, ret = true;
6787 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6788 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6789 for (i = 0; ; i++) {
6790 switch (querydisplayinfo->in.level) {
6791 case 1:
6792 if (i >= querydisplayinfo->out.info->info1.count) {
6793 return ret;
6795 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6796 break;
6797 case 2:
6798 if (i >= querydisplayinfo->out.info->info2.count) {
6799 return ret;
6801 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6802 break;
6803 case 3:
6804 /* Groups */
6805 case 4:
6806 case 5:
6807 /* Not interested in validating just the account name */
6808 return true;
6811 r.out.user_handle = &user_handle;
6813 switch (querydisplayinfo->in.level) {
6814 case 1:
6815 case 2:
6816 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6817 "OpenUser failed");
6818 if (!NT_STATUS_IS_OK(r.out.result)) {
6819 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6820 return false;
6824 q.in.user_handle = &user_handle;
6825 q.in.level = 21;
6826 q.out.info = &info;
6827 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6828 "QueryUserInfo failed");
6829 if (!NT_STATUS_IS_OK(r.out.result)) {
6830 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6831 return false;
6834 switch (querydisplayinfo->in.level) {
6835 case 1:
6836 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6837 *seen_testuser = true;
6839 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6840 info->info21.full_name, info->info21.account_name);
6841 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6842 info->info21.account_name, info->info21.account_name);
6843 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6844 info->info21.description, info->info21.account_name);
6845 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6846 info->info21.rid, info->info21.account_name);
6847 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6848 info->info21.acct_flags, info->info21.account_name);
6850 break;
6851 case 2:
6852 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6853 info->info21.account_name, info->info21.account_name);
6854 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6855 info->info21.description, info->info21.account_name);
6856 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6857 info->info21.rid, info->info21.account_name);
6858 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6859 info->info21.acct_flags, info->info21.account_name);
6861 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6862 torture_result(tctx, TORTURE_FAIL, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6863 info->info21.account_name.string);
6866 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6867 torture_result(tctx, TORTURE_FAIL, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6868 info->info21.account_name.string,
6869 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6870 info->info21.acct_flags);
6871 return false;
6874 break;
6877 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6878 return false;
6881 return ret;
6884 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6885 struct torture_context *tctx,
6886 struct policy_handle *handle)
6888 struct samr_QueryDisplayInfo r;
6889 struct samr_QueryDomainInfo dom_info;
6890 union samr_DomainInfo *info = NULL;
6891 bool ret = true;
6892 uint16_t levels[] = {1, 2, 3, 4, 5};
6893 int i;
6894 bool seen_testuser = false;
6895 uint32_t total_size;
6896 uint32_t returned_size;
6897 union samr_DispInfo disp_info;
6900 for (i=0;i<ARRAY_SIZE(levels);i++) {
6901 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6903 r.in.start_idx = 0;
6904 r.out.result = STATUS_MORE_ENTRIES;
6905 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6906 r.in.domain_handle = handle;
6907 r.in.level = levels[i];
6908 r.in.max_entries = 2;
6909 r.in.buf_size = (uint32_t)-1;
6910 r.out.total_size = &total_size;
6911 r.out.returned_size = &returned_size;
6912 r.out.info = &disp_info;
6914 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6915 "QueryDisplayInfo failed");
6916 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6917 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
6918 levels[i], nt_errstr(r.out.result));
6919 ret = false;
6921 switch (r.in.level) {
6922 case 1:
6923 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6924 ret = false;
6926 r.in.start_idx += r.out.info->info1.count;
6927 break;
6928 case 2:
6929 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6930 ret = false;
6932 r.in.start_idx += r.out.info->info2.count;
6933 break;
6934 case 3:
6935 r.in.start_idx += r.out.info->info3.count;
6936 break;
6937 case 4:
6938 r.in.start_idx += r.out.info->info4.count;
6939 break;
6940 case 5:
6941 r.in.start_idx += r.out.info->info5.count;
6942 break;
6945 dom_info.in.domain_handle = handle;
6946 dom_info.in.level = 2;
6947 dom_info.out.info = &info;
6949 /* Check number of users returned is correct */
6950 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6951 "QueryDomainInfo failed");
6952 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6953 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
6954 r.in.level, nt_errstr(dom_info.out.result));
6955 ret = false;
6956 break;
6958 switch (r.in.level) {
6959 case 1:
6960 case 4:
6961 if (info->general.num_users < r.in.start_idx) {
6962 /* On AD deployments this numbers don't match
6963 * since QueryDisplayInfo returns universal and
6964 * global groups, QueryDomainInfo only global
6965 * ones. */
6966 if (torture_setting_bool(tctx, "samba3", false)) {
6967 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6968 r.in.start_idx, info->general.num_groups,
6969 info->general.domain_name.string);
6970 ret = false;
6973 if (!seen_testuser) {
6974 struct policy_handle user_handle;
6975 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6976 torture_result(tctx, TORTURE_FAIL, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6977 info->general.domain_name.string);
6978 ret = false;
6979 test_samr_handle_Close(b, tctx, &user_handle);
6982 break;
6983 case 3:
6984 case 5:
6985 if (info->general.num_groups != r.in.start_idx) {
6986 /* On AD deployments this numbers don't match
6987 * since QueryDisplayInfo returns universal and
6988 * global groups, QueryDomainInfo only global
6989 * ones. */
6990 if (torture_setting_bool(tctx, "samba3", false)) {
6991 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6992 r.in.start_idx, info->general.num_groups,
6993 info->general.domain_name.string);
6994 ret = false;
6998 break;
7003 return ret;
7006 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
7007 struct torture_context *tctx,
7008 struct policy_handle *handle)
7010 struct samr_QueryDisplayInfo2 r;
7011 bool ret = true;
7012 uint16_t levels[] = {1, 2, 3, 4, 5};
7013 int i;
7014 uint32_t total_size;
7015 uint32_t returned_size;
7016 union samr_DispInfo info;
7018 for (i=0;i<ARRAY_SIZE(levels);i++) {
7019 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
7021 r.in.domain_handle = handle;
7022 r.in.level = levels[i];
7023 r.in.start_idx = 0;
7024 r.in.max_entries = 1000;
7025 r.in.buf_size = (uint32_t)-1;
7026 r.out.total_size = &total_size;
7027 r.out.returned_size = &returned_size;
7028 r.out.info = &info;
7030 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
7031 "QueryDisplayInfo2 failed");
7032 if (!NT_STATUS_IS_OK(r.out.result)) {
7033 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo2 level %u failed - %s\n",
7034 levels[i], nt_errstr(r.out.result));
7035 ret = false;
7039 return ret;
7042 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
7043 struct torture_context *tctx,
7044 struct policy_handle *handle)
7046 struct samr_QueryDisplayInfo3 r;
7047 bool ret = true;
7048 uint16_t levels[] = {1, 2, 3, 4, 5};
7049 int i;
7050 uint32_t total_size;
7051 uint32_t returned_size;
7052 union samr_DispInfo info;
7054 for (i=0;i<ARRAY_SIZE(levels);i++) {
7055 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
7057 r.in.domain_handle = handle;
7058 r.in.level = levels[i];
7059 r.in.start_idx = 0;
7060 r.in.max_entries = 1000;
7061 r.in.buf_size = (uint32_t)-1;
7062 r.out.total_size = &total_size;
7063 r.out.returned_size = &returned_size;
7064 r.out.info = &info;
7066 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
7067 "QueryDisplayInfo3 failed");
7068 if (!NT_STATUS_IS_OK(r.out.result)) {
7069 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo3 level %u failed - %s\n",
7070 levels[i], nt_errstr(r.out.result));
7071 ret = false;
7075 return ret;
7079 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
7080 struct torture_context *tctx,
7081 struct policy_handle *handle)
7083 struct samr_QueryDisplayInfo r;
7084 bool ret = true;
7085 uint32_t total_size;
7086 uint32_t returned_size;
7087 union samr_DispInfo info;
7089 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
7091 r.in.domain_handle = handle;
7092 r.in.level = 1;
7093 r.in.start_idx = 0;
7094 r.in.max_entries = 1;
7095 r.in.buf_size = (uint32_t)-1;
7096 r.out.total_size = &total_size;
7097 r.out.returned_size = &returned_size;
7098 r.out.info = &info;
7100 do {
7101 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7102 "QueryDisplayInfo failed");
7103 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
7104 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
7105 torture_result(tctx, TORTURE_FAIL, "expected idx %d but got %d\n",
7106 r.in.start_idx + 1,
7107 r.out.info->info1.entries[0].idx);
7108 break;
7111 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
7112 !NT_STATUS_IS_OK(r.out.result)) {
7113 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
7114 r.in.level, nt_errstr(r.out.result));
7115 ret = false;
7116 break;
7118 r.in.start_idx++;
7119 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
7120 NT_STATUS_IS_OK(r.out.result)) &&
7121 *r.out.returned_size != 0);
7123 return ret;
7126 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
7127 struct torture_context *tctx,
7128 struct policy_handle *handle)
7130 struct samr_QueryDomainInfo r;
7131 union samr_DomainInfo *info = NULL;
7132 struct samr_SetDomainInfo s;
7133 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
7134 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
7135 int i;
7136 bool ret = true;
7137 struct dcerpc_binding_handle *b = p->binding_handle;
7138 const char *domain_comment = talloc_asprintf(tctx,
7139 "Tortured by Samba4 RPC-SAMR: %s",
7140 timestring(tctx, time(NULL)));
7142 s.in.domain_handle = handle;
7143 s.in.level = 4;
7144 s.in.info = talloc(tctx, union samr_DomainInfo);
7146 s.in.info->oem.oem_information.string = domain_comment;
7147 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
7148 "SetDomainInfo failed");
7149 if (!NT_STATUS_IS_OK(s.out.result)) {
7150 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u (set comment) failed - %s\n",
7151 s.in.level, nt_errstr(s.out.result));
7152 return false;
7155 for (i=0;i<ARRAY_SIZE(levels);i++) {
7156 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
7158 r.in.domain_handle = handle;
7159 r.in.level = levels[i];
7160 r.out.info = &info;
7162 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
7163 "QueryDomainInfo failed");
7164 if (!NT_STATUS_IS_OK(r.out.result)) {
7165 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7166 r.in.level, nt_errstr(r.out.result));
7167 ret = false;
7168 continue;
7171 switch (levels[i]) {
7172 case 2:
7173 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
7174 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
7175 levels[i], info->general.oem_information.string, domain_comment);
7176 if (!torture_setting_bool(tctx, "samba3", false)) {
7177 ret = false;
7180 if (!info->general.primary.string) {
7181 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
7182 levels[i]);
7183 ret = false;
7184 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
7185 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
7186 if (torture_setting_bool(tctx, "samba3", false)) {
7187 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",
7188 levels[i], info->general.primary.string, dcerpc_server_name(p));
7192 break;
7193 case 4:
7194 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
7195 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
7196 levels[i], info->oem.oem_information.string, domain_comment);
7197 if (!torture_setting_bool(tctx, "samba3", false)) {
7198 ret = false;
7201 break;
7202 case 6:
7203 if (!info->info6.primary.string) {
7204 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
7205 levels[i]);
7206 ret = false;
7208 break;
7209 case 11:
7210 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
7211 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
7212 levels[i], info->general2.general.oem_information.string, domain_comment);
7213 if (!torture_setting_bool(tctx, "samba3", false)) {
7214 ret = false;
7217 break;
7220 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
7222 s.in.domain_handle = handle;
7223 s.in.level = levels[i];
7224 s.in.info = info;
7226 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
7227 "SetDomainInfo failed");
7228 if (set_ok[i]) {
7229 if (!NT_STATUS_IS_OK(s.out.result)) {
7230 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u failed - %s\n",
7231 r.in.level, nt_errstr(s.out.result));
7232 ret = false;
7233 continue;
7235 } else {
7236 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
7237 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
7238 r.in.level, nt_errstr(s.out.result));
7239 ret = false;
7240 continue;
7244 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
7245 "QueryDomainInfo failed");
7246 if (!NT_STATUS_IS_OK(r.out.result)) {
7247 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7248 r.in.level, nt_errstr(r.out.result));
7249 ret = false;
7250 continue;
7254 return ret;
7258 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
7259 struct torture_context *tctx,
7260 struct policy_handle *handle)
7262 struct samr_QueryDomainInfo2 r;
7263 union samr_DomainInfo *info = NULL;
7264 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
7265 int i;
7266 bool ret = true;
7268 for (i=0;i<ARRAY_SIZE(levels);i++) {
7269 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
7271 r.in.domain_handle = handle;
7272 r.in.level = levels[i];
7273 r.out.info = &info;
7275 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7276 "QueryDomainInfo2 failed");
7277 if (!NT_STATUS_IS_OK(r.out.result)) {
7278 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo2 level %u failed - %s\n",
7279 r.in.level, nt_errstr(r.out.result));
7280 ret = false;
7281 continue;
7285 return ret;
7288 /* Test whether querydispinfo level 5 and enumdomgroups return the same
7289 set of group names. */
7290 static bool test_GroupList(struct dcerpc_binding_handle *b,
7291 struct torture_context *tctx,
7292 struct dom_sid *domain_sid,
7293 struct policy_handle *handle)
7295 struct samr_EnumDomainGroups q1;
7296 struct samr_QueryDisplayInfo q2;
7297 NTSTATUS status;
7298 uint32_t resume_handle=0;
7299 struct samr_SamArray *sam = NULL;
7300 uint32_t num_entries = 0;
7301 int i;
7302 bool ret = true;
7303 uint32_t total_size;
7304 uint32_t returned_size;
7305 union samr_DispInfo info;
7307 size_t num_names = 0;
7308 const char **names = NULL;
7310 bool builtin_domain = dom_sid_compare(domain_sid,
7311 &global_sid_Builtin) == 0;
7313 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
7315 q1.in.domain_handle = handle;
7316 q1.in.resume_handle = &resume_handle;
7317 q1.in.max_size = 5;
7318 q1.out.resume_handle = &resume_handle;
7319 q1.out.num_entries = &num_entries;
7320 q1.out.sam = &sam;
7322 status = STATUS_MORE_ENTRIES;
7323 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7324 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
7325 "EnumDomainGroups failed");
7326 status = q1.out.result;
7328 if (!NT_STATUS_IS_OK(status) &&
7329 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7330 break;
7332 for (i=0; i<*q1.out.num_entries; i++) {
7333 add_string_to_array(tctx,
7334 sam->entries[i].name.string,
7335 &names, &num_names);
7339 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
7341 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
7343 if (builtin_domain) {
7344 torture_assert(tctx, num_names == 0,
7345 "EnumDomainGroups shouldn't return any group in the builtin domain!");
7348 q2.in.domain_handle = handle;
7349 q2.in.level = 5;
7350 q2.in.start_idx = 0;
7351 q2.in.max_entries = 5;
7352 q2.in.buf_size = (uint32_t)-1;
7353 q2.out.total_size = &total_size;
7354 q2.out.returned_size = &returned_size;
7355 q2.out.info = &info;
7357 status = STATUS_MORE_ENTRIES;
7358 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7359 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
7360 "QueryDisplayInfo failed");
7361 status = q2.out.result;
7362 if (!NT_STATUS_IS_OK(status) &&
7363 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7364 break;
7366 for (i=0; i<q2.out.info->info5.count; i++) {
7367 int j;
7368 const char *name = q2.out.info->info5.entries[i].account_name.string;
7369 bool found = false;
7370 for (j=0; j<num_names; j++) {
7371 if (names[j] == NULL)
7372 continue;
7373 if (strequal(names[j], name)) {
7374 names[j] = NULL;
7375 found = true;
7376 break;
7380 if ((!found) && (!builtin_domain)) {
7381 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7382 name);
7383 ret = false;
7386 q2.in.start_idx += q2.out.info->info5.count;
7389 if (!NT_STATUS_IS_OK(status)) {
7390 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level 5 failed - %s\n",
7391 nt_errstr(status));
7392 ret = false;
7395 if (builtin_domain) {
7396 torture_assert(tctx, q2.in.start_idx != 0,
7397 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
7400 for (i=0; i<num_names; i++) {
7401 if (names[i] != NULL) {
7402 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
7403 names[i]);
7404 ret = false;
7408 return ret;
7411 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
7412 struct torture_context *tctx,
7413 struct policy_handle *group_handle)
7415 struct samr_DeleteDomainGroup d;
7417 torture_comment(tctx, "Testing DeleteDomainGroup\n");
7419 d.in.group_handle = group_handle;
7420 d.out.group_handle = group_handle;
7422 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
7423 "DeleteDomainGroup failed");
7424 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
7426 return true;
7429 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
7430 struct torture_context *tctx,
7431 struct policy_handle *domain_handle)
7433 struct samr_TestPrivateFunctionsDomain r;
7434 bool ret = true;
7436 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
7438 r.in.domain_handle = domain_handle;
7440 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
7441 "TestPrivateFunctionsDomain failed");
7442 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
7444 return ret;
7447 static bool test_RidToSid(struct dcerpc_binding_handle *b,
7448 struct torture_context *tctx,
7449 struct dom_sid *domain_sid,
7450 struct policy_handle *domain_handle)
7452 struct samr_RidToSid r;
7453 bool ret = true;
7454 struct dom_sid *calc_sid, *out_sid;
7455 int rids[] = { 0, 42, 512, 10200 };
7456 int i;
7458 for (i=0;i<ARRAY_SIZE(rids);i++) {
7459 torture_comment(tctx, "Testing RidToSid\n");
7461 calc_sid = dom_sid_dup(tctx, domain_sid);
7462 r.in.domain_handle = domain_handle;
7463 r.in.rid = rids[i];
7464 r.out.sid = &out_sid;
7466 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
7467 "RidToSid failed");
7468 if (!NT_STATUS_IS_OK(r.out.result)) {
7469 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
7470 ret = false;
7471 } else {
7472 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
7474 if (!dom_sid_equal(calc_sid, out_sid)) {
7475 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
7476 dom_sid_string(tctx, out_sid),
7477 dom_sid_string(tctx, calc_sid));
7478 ret = false;
7483 return ret;
7486 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7487 struct torture_context *tctx,
7488 struct policy_handle *domain_handle)
7490 struct samr_GetBootKeyInformation r;
7491 bool ret = true;
7492 uint32_t unknown = 0;
7493 NTSTATUS status;
7495 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7497 r.in.domain_handle = domain_handle;
7498 r.out.unknown = &unknown;
7500 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7501 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7502 status = r.out.result;
7504 if (!NT_STATUS_IS_OK(status)) {
7505 /* w2k3 seems to fail this sometimes and pass it sometimes */
7506 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7509 return ret;
7512 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7513 struct torture_context *tctx,
7514 struct policy_handle *domain_handle,
7515 struct policy_handle *group_handle)
7517 NTSTATUS status;
7518 struct samr_AddGroupMember r;
7519 struct samr_DeleteGroupMember d;
7520 struct samr_QueryGroupMember q;
7521 struct samr_RidAttrArray *rids = NULL;
7522 struct samr_SetMemberAttributesOfGroup s;
7523 uint32_t rid;
7524 bool found_member = false;
7525 int i;
7527 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7528 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7530 r.in.group_handle = group_handle;
7531 r.in.rid = rid;
7532 r.in.flags = 0; /* ??? */
7534 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7536 d.in.group_handle = group_handle;
7537 d.in.rid = rid;
7539 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7540 "DeleteGroupMember failed");
7541 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7543 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7544 "AddGroupMember failed");
7545 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7547 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7548 "AddGroupMember failed");
7549 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7551 if (torture_setting_bool(tctx, "samba4", false) ||
7552 torture_setting_bool(tctx, "samba3", false)) {
7553 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7554 } else {
7555 /* this one is quite strange. I am using random inputs in the
7556 hope of triggering an error that might give us a clue */
7558 s.in.group_handle = group_handle;
7559 s.in.unknown1 = random();
7560 s.in.unknown2 = random();
7562 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7563 "SetMemberAttributesOfGroup failed");
7564 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7567 q.in.group_handle = group_handle;
7568 q.out.rids = &rids;
7570 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7571 "QueryGroupMember failed");
7572 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7573 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7575 for (i=0; i < rids->count; i++) {
7576 if (rids->rids[i] == rid) {
7577 found_member = true;
7581 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7583 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7584 "DeleteGroupMember failed");
7585 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7587 rids = NULL;
7588 found_member = false;
7590 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7591 "QueryGroupMember failed");
7592 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7593 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7595 for (i=0; i < rids->count; i++) {
7596 if (rids->rids[i] == rid) {
7597 found_member = true;
7601 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7603 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7604 "AddGroupMember failed");
7605 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7607 return true;
7611 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7612 struct torture_context *tctx,
7613 struct policy_handle *domain_handle,
7614 const char *group_name,
7615 struct policy_handle *group_handle,
7616 struct dom_sid *domain_sid,
7617 bool test_group)
7619 struct samr_CreateDomainGroup r;
7620 uint32_t rid;
7621 struct lsa_String name;
7622 bool ret = true;
7624 init_lsa_String(&name, group_name);
7626 r.in.domain_handle = domain_handle;
7627 r.in.name = &name;
7628 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7629 r.out.group_handle = group_handle;
7630 r.out.rid = &rid;
7632 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7634 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7635 "CreateDomainGroup failed");
7637 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7638 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7639 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7640 return true;
7641 } else {
7642 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7643 nt_errstr(r.out.result));
7644 return false;
7648 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7649 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7650 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7651 nt_errstr(r.out.result));
7652 return false;
7654 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7655 "CreateDomainGroup failed");
7657 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7658 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7660 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7661 nt_errstr(r.out.result));
7662 return false;
7664 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7665 "CreateDomainGroup failed");
7667 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7669 if (!test_group) {
7670 return ret;
7673 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7674 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7675 ret = false;
7678 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7679 ret = false;
7682 return ret;
7687 its not totally clear what this does. It seems to accept any sid you like.
7689 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7690 struct torture_context *tctx,
7691 struct policy_handle *domain_handle)
7693 struct samr_RemoveMemberFromForeignDomain r;
7695 r.in.domain_handle = domain_handle;
7696 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7698 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7699 "RemoveMemberFromForeignDomain failed");
7700 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7702 return true;
7705 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7706 struct torture_context *tctx,
7707 struct policy_handle *domain_handle,
7708 uint32_t *total_num_entries_p)
7710 NTSTATUS status;
7711 struct samr_EnumDomainUsers r;
7712 uint32_t resume_handle = 0;
7713 uint32_t num_entries = 0;
7714 uint32_t total_num_entries = 0;
7715 struct samr_SamArray *sam;
7717 r.in.domain_handle = domain_handle;
7718 r.in.acct_flags = 0;
7719 r.in.max_size = (uint32_t)-1;
7720 r.in.resume_handle = &resume_handle;
7722 r.out.sam = &sam;
7723 r.out.num_entries = &num_entries;
7724 r.out.resume_handle = &resume_handle;
7726 torture_comment(tctx, "Testing EnumDomainUsers\n");
7728 do {
7729 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7730 "EnumDomainUsers failed");
7731 if (NT_STATUS_IS_ERR(r.out.result)) {
7732 torture_assert_ntstatus_ok(tctx, r.out.result,
7733 "failed to enumerate users");
7735 status = r.out.result;
7737 total_num_entries += num_entries;
7738 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7740 if (total_num_entries_p) {
7741 *total_num_entries_p = total_num_entries;
7744 return true;
7747 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7748 struct torture_context *tctx,
7749 struct policy_handle *domain_handle,
7750 uint32_t *total_num_entries_p)
7752 NTSTATUS status;
7753 struct samr_EnumDomainGroups r;
7754 uint32_t resume_handle = 0;
7755 uint32_t num_entries = 0;
7756 uint32_t total_num_entries = 0;
7757 struct samr_SamArray *sam;
7759 r.in.domain_handle = domain_handle;
7760 r.in.max_size = (uint32_t)-1;
7761 r.in.resume_handle = &resume_handle;
7763 r.out.sam = &sam;
7764 r.out.num_entries = &num_entries;
7765 r.out.resume_handle = &resume_handle;
7767 torture_comment(tctx, "Testing EnumDomainGroups\n");
7769 do {
7770 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7771 "EnumDomainGroups failed");
7772 if (NT_STATUS_IS_ERR(r.out.result)) {
7773 torture_assert_ntstatus_ok(tctx, r.out.result,
7774 "failed to enumerate groups");
7776 status = r.out.result;
7778 total_num_entries += num_entries;
7779 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7781 if (total_num_entries_p) {
7782 *total_num_entries_p = total_num_entries;
7785 return true;
7788 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7789 struct torture_context *tctx,
7790 struct policy_handle *domain_handle,
7791 uint32_t *total_num_entries_p)
7793 NTSTATUS status;
7794 struct samr_EnumDomainAliases r;
7795 uint32_t resume_handle = 0;
7796 uint32_t num_entries = 0;
7797 uint32_t total_num_entries = 0;
7798 struct samr_SamArray *sam;
7800 r.in.domain_handle = domain_handle;
7801 r.in.max_size = (uint32_t)-1;
7802 r.in.resume_handle = &resume_handle;
7804 r.out.sam = &sam;
7805 r.out.num_entries = &num_entries;
7806 r.out.resume_handle = &resume_handle;
7808 torture_comment(tctx, "Testing EnumDomainAliases\n");
7810 do {
7811 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7812 "EnumDomainAliases failed");
7813 if (NT_STATUS_IS_ERR(r.out.result)) {
7814 torture_assert_ntstatus_ok(tctx, r.out.result,
7815 "failed to enumerate aliases");
7817 status = r.out.result;
7819 total_num_entries += num_entries;
7820 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7822 if (total_num_entries_p) {
7823 *total_num_entries_p = total_num_entries;
7826 return true;
7829 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7830 struct torture_context *tctx,
7831 struct policy_handle *handle,
7832 uint16_t level,
7833 uint32_t *total_num_entries_p)
7835 NTSTATUS status;
7836 struct samr_QueryDisplayInfo r;
7837 uint32_t total_num_entries = 0;
7839 r.in.domain_handle = handle;
7840 r.in.level = level;
7841 r.in.start_idx = 0;
7842 r.in.max_entries = (uint32_t)-1;
7843 r.in.buf_size = (uint32_t)-1;
7845 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7847 do {
7848 uint32_t total_size;
7849 uint32_t returned_size;
7850 union samr_DispInfo info;
7852 r.out.total_size = &total_size;
7853 r.out.returned_size = &returned_size;
7854 r.out.info = &info;
7856 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7857 "failed to query displayinfo");
7858 if (NT_STATUS_IS_ERR(r.out.result)) {
7859 torture_assert_ntstatus_ok(tctx, r.out.result,
7860 "failed to query displayinfo");
7862 status = r.out.result;
7864 if (*r.out.returned_size == 0) {
7865 break;
7868 switch (r.in.level) {
7869 case 1:
7870 total_num_entries += info.info1.count;
7871 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7872 break;
7873 case 2:
7874 total_num_entries += info.info2.count;
7875 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7876 break;
7877 case 3:
7878 total_num_entries += info.info3.count;
7879 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7880 break;
7881 case 4:
7882 total_num_entries += info.info4.count;
7883 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7884 break;
7885 case 5:
7886 total_num_entries += info.info5.count;
7887 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7888 break;
7889 default:
7890 return false;
7893 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7895 if (total_num_entries_p) {
7896 *total_num_entries_p = total_num_entries;
7899 return true;
7902 static bool test_ManyObjects(struct dcerpc_pipe *p,
7903 struct torture_context *tctx,
7904 struct policy_handle *domain_handle,
7905 struct dom_sid *domain_sid,
7906 struct torture_samr_context *ctx)
7908 uint32_t num_total = ctx->num_objects_large_dc;
7909 uint32_t num_enum = 0;
7910 uint32_t num_disp = 0;
7911 uint32_t num_created = 0;
7912 uint32_t num_anounced = 0;
7913 uint32_t i;
7914 struct dcerpc_binding_handle *b = p->binding_handle;
7916 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7918 /* query */
7921 struct samr_QueryDomainInfo2 r;
7922 union samr_DomainInfo *info;
7923 r.in.domain_handle = domain_handle;
7924 r.in.level = 2;
7925 r.out.info = &info;
7927 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7928 "QueryDomainInfo2 failed");
7929 torture_assert_ntstatus_ok(tctx, r.out.result,
7930 "failed to query domain info");
7932 switch (ctx->choice) {
7933 case TORTURE_SAMR_MANY_ACCOUNTS:
7934 num_anounced = info->general.num_users;
7935 break;
7936 case TORTURE_SAMR_MANY_GROUPS:
7937 num_anounced = info->general.num_groups;
7938 break;
7939 case TORTURE_SAMR_MANY_ALIASES:
7940 num_anounced = info->general.num_aliases;
7941 break;
7942 default:
7943 return false;
7947 /* create */
7949 for (i=0; i < num_total; i++) {
7951 const char *name = NULL;
7953 switch (ctx->choice) {
7954 case TORTURE_SAMR_MANY_ACCOUNTS:
7955 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7956 torture_assert(tctx,
7957 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7958 "failed to create user");
7959 break;
7960 case TORTURE_SAMR_MANY_GROUPS:
7961 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7962 torture_assert(tctx,
7963 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7964 "failed to create group");
7965 break;
7966 case TORTURE_SAMR_MANY_ALIASES:
7967 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7968 torture_assert(tctx,
7969 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7970 "failed to create alias");
7971 break;
7972 default:
7973 return false;
7975 if (!ndr_policy_handle_empty(&handles[i])) {
7976 num_created++;
7980 /* enum */
7982 switch (ctx->choice) {
7983 case TORTURE_SAMR_MANY_ACCOUNTS:
7984 torture_assert(tctx,
7985 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7986 "failed to enum users");
7987 break;
7988 case TORTURE_SAMR_MANY_GROUPS:
7989 torture_assert(tctx,
7990 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7991 "failed to enum groups");
7992 break;
7993 case TORTURE_SAMR_MANY_ALIASES:
7994 torture_assert(tctx,
7995 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7996 "failed to enum aliases");
7997 break;
7998 default:
7999 return false;
8002 /* dispinfo */
8004 switch (ctx->choice) {
8005 case TORTURE_SAMR_MANY_ACCOUNTS:
8006 torture_assert(tctx,
8007 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
8008 "failed to query display info");
8009 break;
8010 case TORTURE_SAMR_MANY_GROUPS:
8011 torture_assert(tctx,
8012 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
8013 "failed to query display info");
8014 break;
8015 case TORTURE_SAMR_MANY_ALIASES:
8016 /* no aliases in dispinfo */
8017 break;
8018 default:
8019 return false;
8022 /* close or delete */
8024 for (i=0; i < num_total; i++) {
8026 if (ndr_policy_handle_empty(&handles[i])) {
8027 continue;
8030 if (torture_setting_bool(tctx, "samba3", false)) {
8031 torture_assert(tctx,
8032 test_samr_handle_Close(b, tctx, &handles[i]),
8033 "failed to close handle");
8034 } else {
8035 switch (ctx->choice) {
8036 case TORTURE_SAMR_MANY_ACCOUNTS:
8037 torture_assert(tctx,
8038 test_DeleteUser(b, tctx, &handles[i]),
8039 "failed to delete user");
8040 break;
8041 case TORTURE_SAMR_MANY_GROUPS:
8042 torture_assert(tctx,
8043 test_DeleteDomainGroup(b, tctx, &handles[i]),
8044 "failed to delete group");
8045 break;
8046 case TORTURE_SAMR_MANY_ALIASES:
8047 torture_assert(tctx,
8048 test_DeleteAlias(b, tctx, &handles[i]),
8049 "failed to delete alias");
8050 break;
8051 default:
8052 return false;
8057 talloc_free(handles);
8059 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
8060 torture_comment(tctx,
8061 "unexpected number of results (%u) returned in enum call, expected %u\n",
8062 num_enum, num_anounced + num_created);
8064 torture_comment(tctx,
8065 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
8066 num_disp, num_anounced + num_created);
8069 return true;
8072 static bool test_Connect(struct dcerpc_binding_handle *b,
8073 struct torture_context *tctx,
8074 struct policy_handle *handle);
8076 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
8077 struct torture_samr_context *ctx, struct dom_sid *sid)
8079 struct samr_OpenDomain r;
8080 struct policy_handle domain_handle;
8081 struct policy_handle alias_handle;
8082 struct policy_handle user_handle;
8083 struct policy_handle group_handle;
8084 bool ret = true;
8085 struct dcerpc_binding_handle *b = p->binding_handle;
8087 ZERO_STRUCT(alias_handle);
8088 ZERO_STRUCT(user_handle);
8089 ZERO_STRUCT(group_handle);
8090 ZERO_STRUCT(domain_handle);
8092 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
8094 r.in.connect_handle = &ctx->handle;
8095 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8096 r.in.sid = sid;
8097 r.out.domain_handle = &domain_handle;
8099 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
8100 "OpenDomain failed");
8101 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
8103 /* run the domain tests with the main handle closed - this tests
8104 the servers reference counting */
8105 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
8107 switch (ctx->choice) {
8108 case TORTURE_SAMR_PASSWORDS:
8109 case TORTURE_SAMR_USER_PRIVILEGES:
8110 if (!torture_setting_bool(tctx, "samba3", false)) {
8111 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
8113 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8114 if (!ret) {
8115 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
8117 break;
8118 case TORTURE_SAMR_USER_ATTRIBUTES:
8119 if (!torture_setting_bool(tctx, "samba3", false)) {
8120 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
8122 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8123 /* This test needs 'complex' users to validate */
8124 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
8125 if (!ret) {
8126 torture_result(tctx, TORTURE_FAIL, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
8128 break;
8129 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
8130 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
8131 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
8132 if (!torture_setting_bool(tctx, "samba3", false)) {
8133 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
8135 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
8136 if (!ret) {
8137 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
8139 break;
8140 case TORTURE_SAMR_MANY_ACCOUNTS:
8141 case TORTURE_SAMR_MANY_GROUPS:
8142 case TORTURE_SAMR_MANY_ALIASES:
8143 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
8144 if (!ret) {
8145 torture_result(tctx, TORTURE_FAIL, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
8147 break;
8148 case TORTURE_SAMR_OTHER:
8149 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8150 if (!ret) {
8151 torture_result(tctx, TORTURE_FAIL, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
8153 if (!torture_setting_bool(tctx, "samba3", false)) {
8154 ret &= test_QuerySecurity(b, tctx, &domain_handle);
8156 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
8157 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
8158 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
8159 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
8160 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
8161 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
8162 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
8163 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
8164 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
8165 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
8166 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
8167 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
8168 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
8170 if (torture_setting_bool(tctx, "samba4", false)) {
8171 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
8172 } else {
8173 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
8174 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
8176 ret &= test_GroupList(b, tctx, sid, &domain_handle);
8177 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
8178 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
8179 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
8180 if (!ret) {
8181 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
8183 break;
8186 if (!ndr_policy_handle_empty(&user_handle) &&
8187 !test_DeleteUser(b, tctx, &user_handle)) {
8188 ret = false;
8191 if (!ndr_policy_handle_empty(&alias_handle) &&
8192 !test_DeleteAlias(b, tctx, &alias_handle)) {
8193 ret = false;
8196 if (!ndr_policy_handle_empty(&group_handle) &&
8197 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
8198 ret = false;
8201 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
8203 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
8204 /* reconnect the main handle */
8206 if (!ret) {
8207 torture_result(tctx, TORTURE_FAIL, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
8210 return ret;
8213 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
8214 struct torture_samr_context *ctx, const char *domain)
8216 struct samr_LookupDomain r;
8217 struct dom_sid2 *sid = NULL;
8218 struct lsa_String n1;
8219 struct lsa_String n2;
8220 bool ret = true;
8221 struct dcerpc_binding_handle *b = p->binding_handle;
8223 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
8225 /* check for correct error codes */
8226 r.in.connect_handle = &ctx->handle;
8227 r.in.domain_name = &n2;
8228 r.out.sid = &sid;
8229 n2.string = NULL;
8231 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8232 "LookupDomain failed");
8233 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
8235 init_lsa_String(&n2, "xxNODOMAINxx");
8237 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8238 "LookupDomain failed");
8239 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
8241 r.in.connect_handle = &ctx->handle;
8243 init_lsa_String(&n1, domain);
8244 r.in.domain_name = &n1;
8246 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8247 "LookupDomain failed");
8248 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
8250 if (!test_GetDomPwInfo(p, tctx, &n1)) {
8251 ret = false;
8254 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
8255 ret = false;
8258 return ret;
8262 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
8263 struct torture_samr_context *ctx)
8265 struct samr_EnumDomains r;
8266 uint32_t resume_handle = 0;
8267 uint32_t num_entries = 0;
8268 struct samr_SamArray *sam = NULL;
8269 int i;
8270 bool ret = true;
8271 struct dcerpc_binding_handle *b = p->binding_handle;
8273 r.in.connect_handle = &ctx->handle;
8274 r.in.resume_handle = &resume_handle;
8275 r.in.buf_size = (uint32_t)-1;
8276 r.out.resume_handle = &resume_handle;
8277 r.out.num_entries = &num_entries;
8278 r.out.sam = &sam;
8280 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
8281 "EnumDomains failed");
8282 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
8284 if (!*r.out.sam) {
8285 return false;
8288 for (i=0;i<sam->count;i++) {
8289 if (!test_LookupDomain(p, tctx, ctx,
8290 sam->entries[i].name.string)) {
8291 ret = false;
8295 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
8296 "EnumDomains failed");
8297 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
8299 return ret;
8303 static bool test_Connect(struct dcerpc_binding_handle *b,
8304 struct torture_context *tctx,
8305 struct policy_handle *handle)
8307 struct samr_Connect r;
8308 struct samr_Connect2 r2;
8309 struct samr_Connect3 r3;
8310 struct samr_Connect4 r4;
8311 struct samr_Connect5 r5;
8312 union samr_ConnectInfo info;
8313 struct policy_handle h;
8314 uint32_t level_out = 0;
8315 bool ret = true, got_handle = false;
8317 torture_comment(tctx, "Testing samr_Connect\n");
8319 r.in.system_name = NULL;
8320 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8321 r.out.connect_handle = &h;
8323 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
8324 "Connect failed");
8325 if (!NT_STATUS_IS_OK(r.out.result)) {
8326 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
8327 ret = false;
8328 } else {
8329 got_handle = true;
8330 *handle = h;
8333 torture_comment(tctx, "Testing samr_Connect2\n");
8335 r2.in.system_name = NULL;
8336 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8337 r2.out.connect_handle = &h;
8339 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
8340 "Connect2 failed");
8341 if (!NT_STATUS_IS_OK(r2.out.result)) {
8342 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
8343 ret = false;
8344 } else {
8345 if (got_handle) {
8346 test_samr_handle_Close(b, tctx, handle);
8348 got_handle = true;
8349 *handle = h;
8352 torture_comment(tctx, "Testing samr_Connect3\n");
8354 r3.in.system_name = NULL;
8355 r3.in.unknown = 0;
8356 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8357 r3.out.connect_handle = &h;
8359 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
8360 "Connect3 failed");
8361 if (!NT_STATUS_IS_OK(r3.out.result)) {
8362 torture_result(tctx, TORTURE_FAIL, "Connect3 failed - %s\n", nt_errstr(r3.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 torture_comment(tctx, "Testing samr_Connect4\n");
8374 r4.in.system_name = "";
8375 r4.in.client_version = 0;
8376 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8377 r4.out.connect_handle = &h;
8379 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8380 "Connect4 failed");
8381 if (!NT_STATUS_IS_OK(r4.out.result)) {
8382 torture_result(tctx, TORTURE_FAIL, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8383 ret = false;
8384 } else {
8385 if (got_handle) {
8386 test_samr_handle_Close(b, tctx, handle);
8388 got_handle = true;
8389 *handle = h;
8392 torture_comment(tctx, "Testing samr_Connect5\n");
8394 info.info1.client_version = 0;
8395 info.info1.unknown2 = 0;
8397 r5.in.system_name = "";
8398 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8399 r5.in.level_in = 1;
8400 r5.out.level_out = &level_out;
8401 r5.in.info_in = &info;
8402 r5.out.info_out = &info;
8403 r5.out.connect_handle = &h;
8405 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
8406 "Connect5 failed");
8407 if (!NT_STATUS_IS_OK(r5.out.result)) {
8408 torture_result(tctx, TORTURE_FAIL, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
8409 ret = false;
8410 } else {
8411 if (got_handle) {
8412 test_samr_handle_Close(b, tctx, handle);
8414 got_handle = true;
8415 *handle = h;
8418 return ret;
8422 static bool test_samr_ValidatePassword(struct torture_context *tctx,
8423 struct dcerpc_pipe *p)
8425 struct samr_ValidatePassword r;
8426 union samr_ValidatePasswordReq req;
8427 union samr_ValidatePasswordRep *repp = NULL;
8428 NTSTATUS status;
8429 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
8430 int i;
8431 struct dcerpc_binding_handle *b = p->binding_handle;
8433 torture_comment(tctx, "Testing samr_ValidatePassword\n");
8435 if (p->conn->transport.transport != NCACN_IP_TCP) {
8436 torture_comment(tctx, "samr_ValidatePassword only should succeed over NCACN_IP_TCP!\n");
8439 ZERO_STRUCT(r);
8440 r.in.level = NetValidatePasswordReset;
8441 r.in.req = &req;
8442 r.out.rep = &repp;
8444 ZERO_STRUCT(req);
8445 req.req3.account.string = "non-existent-account-aklsdji";
8447 for (i=0; passwords[i]; i++) {
8448 req.req3.password.string = passwords[i];
8450 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
8451 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
8452 torture_skip(tctx, "ValidatePassword not supported by server\n");
8454 torture_assert_ntstatus_ok(tctx, status,
8455 "samr_ValidatePassword failed");
8456 torture_assert_ntstatus_ok(tctx, r.out.result,
8457 "samr_ValidatePassword failed");
8458 torture_comment(tctx, "Server %s password '%s' with code %i\n",
8459 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
8460 req.req3.password.string, repp->ctr3.status);
8463 return true;
8466 bool torture_rpc_samr(struct torture_context *torture)
8468 NTSTATUS status;
8469 struct dcerpc_pipe *p;
8470 bool ret = true;
8471 struct torture_samr_context *ctx;
8472 struct dcerpc_binding_handle *b;
8474 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8475 if (!NT_STATUS_IS_OK(status)) {
8476 return false;
8478 b = p->binding_handle;
8480 ctx = talloc_zero(torture, struct torture_samr_context);
8482 ctx->choice = TORTURE_SAMR_OTHER;
8484 ret &= test_Connect(b, torture, &ctx->handle);
8486 if (!torture_setting_bool(torture, "samba3", false)) {
8487 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8490 ret &= test_EnumDomains(p, torture, ctx);
8492 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8494 ret &= test_Shutdown(b, torture, &ctx->handle);
8496 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8498 return ret;
8502 bool torture_rpc_samr_users(struct torture_context *torture)
8504 NTSTATUS status;
8505 struct dcerpc_pipe *p;
8506 bool ret = true;
8507 struct torture_samr_context *ctx;
8508 struct dcerpc_binding_handle *b;
8510 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8511 if (!NT_STATUS_IS_OK(status)) {
8512 return false;
8514 b = p->binding_handle;
8516 ctx = talloc_zero(torture, struct torture_samr_context);
8518 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8520 ret &= test_Connect(b, torture, &ctx->handle);
8522 if (!torture_setting_bool(torture, "samba3", false)) {
8523 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8526 ret &= test_EnumDomains(p, torture, ctx);
8528 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8530 ret &= test_Shutdown(b, torture, &ctx->handle);
8532 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8534 return ret;
8538 bool torture_rpc_samr_passwords(struct torture_context *torture)
8540 NTSTATUS status;
8541 struct dcerpc_pipe *p;
8542 bool ret = true;
8543 struct torture_samr_context *ctx;
8544 struct dcerpc_binding_handle *b;
8546 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8547 if (!NT_STATUS_IS_OK(status)) {
8548 return false;
8550 b = p->binding_handle;
8552 ctx = talloc_zero(torture, struct torture_samr_context);
8554 ctx->choice = TORTURE_SAMR_PASSWORDS;
8556 ret &= test_Connect(b, torture, &ctx->handle);
8558 ret &= test_EnumDomains(p, torture, ctx);
8560 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8562 return ret;
8565 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8566 struct dcerpc_pipe *p2,
8567 struct cli_credentials *machine_credentials)
8569 NTSTATUS status;
8570 struct dcerpc_pipe *p;
8571 bool ret = true;
8572 struct torture_samr_context *ctx;
8573 struct dcerpc_binding_handle *b;
8575 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8576 if (!NT_STATUS_IS_OK(status)) {
8577 return false;
8579 b = p->binding_handle;
8581 ctx = talloc_zero(torture, struct torture_samr_context);
8583 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8584 ctx->machine_credentials = machine_credentials;
8586 ret &= test_Connect(b, torture, &ctx->handle);
8588 ret &= test_EnumDomains(p, torture, ctx);
8590 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8592 return ret;
8595 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8597 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8598 struct torture_rpc_tcase *tcase;
8600 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8601 &ndr_table_samr,
8602 TEST_ACCOUNT_NAME_PWD);
8604 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8605 torture_rpc_samr_pwdlastset);
8607 return suite;
8610 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8611 struct dcerpc_pipe *p2,
8612 struct cli_credentials *machine_credentials)
8614 NTSTATUS status;
8615 struct dcerpc_pipe *p;
8616 bool ret = true;
8617 struct torture_samr_context *ctx;
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 = talloc_zero(torture, struct torture_samr_context);
8628 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8629 ctx->machine_credentials = machine_credentials;
8631 ret &= test_Connect(b, torture, &ctx->handle);
8633 ret &= test_EnumDomains(p, torture, ctx);
8635 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8637 return ret;
8640 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8642 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8643 struct torture_rpc_tcase *tcase;
8645 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8646 &ndr_table_samr,
8647 TEST_ACCOUNT_NAME_PWD);
8649 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8650 torture_rpc_samr_users_privileges_delete_user);
8652 return suite;
8655 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8656 struct dcerpc_pipe *p2,
8657 void *data)
8659 NTSTATUS status;
8660 struct dcerpc_pipe *p;
8661 bool ret = true;
8662 struct torture_samr_context *ctx =
8663 talloc_get_type_abort(data, struct torture_samr_context);
8664 struct dcerpc_binding_handle *b;
8666 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8667 if (!NT_STATUS_IS_OK(status)) {
8668 return false;
8670 b = p->binding_handle;
8672 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8673 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8674 ctx->num_objects_large_dc);
8676 ret &= test_Connect(b, torture, &ctx->handle);
8678 ret &= test_EnumDomains(p, torture, ctx);
8680 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8682 return ret;
8685 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8686 struct dcerpc_pipe *p2,
8687 void *data)
8689 NTSTATUS status;
8690 struct dcerpc_pipe *p;
8691 bool ret = true;
8692 struct torture_samr_context *ctx =
8693 talloc_get_type_abort(data, struct torture_samr_context);
8694 struct dcerpc_binding_handle *b;
8696 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8697 if (!NT_STATUS_IS_OK(status)) {
8698 return false;
8700 b = p->binding_handle;
8702 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8703 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8704 ctx->num_objects_large_dc);
8706 ret &= test_Connect(b, torture, &ctx->handle);
8708 ret &= test_EnumDomains(p, torture, ctx);
8710 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8712 return ret;
8715 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8716 struct dcerpc_pipe *p2,
8717 void *data)
8719 NTSTATUS status;
8720 struct dcerpc_pipe *p;
8721 bool ret = true;
8722 struct torture_samr_context *ctx =
8723 talloc_get_type_abort(data, struct torture_samr_context);
8724 struct dcerpc_binding_handle *b;
8726 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8727 if (!NT_STATUS_IS_OK(status)) {
8728 return false;
8730 b = p->binding_handle;
8732 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8733 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8734 ctx->num_objects_large_dc);
8736 ret &= test_Connect(b, torture, &ctx->handle);
8738 ret &= test_EnumDomains(p, torture, ctx);
8740 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8742 return ret;
8745 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8747 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8748 struct torture_rpc_tcase *tcase;
8749 struct torture_samr_context *ctx;
8751 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8753 ctx = talloc_zero(suite, struct torture_samr_context);
8754 ctx->num_objects_large_dc = 150;
8756 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8757 torture_rpc_samr_many_aliases, ctx);
8758 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8759 torture_rpc_samr_many_groups, ctx);
8760 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8761 torture_rpc_samr_many_accounts, ctx);
8763 return suite;
8766 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8767 struct dcerpc_pipe *p2,
8768 struct cli_credentials *machine_credentials)
8770 NTSTATUS status;
8771 struct dcerpc_pipe *p;
8772 bool ret = true;
8773 struct torture_samr_context *ctx;
8774 struct dcerpc_binding_handle *b;
8776 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8777 if (!NT_STATUS_IS_OK(status)) {
8778 return false;
8780 b = p->binding_handle;
8782 ctx = talloc_zero(torture, struct torture_samr_context);
8784 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8785 ctx->machine_credentials = machine_credentials;
8787 ret &= test_Connect(b, torture, &ctx->handle);
8789 ret &= test_EnumDomains(p, torture, ctx);
8791 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8793 return ret;
8796 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8798 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8799 struct torture_rpc_tcase *tcase;
8801 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8802 &ndr_table_samr,
8803 TEST_ACCOUNT_NAME_PWD);
8805 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8806 torture_rpc_samr_badpwdcount);
8808 return suite;
8811 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8812 struct dcerpc_pipe *p2,
8813 struct cli_credentials *machine_credentials)
8815 NTSTATUS status;
8816 struct dcerpc_pipe *p;
8817 bool ret = true;
8818 struct torture_samr_context *ctx;
8819 struct dcerpc_binding_handle *b;
8821 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8822 if (!NT_STATUS_IS_OK(status)) {
8823 return false;
8825 b = p->binding_handle;
8827 ctx = talloc_zero(torture, struct torture_samr_context);
8829 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8830 ctx->machine_credentials = machine_credentials;
8832 ret &= test_Connect(b, torture, &ctx->handle);
8834 ret &= test_EnumDomains(p, torture, ctx);
8836 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8838 return ret;
8841 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8843 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8844 struct torture_rpc_tcase *tcase;
8846 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8847 &ndr_table_samr,
8848 TEST_ACCOUNT_NAME_PWD);
8850 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8851 torture_rpc_samr_lockout);
8853 return suite;
8856 struct torture_suite *torture_rpc_samr_passwords_validate(TALLOC_CTX *mem_ctx)
8858 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.validate");
8859 struct torture_rpc_tcase *tcase;
8861 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
8862 &ndr_table_samr);
8863 torture_rpc_tcase_add_test(tcase, "validate",
8864 test_samr_ValidatePassword);
8866 return suite;