libcli/cldap: make use of samba_tevent_context_init()
[Samba/gebeck_regimport.git] / source4 / torture / rpc / samr.c
blob6a4f653f2c031a1acfe1e41df21a36d9fa396920
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/schannel.h"
41 #include "auth/gensec/gensec_proto.h"
42 #include "../libcli/auth/schannel.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_comment(tctx, #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 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
255 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
256 #field, s2, __location__); \
257 ret = false; \
258 break; \
261 #define MEM_EQUAL(s1, s2, length, field) \
262 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
263 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
264 #field, (const char *)s2, __location__); \
265 ret = false; \
266 break; \
269 #define INT_EQUAL(i1, i2, field) \
270 if (i1 != i2) { \
271 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
272 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
273 ret = false; \
274 break; \
277 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
278 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
279 q.in.level = lvl1; \
280 TESTCALL(QueryUserInfo, q) \
281 s.in.level = lvl1; \
282 s2.in.level = lvl1; \
283 u = *info; \
284 if (lvl1 == 21) { \
285 ZERO_STRUCT(u.info21); \
286 u.info21.fields_present = fpval; \
288 init_lsa_String(&u.info ## lvl1.field1, value); \
289 TESTCALL(SetUserInfo, s) \
290 TESTCALL(SetUserInfo2, s2) \
291 init_lsa_String(&u.info ## lvl1.field1, ""); \
292 TESTCALL(QueryUserInfo, q); \
293 u = *info; \
294 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
295 q.in.level = lvl2; \
296 TESTCALL(QueryUserInfo, q) \
297 u = *info; \
298 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
299 } while (0)
301 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
302 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
303 q.in.level = lvl1; \
304 TESTCALL(QueryUserInfo, q) \
305 s.in.level = lvl1; \
306 s2.in.level = lvl1; \
307 u = *info; \
308 if (lvl1 == 21) { \
309 ZERO_STRUCT(u.info21); \
310 u.info21.fields_present = fpval; \
312 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
313 TESTCALL(SetUserInfo, s) \
314 TESTCALL(SetUserInfo2, s2) \
315 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
316 TESTCALL(QueryUserInfo, q); \
317 u = *info; \
318 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
319 q.in.level = lvl2; \
320 TESTCALL(QueryUserInfo, q) \
321 u = *info; \
322 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
323 } while (0)
325 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
326 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
327 q.in.level = lvl1; \
328 TESTCALL(QueryUserInfo, q) \
329 s.in.level = lvl1; \
330 s2.in.level = lvl1; \
331 u = *info; \
332 if (lvl1 == 21) { \
333 uint8_t *bits = u.info21.logon_hours.bits; \
334 ZERO_STRUCT(u.info21); \
335 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
336 u.info21.logon_hours.units_per_week = 168; \
337 u.info21.logon_hours.bits = bits; \
339 u.info21.fields_present = fpval; \
341 u.info ## lvl1.field1 = value; \
342 TESTCALL(SetUserInfo, s) \
343 TESTCALL(SetUserInfo2, s2) \
344 u.info ## lvl1.field1 = 0; \
345 TESTCALL(QueryUserInfo, q); \
346 u = *info; \
347 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
348 q.in.level = lvl2; \
349 TESTCALL(QueryUserInfo, q) \
350 u = *info; \
351 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
352 } while (0)
354 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
355 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
356 } while (0)
358 q0.in.level = 12;
359 do { TESTCALL(QueryUserInfo, q0) } while (0);
361 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
362 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
363 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
364 SAMR_FIELD_COMMENT);
366 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
367 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
368 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
369 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
370 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
371 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
372 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
373 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
374 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
375 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
376 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
377 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
378 test_account_name = base_account_name;
379 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
380 SAMR_FIELD_ACCOUNT_NAME);
382 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
383 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
384 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
385 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
386 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
387 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
388 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
389 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
390 SAMR_FIELD_FULL_NAME);
392 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
393 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
394 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
395 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
396 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
397 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
398 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
399 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
400 SAMR_FIELD_FULL_NAME);
402 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
403 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
404 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
405 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
406 SAMR_FIELD_LOGON_SCRIPT);
408 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
409 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
410 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
411 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
412 SAMR_FIELD_PROFILE_PATH);
414 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
415 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
416 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
417 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
418 SAMR_FIELD_HOME_DIRECTORY);
419 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
420 SAMR_FIELD_HOME_DIRECTORY);
422 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
423 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
424 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
425 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
426 SAMR_FIELD_HOME_DRIVE);
427 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
428 SAMR_FIELD_HOME_DRIVE);
430 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
431 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
432 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
433 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
434 SAMR_FIELD_DESCRIPTION);
436 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
437 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
438 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
439 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
440 SAMR_FIELD_WORKSTATIONS);
441 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
442 SAMR_FIELD_WORKSTATIONS);
443 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
444 SAMR_FIELD_WORKSTATIONS);
445 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
446 SAMR_FIELD_WORKSTATIONS);
448 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
449 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
450 SAMR_FIELD_PARAMETERS);
451 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
452 SAMR_FIELD_PARAMETERS);
453 /* also empty user parameters are allowed */
454 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
455 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
456 SAMR_FIELD_PARAMETERS);
457 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
458 SAMR_FIELD_PARAMETERS);
460 /* Samba 3 cannot store country_code and code_page atm. - gd */
461 if (!torture_setting_bool(tctx, "samba3", false)) {
462 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
463 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
464 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
465 SAMR_FIELD_COUNTRY_CODE);
466 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
467 SAMR_FIELD_COUNTRY_CODE);
469 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
470 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
471 SAMR_FIELD_CODE_PAGE);
472 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
473 SAMR_FIELD_CODE_PAGE);
476 if (!torture_setting_bool(tctx, "samba3", false)) {
477 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
478 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
479 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
480 SAMR_FIELD_ACCT_EXPIRY);
481 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
482 SAMR_FIELD_ACCT_EXPIRY);
483 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
484 SAMR_FIELD_ACCT_EXPIRY);
485 } else {
486 /* Samba 3 can only store seconds / time_t in passdb - gd */
487 NTTIME nt;
488 unix_to_nt_time(&nt, time(NULL) + __LINE__);
489 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
490 unix_to_nt_time(&nt, time(NULL) + __LINE__);
491 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
492 unix_to_nt_time(&nt, time(NULL) + __LINE__);
493 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
494 unix_to_nt_time(&nt, time(NULL) + __LINE__);
495 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
496 unix_to_nt_time(&nt, time(NULL) + __LINE__);
497 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
500 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
501 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
502 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
503 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
504 SAMR_FIELD_LOGON_HOURS);
506 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
507 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
508 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
510 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
511 (base_acct_flags | ACB_DISABLED),
512 (base_acct_flags | ACB_DISABLED | user_extra_flags),
515 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
516 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
517 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
518 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
520 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
521 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
522 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
526 /* The 'autolock' flag doesn't stick - check this */
527 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
528 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
529 (base_acct_flags | ACB_DISABLED | user_extra_flags),
531 #if 0
532 /* Removing the 'disabled' flag doesn't stick - check this */
533 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
534 (base_acct_flags),
535 (base_acct_flags | ACB_DISABLED | user_extra_flags),
537 #endif
539 /* Samba3 cannot store these atm */
540 if (!torture_setting_bool(tctx, "samba3", false)) {
541 /* The 'store plaintext' flag does stick */
542 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
543 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
544 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
546 /* The 'use DES' flag does stick */
547 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
548 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
549 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
551 /* The 'don't require kerberos pre-authentication flag does stick */
552 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
553 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
554 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
556 /* The 'no kerberos PAC required' flag sticks */
557 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
558 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
559 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
562 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
563 (base_acct_flags | ACB_DISABLED),
564 (base_acct_flags | ACB_DISABLED | user_extra_flags),
565 SAMR_FIELD_ACCT_FLAGS);
567 #if 0
568 /* these fail with win2003 - it appears you can't set the primary gid?
569 the set succeeds, but the gid isn't changed. Very weird! */
570 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
571 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
572 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
573 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
574 #endif
576 return ret;
580 generate a random password for password change tests
582 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
584 size_t len = MAX(8, min_len);
585 char *s = generate_random_password(mem_ctx, len, len+6);
586 return s;
589 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
591 char *s = samr_rand_pass_silent(mem_ctx, min_len);
592 printf("Generated password '%s'\n", s);
593 return s;
598 generate a random password for password change tests
600 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
602 int i;
603 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
604 generate_random_buffer(password.data, password.length);
606 for (i=0; i < len; i++) {
607 if (((uint16_t *)password.data)[i] == 0) {
608 ((uint16_t *)password.data)[i] = 1;
612 return password;
616 generate a random password for password change tests (fixed length)
618 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
620 char *s = generate_random_password(mem_ctx, len, len);
621 printf("Generated password '%s'\n", s);
622 return s;
625 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
626 struct policy_handle *handle, char **password)
628 NTSTATUS status;
629 struct samr_SetUserInfo s;
630 union samr_UserInfo u;
631 bool ret = true;
632 DATA_BLOB session_key;
633 char *newpass;
634 struct dcerpc_binding_handle *b = p->binding_handle;
635 struct samr_GetUserPwInfo pwp;
636 struct samr_PwInfo info;
637 int policy_min_pw_len = 0;
638 pwp.in.user_handle = handle;
639 pwp.out.info = &info;
641 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
642 "GetUserPwInfo failed");
643 if (NT_STATUS_IS_OK(pwp.out.result)) {
644 policy_min_pw_len = pwp.out.info->min_password_length;
646 newpass = samr_rand_pass(tctx, policy_min_pw_len);
648 s.in.user_handle = handle;
649 s.in.info = &u;
650 s.in.level = 24;
652 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
653 u.info24.password_expired = 0;
655 status = dcerpc_fetch_session_key(p, &session_key);
656 if (!NT_STATUS_IS_OK(status)) {
657 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
658 s.in.level, nt_errstr(status));
659 return false;
662 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
664 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
666 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
667 "SetUserInfo failed");
668 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
669 __location__, __FUNCTION__,
670 newpass, nt_errstr(s.out.result));
671 if (!NT_STATUS_IS_OK(s.out.result)) {
672 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
673 s.in.level, nt_errstr(s.out.result));
674 ret = false;
675 } else {
676 *password = newpass;
679 return ret;
683 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
684 struct policy_handle *handle, uint32_t fields_present,
685 char **password)
687 NTSTATUS status;
688 struct samr_SetUserInfo s;
689 union samr_UserInfo u;
690 bool ret = true;
691 DATA_BLOB session_key;
692 struct dcerpc_binding_handle *b = p->binding_handle;
693 char *newpass;
694 struct samr_GetUserPwInfo pwp;
695 struct samr_PwInfo info;
696 int policy_min_pw_len = 0;
697 pwp.in.user_handle = handle;
698 pwp.out.info = &info;
700 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
701 "GetUserPwInfo failed");
702 if (NT_STATUS_IS_OK(pwp.out.result)) {
703 policy_min_pw_len = pwp.out.info->min_password_length;
705 newpass = samr_rand_pass(tctx, policy_min_pw_len);
707 s.in.user_handle = handle;
708 s.in.info = &u;
709 s.in.level = 23;
711 ZERO_STRUCT(u);
713 u.info23.info.fields_present = fields_present;
715 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
717 status = dcerpc_fetch_session_key(p, &session_key);
718 if (!NT_STATUS_IS_OK(status)) {
719 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
720 s.in.level, nt_errstr(status));
721 return false;
724 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
726 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
728 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
729 "SetUserInfo failed");
730 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
731 __location__, __FUNCTION__,
732 newpass, nt_errstr(s.out.result));
733 if (!NT_STATUS_IS_OK(s.out.result)) {
734 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
735 s.in.level, nt_errstr(s.out.result));
736 ret = false;
737 } else {
738 *password = newpass;
741 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
743 status = dcerpc_fetch_session_key(p, &session_key);
744 if (!NT_STATUS_IS_OK(status)) {
745 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
746 s.in.level, nt_errstr(status));
747 return false;
750 /* This should break the key nicely */
751 session_key.length--;
752 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
754 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
756 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
757 "SetUserInfo failed");
758 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
759 __location__, __FUNCTION__,
760 newpass, nt_errstr(s.out.result));
761 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
762 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
763 s.in.level, nt_errstr(s.out.result));
764 ret = false;
767 return ret;
771 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
772 struct policy_handle *handle, bool makeshort,
773 char **password)
775 NTSTATUS status;
776 struct samr_SetUserInfo s;
777 union samr_UserInfo u;
778 bool ret = true;
779 DATA_BLOB session_key;
780 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
781 uint8_t confounder[16];
782 char *newpass;
783 struct dcerpc_binding_handle *b = p->binding_handle;
784 struct MD5Context ctx;
785 struct samr_GetUserPwInfo pwp;
786 struct samr_PwInfo info;
787 int policy_min_pw_len = 0;
788 pwp.in.user_handle = handle;
789 pwp.out.info = &info;
791 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
792 "GetUserPwInfo failed");
793 if (NT_STATUS_IS_OK(pwp.out.result)) {
794 policy_min_pw_len = pwp.out.info->min_password_length;
796 if (makeshort && policy_min_pw_len) {
797 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
798 } else {
799 newpass = samr_rand_pass(tctx, policy_min_pw_len);
802 s.in.user_handle = handle;
803 s.in.info = &u;
804 s.in.level = 26;
806 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
807 u.info26.password_expired = 0;
809 status = dcerpc_fetch_session_key(p, &session_key);
810 if (!NT_STATUS_IS_OK(status)) {
811 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
812 s.in.level, nt_errstr(status));
813 return false;
816 generate_random_buffer((uint8_t *)confounder, 16);
818 MD5Init(&ctx);
819 MD5Update(&ctx, confounder, 16);
820 MD5Update(&ctx, session_key.data, session_key.length);
821 MD5Final(confounded_session_key.data, &ctx);
823 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
824 memcpy(&u.info26.password.data[516], confounder, 16);
826 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
828 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
829 "SetUserInfo failed");
830 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
831 __location__, __FUNCTION__,
832 newpass, nt_errstr(s.out.result));
833 if (!NT_STATUS_IS_OK(s.out.result)) {
834 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
835 s.in.level, nt_errstr(s.out.result));
836 ret = false;
837 } else {
838 *password = newpass;
841 /* This should break the key nicely */
842 confounded_session_key.data[0]++;
844 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
845 memcpy(&u.info26.password.data[516], confounder, 16);
847 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
849 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
850 "SetUserInfo failed");
851 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
852 __location__, __FUNCTION__,
853 newpass, nt_errstr(s.out.result));
854 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
855 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
856 s.in.level, nt_errstr(s.out.result));
857 ret = false;
858 } else {
859 *password = newpass;
862 return ret;
865 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
866 struct policy_handle *handle, uint32_t fields_present,
867 char **password)
869 NTSTATUS status;
870 struct samr_SetUserInfo s;
871 union samr_UserInfo u;
872 bool ret = true;
873 DATA_BLOB session_key;
874 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
875 struct MD5Context ctx;
876 uint8_t confounder[16];
877 char *newpass;
878 struct dcerpc_binding_handle *b = p->binding_handle;
879 struct samr_GetUserPwInfo pwp;
880 struct samr_PwInfo info;
881 int policy_min_pw_len = 0;
882 pwp.in.user_handle = handle;
883 pwp.out.info = &info;
885 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
886 "GetUserPwInfo failed");
887 if (NT_STATUS_IS_OK(pwp.out.result)) {
888 policy_min_pw_len = pwp.out.info->min_password_length;
890 newpass = samr_rand_pass(tctx, policy_min_pw_len);
892 s.in.user_handle = handle;
893 s.in.info = &u;
894 s.in.level = 25;
896 ZERO_STRUCT(u);
898 u.info25.info.fields_present = fields_present;
900 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
902 status = dcerpc_fetch_session_key(p, &session_key);
903 if (!NT_STATUS_IS_OK(status)) {
904 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
905 s.in.level, nt_errstr(status));
906 return false;
909 generate_random_buffer((uint8_t *)confounder, 16);
911 MD5Init(&ctx);
912 MD5Update(&ctx, confounder, 16);
913 MD5Update(&ctx, session_key.data, session_key.length);
914 MD5Final(confounded_session_key.data, &ctx);
916 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
917 memcpy(&u.info25.password.data[516], confounder, 16);
919 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
921 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
922 "SetUserInfo failed");
923 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
924 __location__, __FUNCTION__,
925 newpass, nt_errstr(s.out.result));
926 if (!NT_STATUS_IS_OK(s.out.result)) {
927 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
928 s.in.level, nt_errstr(s.out.result));
929 ret = false;
930 } else {
931 *password = newpass;
934 /* This should break the key nicely */
935 confounded_session_key.data[0]++;
937 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
938 memcpy(&u.info25.password.data[516], confounder, 16);
940 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
942 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
943 "SetUserInfo failed");
944 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
945 __location__, __FUNCTION__,
946 newpass, nt_errstr(s.out.result));
947 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
948 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
949 s.in.level, nt_errstr(s.out.result));
950 ret = false;
953 return ret;
956 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
957 struct policy_handle *handle, char **password)
959 NTSTATUS status;
960 struct samr_SetUserInfo s;
961 union samr_UserInfo u;
962 bool ret = true;
963 DATA_BLOB session_key;
964 char *newpass;
965 struct dcerpc_binding_handle *b = p->binding_handle;
966 struct samr_GetUserPwInfo pwp;
967 struct samr_PwInfo info;
968 int policy_min_pw_len = 0;
969 uint8_t lm_hash[16], nt_hash[16];
971 pwp.in.user_handle = handle;
972 pwp.out.info = &info;
974 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
975 "GetUserPwInfo failed");
976 if (NT_STATUS_IS_OK(pwp.out.result)) {
977 policy_min_pw_len = pwp.out.info->min_password_length;
979 newpass = samr_rand_pass(tctx, policy_min_pw_len);
981 s.in.user_handle = handle;
982 s.in.info = &u;
983 s.in.level = 18;
985 ZERO_STRUCT(u);
987 u.info18.nt_pwd_active = true;
988 u.info18.lm_pwd_active = true;
990 E_md4hash(newpass, nt_hash);
991 E_deshash(newpass, lm_hash);
993 status = dcerpc_fetch_session_key(p, &session_key);
994 if (!NT_STATUS_IS_OK(status)) {
995 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
996 s.in.level, nt_errstr(status));
997 return false;
1001 DATA_BLOB in,out;
1002 in = data_blob_const(nt_hash, 16);
1003 out = data_blob_talloc_zero(tctx, 16);
1004 sess_crypt_blob(&out, &in, &session_key, true);
1005 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1008 DATA_BLOB in,out;
1009 in = data_blob_const(lm_hash, 16);
1010 out = data_blob_talloc_zero(tctx, 16);
1011 sess_crypt_blob(&out, &in, &session_key, true);
1012 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1015 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
1017 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1018 "SetUserInfo failed");
1019 if (!NT_STATUS_IS_OK(s.out.result)) {
1020 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1021 s.in.level, nt_errstr(s.out.result));
1022 ret = false;
1023 } else {
1024 *password = newpass;
1027 return ret;
1030 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1031 struct policy_handle *handle, uint32_t fields_present,
1032 char **password)
1034 NTSTATUS status;
1035 struct samr_SetUserInfo s;
1036 union samr_UserInfo u;
1037 bool ret = true;
1038 DATA_BLOB session_key;
1039 char *newpass;
1040 struct dcerpc_binding_handle *b = p->binding_handle;
1041 struct samr_GetUserPwInfo pwp;
1042 struct samr_PwInfo info;
1043 int policy_min_pw_len = 0;
1044 uint8_t lm_hash[16], nt_hash[16];
1046 pwp.in.user_handle = handle;
1047 pwp.out.info = &info;
1049 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1050 "GetUserPwInfo failed");
1051 if (NT_STATUS_IS_OK(pwp.out.result)) {
1052 policy_min_pw_len = pwp.out.info->min_password_length;
1054 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1056 s.in.user_handle = handle;
1057 s.in.info = &u;
1058 s.in.level = 21;
1060 E_md4hash(newpass, nt_hash);
1061 E_deshash(newpass, lm_hash);
1063 ZERO_STRUCT(u);
1065 u.info21.fields_present = fields_present;
1067 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1068 u.info21.lm_owf_password.length = 16;
1069 u.info21.lm_owf_password.size = 16;
1070 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1071 u.info21.lm_password_set = true;
1074 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1075 u.info21.nt_owf_password.length = 16;
1076 u.info21.nt_owf_password.size = 16;
1077 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1078 u.info21.nt_password_set = true;
1081 status = dcerpc_fetch_session_key(p, &session_key);
1082 if (!NT_STATUS_IS_OK(status)) {
1083 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1084 s.in.level, nt_errstr(status));
1085 return false;
1088 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1089 DATA_BLOB in,out;
1090 in = data_blob_const(u.info21.lm_owf_password.array,
1091 u.info21.lm_owf_password.length);
1092 out = data_blob_talloc_zero(tctx, 16);
1093 sess_crypt_blob(&out, &in, &session_key, true);
1094 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1097 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1098 DATA_BLOB in,out;
1099 in = data_blob_const(u.info21.nt_owf_password.array,
1100 u.info21.nt_owf_password.length);
1101 out = data_blob_talloc_zero(tctx, 16);
1102 sess_crypt_blob(&out, &in, &session_key, true);
1103 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1106 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1108 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1109 "SetUserInfo failed");
1110 if (!NT_STATUS_IS_OK(s.out.result)) {
1111 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1112 s.in.level, nt_errstr(s.out.result));
1113 ret = false;
1114 } else {
1115 *password = newpass;
1118 /* try invalid length */
1119 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1121 u.info21.nt_owf_password.length++;
1123 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1124 "SetUserInfo failed");
1125 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1126 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1127 s.in.level, nt_errstr(s.out.result));
1128 ret = false;
1132 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1134 u.info21.lm_owf_password.length++;
1136 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1137 "SetUserInfo failed");
1138 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1139 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1140 s.in.level, nt_errstr(s.out.result));
1141 ret = false;
1145 return ret;
1148 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1149 struct torture_context *tctx,
1150 struct policy_handle *handle,
1151 uint16_t level,
1152 uint32_t fields_present,
1153 char **password, uint8_t password_expired,
1154 bool use_setinfo2,
1155 bool *matched_expected_error)
1157 NTSTATUS status;
1158 NTSTATUS expected_error = NT_STATUS_OK;
1159 struct samr_SetUserInfo s;
1160 struct samr_SetUserInfo2 s2;
1161 union samr_UserInfo u;
1162 bool ret = true;
1163 DATA_BLOB session_key;
1164 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1165 struct MD5Context ctx;
1166 uint8_t confounder[16];
1167 char *newpass;
1168 struct dcerpc_binding_handle *b = p->binding_handle;
1169 struct samr_GetUserPwInfo pwp;
1170 struct samr_PwInfo info;
1171 int policy_min_pw_len = 0;
1172 const char *comment = NULL;
1173 uint8_t lm_hash[16], nt_hash[16];
1175 pwp.in.user_handle = handle;
1176 pwp.out.info = &info;
1178 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1179 "GetUserPwInfo failed");
1180 if (NT_STATUS_IS_OK(pwp.out.result)) {
1181 policy_min_pw_len = pwp.out.info->min_password_length;
1183 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1185 if (use_setinfo2) {
1186 s2.in.user_handle = handle;
1187 s2.in.info = &u;
1188 s2.in.level = level;
1189 } else {
1190 s.in.user_handle = handle;
1191 s.in.info = &u;
1192 s.in.level = level;
1195 if (fields_present & SAMR_FIELD_COMMENT) {
1196 comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
1199 ZERO_STRUCT(u);
1201 switch (level) {
1202 case 18:
1203 E_md4hash(newpass, nt_hash);
1204 E_deshash(newpass, lm_hash);
1206 u.info18.nt_pwd_active = true;
1207 u.info18.lm_pwd_active = true;
1208 u.info18.password_expired = password_expired;
1210 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1211 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1213 break;
1214 case 21:
1215 E_md4hash(newpass, nt_hash);
1216 E_deshash(newpass, lm_hash);
1218 u.info21.fields_present = fields_present;
1219 u.info21.password_expired = password_expired;
1220 u.info21.comment.string = comment;
1222 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1223 u.info21.lm_owf_password.length = 16;
1224 u.info21.lm_owf_password.size = 16;
1225 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1226 u.info21.lm_password_set = true;
1229 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1230 u.info21.nt_owf_password.length = 16;
1231 u.info21.nt_owf_password.size = 16;
1232 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1233 u.info21.nt_password_set = true;
1236 break;
1237 case 23:
1238 u.info23.info.fields_present = fields_present;
1239 u.info23.info.password_expired = password_expired;
1240 u.info23.info.comment.string = comment;
1242 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1244 break;
1245 case 24:
1246 u.info24.password_expired = password_expired;
1248 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1250 break;
1251 case 25:
1252 u.info25.info.fields_present = fields_present;
1253 u.info25.info.password_expired = password_expired;
1254 u.info25.info.comment.string = comment;
1256 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1258 break;
1259 case 26:
1260 u.info26.password_expired = password_expired;
1262 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1264 break;
1267 status = dcerpc_fetch_session_key(p, &session_key);
1268 if (!NT_STATUS_IS_OK(status)) {
1269 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1270 s.in.level, nt_errstr(status));
1271 return false;
1274 generate_random_buffer((uint8_t *)confounder, 16);
1276 MD5Init(&ctx);
1277 MD5Update(&ctx, confounder, 16);
1278 MD5Update(&ctx, session_key.data, session_key.length);
1279 MD5Final(confounded_session_key.data, &ctx);
1281 switch (level) {
1282 case 18:
1284 DATA_BLOB in,out;
1285 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1286 out = data_blob_talloc_zero(tctx, 16);
1287 sess_crypt_blob(&out, &in, &session_key, true);
1288 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1291 DATA_BLOB in,out;
1292 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1293 out = data_blob_talloc_zero(tctx, 16);
1294 sess_crypt_blob(&out, &in, &session_key, true);
1295 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1298 break;
1299 case 21:
1300 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1301 DATA_BLOB in,out;
1302 in = data_blob_const(u.info21.lm_owf_password.array,
1303 u.info21.lm_owf_password.length);
1304 out = data_blob_talloc_zero(tctx, 16);
1305 sess_crypt_blob(&out, &in, &session_key, true);
1306 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1308 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1309 DATA_BLOB in,out;
1310 in = data_blob_const(u.info21.nt_owf_password.array,
1311 u.info21.nt_owf_password.length);
1312 out = data_blob_talloc_zero(tctx, 16);
1313 sess_crypt_blob(&out, &in, &session_key, true);
1314 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1316 break;
1317 case 23:
1318 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1319 break;
1320 case 24:
1321 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1322 break;
1323 case 25:
1324 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1325 memcpy(&u.info25.password.data[516], confounder, 16);
1326 break;
1327 case 26:
1328 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1329 memcpy(&u.info26.password.data[516], confounder, 16);
1330 break;
1333 if (use_setinfo2) {
1334 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1335 "SetUserInfo2 failed");
1336 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1337 __location__, __FUNCTION__,
1338 newpass, nt_errstr(s2.out.result));
1339 status = s2.out.result;
1340 } else {
1341 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1342 "SetUserInfo failed");
1343 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1344 __location__, __FUNCTION__,
1345 newpass, nt_errstr(s.out.result));
1346 status = s.out.result;
1349 if (!NT_STATUS_IS_OK(status)) {
1350 if (fields_present == 0) {
1351 expected_error = NT_STATUS_INVALID_PARAMETER;
1353 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1354 expected_error = NT_STATUS_ACCESS_DENIED;
1358 if (!NT_STATUS_IS_OK(expected_error)) {
1359 if (use_setinfo2) {
1360 torture_assert_ntstatus_equal(tctx,
1361 s2.out.result,
1362 expected_error, "SetUserInfo2 failed");
1363 } else {
1364 torture_assert_ntstatus_equal(tctx,
1365 s.out.result,
1366 expected_error, "SetUserInfo failed");
1368 *matched_expected_error = true;
1369 return true;
1372 if (!NT_STATUS_IS_OK(status)) {
1373 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1374 use_setinfo2 ? "2":"", level, nt_errstr(status));
1375 ret = false;
1376 } else {
1377 *password = newpass;
1380 return ret;
1383 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1384 struct torture_context *tctx,
1385 struct policy_handle *handle)
1387 struct samr_SetAliasInfo r;
1388 struct samr_QueryAliasInfo q;
1389 union samr_AliasInfo *info;
1390 uint16_t levels[] = {2, 3};
1391 int i;
1392 bool ret = true;
1394 /* Ignoring switch level 1, as that includes the number of members for the alias
1395 * and setting this to a wrong value might have negative consequences
1398 for (i=0;i<ARRAY_SIZE(levels);i++) {
1399 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1401 r.in.alias_handle = handle;
1402 r.in.level = levels[i];
1403 r.in.info = talloc(tctx, union samr_AliasInfo);
1404 switch (r.in.level) {
1405 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1406 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1407 "Test Description, should test I18N as well"); break;
1408 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1411 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1412 "SetAliasInfo failed");
1413 if (!NT_STATUS_IS_OK(r.out.result)) {
1414 torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1415 levels[i], nt_errstr(r.out.result));
1416 ret = false;
1419 q.in.alias_handle = handle;
1420 q.in.level = levels[i];
1421 q.out.info = &info;
1423 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1424 "QueryAliasInfo failed");
1425 if (!NT_STATUS_IS_OK(q.out.result)) {
1426 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1427 levels[i], nt_errstr(q.out.result));
1428 ret = false;
1432 return ret;
1435 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1436 struct torture_context *tctx,
1437 struct policy_handle *user_handle)
1439 struct samr_GetGroupsForUser r;
1440 struct samr_RidWithAttributeArray *rids = NULL;
1442 torture_comment(tctx, "Testing GetGroupsForUser\n");
1444 r.in.user_handle = user_handle;
1445 r.out.rids = &rids;
1447 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1448 "GetGroupsForUser failed");
1449 torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1451 return true;
1455 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1456 struct lsa_String *domain_name)
1458 struct samr_GetDomPwInfo r;
1459 struct samr_PwInfo info;
1460 struct dcerpc_binding_handle *b = p->binding_handle;
1462 r.in.domain_name = domain_name;
1463 r.out.info = &info;
1465 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1467 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1468 "GetDomPwInfo failed");
1469 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1471 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1472 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1474 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1475 "GetDomPwInfo failed");
1476 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1478 r.in.domain_name->string = "\\\\__NONAME__";
1479 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1481 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1482 "GetDomPwInfo failed");
1483 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1485 r.in.domain_name->string = "\\\\Builtin";
1486 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1488 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1489 "GetDomPwInfo failed");
1490 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1492 return true;
1495 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1496 struct torture_context *tctx,
1497 struct policy_handle *handle)
1499 struct samr_GetUserPwInfo r;
1500 struct samr_PwInfo info;
1502 torture_comment(tctx, "Testing GetUserPwInfo\n");
1504 r.in.user_handle = handle;
1505 r.out.info = &info;
1507 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1508 "GetUserPwInfo failed");
1509 torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1511 return true;
1514 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1515 struct torture_context *tctx,
1516 struct policy_handle *domain_handle, const char *name,
1517 uint32_t *rid)
1519 NTSTATUS status;
1520 struct samr_LookupNames n;
1521 struct lsa_String sname[2];
1522 struct samr_Ids rids, types;
1524 init_lsa_String(&sname[0], name);
1526 n.in.domain_handle = domain_handle;
1527 n.in.num_names = 1;
1528 n.in.names = sname;
1529 n.out.rids = &rids;
1530 n.out.types = &types;
1531 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 return status;
1535 if (NT_STATUS_IS_OK(n.out.result)) {
1536 *rid = n.out.rids->ids[0];
1537 } else {
1538 return n.out.result;
1541 init_lsa_String(&sname[1], "xxNONAMExx");
1542 n.in.num_names = 2;
1543 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 return status;
1547 if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1548 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1549 if (NT_STATUS_IS_OK(n.out.result)) {
1550 return NT_STATUS_UNSUCCESSFUL;
1552 return n.out.result;
1555 n.in.num_names = 0;
1556 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1557 if (!NT_STATUS_IS_OK(status)) {
1558 return status;
1560 if (!NT_STATUS_IS_OK(n.out.result)) {
1561 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1562 return n.out.result;
1565 init_lsa_String(&sname[0], "xxNONAMExx");
1566 n.in.num_names = 1;
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_warning(tctx, "LookupNames[1 bad name] 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 init_lsa_String(&sname[0], "xxNONAMExx");
1580 init_lsa_String(&sname[1], "xxNONAME2xx");
1581 n.in.num_names = 2;
1582 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1583 if (!NT_STATUS_IS_OK(status)) {
1584 return status;
1586 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1587 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1588 if (NT_STATUS_IS_OK(n.out.result)) {
1589 return NT_STATUS_UNSUCCESSFUL;
1591 return n.out.result;
1594 return NT_STATUS_OK;
1597 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1598 struct torture_context *tctx,
1599 struct policy_handle *domain_handle,
1600 const char *name, struct policy_handle *user_handle)
1602 NTSTATUS status;
1603 struct samr_OpenUser r;
1604 uint32_t rid;
1606 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 return status;
1611 r.in.domain_handle = domain_handle;
1612 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1613 r.in.rid = rid;
1614 r.out.user_handle = user_handle;
1615 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 return status;
1619 if (!NT_STATUS_IS_OK(r.out.result)) {
1620 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1623 return r.out.result;
1626 #if 0
1627 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1628 struct torture_context *tctx,
1629 struct policy_handle *handle)
1631 NTSTATUS status;
1632 struct samr_ChangePasswordUser r;
1633 bool ret = true;
1634 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1635 struct policy_handle user_handle;
1636 char *oldpass = "test";
1637 char *newpass = "test2";
1638 uint8_t old_nt_hash[16], new_nt_hash[16];
1639 uint8_t old_lm_hash[16], new_lm_hash[16];
1641 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 return false;
1646 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1648 torture_comment(tctx, "old password: %s\n", oldpass);
1649 torture_comment(tctx, "new password: %s\n", newpass);
1651 E_md4hash(oldpass, old_nt_hash);
1652 E_md4hash(newpass, new_nt_hash);
1653 E_deshash(oldpass, old_lm_hash);
1654 E_deshash(newpass, new_lm_hash);
1656 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1657 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1658 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1659 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1660 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1661 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1663 r.in.handle = &user_handle;
1664 r.in.lm_present = 1;
1665 r.in.old_lm_crypted = &hash1;
1666 r.in.new_lm_crypted = &hash2;
1667 r.in.nt_present = 1;
1668 r.in.old_nt_crypted = &hash3;
1669 r.in.new_nt_crypted = &hash4;
1670 r.in.cross1_present = 1;
1671 r.in.nt_cross = &hash5;
1672 r.in.cross2_present = 1;
1673 r.in.lm_cross = &hash6;
1675 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1676 "ChangePasswordUser failed");
1677 if (!NT_STATUS_IS_OK(r.out.result)) {
1678 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1679 ret = false;
1682 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1683 ret = false;
1686 return ret;
1688 #endif
1690 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1691 struct torture_context *tctx,
1692 const char *acct_name,
1693 struct policy_handle *handle, char **password)
1695 NTSTATUS status;
1696 struct samr_ChangePasswordUser r;
1697 bool ret = true;
1698 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1699 struct policy_handle user_handle;
1700 char *oldpass;
1701 uint8_t old_nt_hash[16], new_nt_hash[16];
1702 uint8_t old_lm_hash[16], new_lm_hash[16];
1703 bool changed = true;
1705 char *newpass;
1706 struct samr_GetUserPwInfo pwp;
1707 struct samr_PwInfo info;
1708 int policy_min_pw_len = 0;
1710 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return false;
1714 pwp.in.user_handle = &user_handle;
1715 pwp.out.info = &info;
1717 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1718 "GetUserPwInfo failed");
1719 if (NT_STATUS_IS_OK(pwp.out.result)) {
1720 policy_min_pw_len = pwp.out.info->min_password_length;
1722 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1724 torture_comment(tctx, "Testing ChangePasswordUser\n");
1726 torture_assert(tctx, *password != NULL,
1727 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1729 oldpass = *password;
1731 E_md4hash(oldpass, old_nt_hash);
1732 E_md4hash(newpass, new_nt_hash);
1733 E_deshash(oldpass, old_lm_hash);
1734 E_deshash(newpass, new_lm_hash);
1736 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1737 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1738 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1739 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1740 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1741 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1743 r.in.user_handle = &user_handle;
1744 r.in.lm_present = 1;
1745 /* Break the LM hash */
1746 hash1.hash[0]++;
1747 r.in.old_lm_crypted = &hash1;
1748 r.in.new_lm_crypted = &hash2;
1749 r.in.nt_present = 1;
1750 r.in.old_nt_crypted = &hash3;
1751 r.in.new_nt_crypted = &hash4;
1752 r.in.cross1_present = 1;
1753 r.in.nt_cross = &hash5;
1754 r.in.cross2_present = 1;
1755 r.in.lm_cross = &hash6;
1757 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1758 "ChangePasswordUser failed");
1759 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1760 __location__, __FUNCTION__,
1761 oldpass, newpass, nt_errstr(r.out.result));
1762 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1763 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1764 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1767 /* Unbreak the LM hash */
1768 hash1.hash[0]--;
1770 r.in.user_handle = &user_handle;
1771 r.in.lm_present = 1;
1772 r.in.old_lm_crypted = &hash1;
1773 r.in.new_lm_crypted = &hash2;
1774 /* Break the NT hash */
1775 hash3.hash[0]--;
1776 r.in.nt_present = 1;
1777 r.in.old_nt_crypted = &hash3;
1778 r.in.new_nt_crypted = &hash4;
1779 r.in.cross1_present = 1;
1780 r.in.nt_cross = &hash5;
1781 r.in.cross2_present = 1;
1782 r.in.lm_cross = &hash6;
1784 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1785 "ChangePasswordUser failed");
1786 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1787 __location__, __FUNCTION__,
1788 oldpass, newpass, nt_errstr(r.out.result));
1789 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1790 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1791 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1794 /* Unbreak the NT hash */
1795 hash3.hash[0]--;
1797 r.in.user_handle = &user_handle;
1798 r.in.lm_present = 1;
1799 r.in.old_lm_crypted = &hash1;
1800 r.in.new_lm_crypted = &hash2;
1801 r.in.nt_present = 1;
1802 r.in.old_nt_crypted = &hash3;
1803 r.in.new_nt_crypted = &hash4;
1804 r.in.cross1_present = 1;
1805 r.in.nt_cross = &hash5;
1806 r.in.cross2_present = 1;
1807 /* Break the LM cross */
1808 hash6.hash[0]++;
1809 r.in.lm_cross = &hash6;
1811 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1812 "ChangePasswordUser failed");
1813 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1814 __location__, __FUNCTION__,
1815 oldpass, newpass, nt_errstr(r.out.result));
1816 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1817 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1819 torture_warning(tctx, "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));
1820 ret = false;
1823 /* Unbreak the LM cross */
1824 hash6.hash[0]--;
1826 r.in.user_handle = &user_handle;
1827 r.in.lm_present = 1;
1828 r.in.old_lm_crypted = &hash1;
1829 r.in.new_lm_crypted = &hash2;
1830 r.in.nt_present = 1;
1831 r.in.old_nt_crypted = &hash3;
1832 r.in.new_nt_crypted = &hash4;
1833 r.in.cross1_present = 1;
1834 /* Break the NT cross */
1835 hash5.hash[0]++;
1836 r.in.nt_cross = &hash5;
1837 r.in.cross2_present = 1;
1838 r.in.lm_cross = &hash6;
1840 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1841 "ChangePasswordUser failed");
1842 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1843 __location__, __FUNCTION__,
1844 oldpass, newpass, nt_errstr(r.out.result));
1845 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1846 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1848 torture_warning(tctx, "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));
1849 ret = false;
1852 /* Unbreak the NT cross */
1853 hash5.hash[0]--;
1856 /* Reset the hashes to not broken values */
1857 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1858 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1859 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1860 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1861 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1862 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1864 r.in.user_handle = &user_handle;
1865 r.in.lm_present = 1;
1866 r.in.old_lm_crypted = &hash1;
1867 r.in.new_lm_crypted = &hash2;
1868 r.in.nt_present = 1;
1869 r.in.old_nt_crypted = &hash3;
1870 r.in.new_nt_crypted = &hash4;
1871 r.in.cross1_present = 1;
1872 r.in.nt_cross = &hash5;
1873 r.in.cross2_present = 0;
1874 r.in.lm_cross = NULL;
1876 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1877 "ChangePasswordUser failed");
1878 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1879 __location__, __FUNCTION__,
1880 oldpass, newpass, nt_errstr(r.out.result));
1881 if (NT_STATUS_IS_OK(r.out.result)) {
1882 changed = true;
1883 *password = newpass;
1884 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1885 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1886 ret = false;
1889 oldpass = newpass;
1890 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1892 E_md4hash(oldpass, old_nt_hash);
1893 E_md4hash(newpass, new_nt_hash);
1894 E_deshash(oldpass, old_lm_hash);
1895 E_deshash(newpass, new_lm_hash);
1898 /* Reset the hashes to not broken values */
1899 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1900 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1901 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1902 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1903 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1904 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1906 r.in.user_handle = &user_handle;
1907 r.in.lm_present = 1;
1908 r.in.old_lm_crypted = &hash1;
1909 r.in.new_lm_crypted = &hash2;
1910 r.in.nt_present = 1;
1911 r.in.old_nt_crypted = &hash3;
1912 r.in.new_nt_crypted = &hash4;
1913 r.in.cross1_present = 0;
1914 r.in.nt_cross = NULL;
1915 r.in.cross2_present = 1;
1916 r.in.lm_cross = &hash6;
1918 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1919 "ChangePasswordUser failed");
1920 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1921 __location__, __FUNCTION__,
1922 oldpass, newpass, nt_errstr(r.out.result));
1923 if (NT_STATUS_IS_OK(r.out.result)) {
1924 changed = true;
1925 *password = newpass;
1926 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1927 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1928 ret = false;
1931 oldpass = newpass;
1932 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1934 E_md4hash(oldpass, old_nt_hash);
1935 E_md4hash(newpass, new_nt_hash);
1936 E_deshash(oldpass, old_lm_hash);
1937 E_deshash(newpass, new_lm_hash);
1940 /* Reset the hashes to not broken values */
1941 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1942 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1943 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1944 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1945 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1946 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1948 r.in.user_handle = &user_handle;
1949 r.in.lm_present = 1;
1950 r.in.old_lm_crypted = &hash1;
1951 r.in.new_lm_crypted = &hash2;
1952 r.in.nt_present = 1;
1953 r.in.old_nt_crypted = &hash3;
1954 r.in.new_nt_crypted = &hash4;
1955 r.in.cross1_present = 1;
1956 r.in.nt_cross = &hash5;
1957 r.in.cross2_present = 1;
1958 r.in.lm_cross = &hash6;
1960 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1961 "ChangePasswordUser failed");
1962 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1963 __location__, __FUNCTION__,
1964 oldpass, newpass, nt_errstr(r.out.result));
1965 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1966 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1967 } else if (!NT_STATUS_IS_OK(r.out.result)) {
1968 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1969 ret = false;
1970 } else {
1971 changed = true;
1972 *password = newpass;
1975 r.in.user_handle = &user_handle;
1976 r.in.lm_present = 1;
1977 r.in.old_lm_crypted = &hash1;
1978 r.in.new_lm_crypted = &hash2;
1979 r.in.nt_present = 1;
1980 r.in.old_nt_crypted = &hash3;
1981 r.in.new_nt_crypted = &hash4;
1982 r.in.cross1_present = 1;
1983 r.in.nt_cross = &hash5;
1984 r.in.cross2_present = 1;
1985 r.in.lm_cross = &hash6;
1987 if (changed) {
1988 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1989 "ChangePasswordUser failed");
1990 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1991 __location__, __FUNCTION__,
1992 oldpass, newpass, nt_errstr(r.out.result));
1993 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1994 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1995 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1996 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
1997 ret = false;
2002 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
2003 ret = false;
2006 return ret;
2010 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
2011 struct torture_context *tctx,
2012 const char *acct_name,
2013 struct policy_handle *handle, char **password)
2015 struct samr_OemChangePasswordUser2 r;
2016 bool ret = true;
2017 struct samr_Password lm_verifier;
2018 struct samr_CryptPassword lm_pass;
2019 struct lsa_AsciiString server, account, account_bad;
2020 char *oldpass;
2021 char *newpass;
2022 struct dcerpc_binding_handle *b = p->binding_handle;
2023 uint8_t old_lm_hash[16], new_lm_hash[16];
2025 struct samr_GetDomPwInfo dom_pw_info;
2026 struct samr_PwInfo info;
2027 int policy_min_pw_len = 0;
2029 struct lsa_String domain_name;
2031 domain_name.string = "";
2032 dom_pw_info.in.domain_name = &domain_name;
2033 dom_pw_info.out.info = &info;
2035 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
2037 torture_assert(tctx, *password != NULL,
2038 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
2040 oldpass = *password;
2042 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2043 "GetDomPwInfo failed");
2044 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2045 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2048 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2050 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2051 account.string = acct_name;
2053 E_deshash(oldpass, old_lm_hash);
2054 E_deshash(newpass, new_lm_hash);
2056 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2057 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2058 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2060 r.in.server = &server;
2061 r.in.account = &account;
2062 r.in.password = &lm_pass;
2063 r.in.hash = &lm_verifier;
2065 /* Break the verification */
2066 lm_verifier.hash[0]++;
2068 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2069 "OemChangePasswordUser2 failed");
2070 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2071 __location__, __FUNCTION__,
2072 oldpass, newpass, nt_errstr(r.out.result));
2074 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2075 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2076 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2077 nt_errstr(r.out.result));
2078 ret = false;
2081 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2082 /* Break the old password */
2083 old_lm_hash[0]++;
2084 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2085 /* unbreak it for the next operation */
2086 old_lm_hash[0]--;
2087 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2089 r.in.server = &server;
2090 r.in.account = &account;
2091 r.in.password = &lm_pass;
2092 r.in.hash = &lm_verifier;
2094 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2095 "OemChangePasswordUser2 failed");
2096 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2097 __location__, __FUNCTION__,
2098 oldpass, newpass, nt_errstr(r.out.result));
2100 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2101 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2102 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2103 nt_errstr(r.out.result));
2104 ret = false;
2107 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2108 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2110 r.in.server = &server;
2111 r.in.account = &account;
2112 r.in.password = &lm_pass;
2113 r.in.hash = NULL;
2115 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2116 "OemChangePasswordUser2 failed");
2117 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2118 __location__, __FUNCTION__,
2119 oldpass, newpass, nt_errstr(r.out.result));
2121 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2122 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2123 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2124 nt_errstr(r.out.result));
2125 ret = false;
2128 /* This shouldn't be a valid name */
2129 account_bad.string = TEST_ACCOUNT_NAME "XX";
2130 r.in.account = &account_bad;
2132 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2133 "OemChangePasswordUser2 failed");
2134 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2135 __location__, __FUNCTION__,
2136 oldpass, newpass, nt_errstr(r.out.result));
2138 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2139 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2140 nt_errstr(r.out.result));
2141 ret = false;
2144 /* This shouldn't be a valid name */
2145 account_bad.string = TEST_ACCOUNT_NAME "XX";
2146 r.in.account = &account_bad;
2147 r.in.password = &lm_pass;
2148 r.in.hash = &lm_verifier;
2150 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2151 "OemChangePasswordUser2 failed");
2152 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2153 __location__, __FUNCTION__,
2154 oldpass, newpass, nt_errstr(r.out.result));
2156 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2157 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2158 nt_errstr(r.out.result));
2159 ret = false;
2162 /* This shouldn't be a valid name */
2163 account_bad.string = TEST_ACCOUNT_NAME "XX";
2164 r.in.account = &account_bad;
2165 r.in.password = NULL;
2166 r.in.hash = &lm_verifier;
2168 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2169 "OemChangePasswordUser2 failed");
2170 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2171 __location__, __FUNCTION__,
2172 oldpass, newpass, nt_errstr(r.out.result));
2174 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2175 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2176 nt_errstr(r.out.result));
2177 ret = false;
2180 E_deshash(oldpass, old_lm_hash);
2181 E_deshash(newpass, new_lm_hash);
2183 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2184 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2185 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2187 r.in.server = &server;
2188 r.in.account = &account;
2189 r.in.password = &lm_pass;
2190 r.in.hash = &lm_verifier;
2192 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2193 "OemChangePasswordUser2 failed");
2194 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2195 __location__, __FUNCTION__,
2196 oldpass, newpass, nt_errstr(r.out.result));
2198 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2199 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2200 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2201 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2202 ret = false;
2203 } else {
2204 *password = newpass;
2207 return ret;
2211 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2212 const char *acct_name,
2213 char **password,
2214 char *newpass, bool allow_password_restriction)
2216 struct samr_ChangePasswordUser2 r;
2217 bool ret = true;
2218 struct lsa_String server, account;
2219 struct samr_CryptPassword nt_pass, lm_pass;
2220 struct samr_Password nt_verifier, lm_verifier;
2221 char *oldpass;
2222 struct dcerpc_binding_handle *b = p->binding_handle;
2223 uint8_t old_nt_hash[16], new_nt_hash[16];
2224 uint8_t old_lm_hash[16], new_lm_hash[16];
2226 struct samr_GetDomPwInfo dom_pw_info;
2227 struct samr_PwInfo info;
2229 struct lsa_String domain_name;
2231 domain_name.string = "";
2232 dom_pw_info.in.domain_name = &domain_name;
2233 dom_pw_info.out.info = &info;
2235 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2237 torture_assert(tctx, *password != NULL,
2238 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2239 oldpass = *password;
2241 if (!newpass) {
2242 int policy_min_pw_len = 0;
2243 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2244 "GetDomPwInfo failed");
2245 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2246 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2249 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2252 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2253 init_lsa_String(&account, acct_name);
2255 E_md4hash(oldpass, old_nt_hash);
2256 E_md4hash(newpass, new_nt_hash);
2258 E_deshash(oldpass, old_lm_hash);
2259 E_deshash(newpass, new_lm_hash);
2261 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2262 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2263 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2265 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2266 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2267 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2269 r.in.server = &server;
2270 r.in.account = &account;
2271 r.in.nt_password = &nt_pass;
2272 r.in.nt_verifier = &nt_verifier;
2273 r.in.lm_change = 1;
2274 r.in.lm_password = &lm_pass;
2275 r.in.lm_verifier = &lm_verifier;
2277 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2278 "ChangePasswordUser2 failed");
2279 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2280 __location__, __FUNCTION__,
2281 oldpass, newpass, nt_errstr(r.out.result));
2283 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2284 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2285 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2286 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2287 ret = false;
2288 } else {
2289 *password = newpass;
2292 return ret;
2296 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2297 const char *account_string,
2298 int policy_min_pw_len,
2299 char **password,
2300 const char *newpass,
2301 NTTIME last_password_change,
2302 bool handle_reject_reason)
2304 struct samr_ChangePasswordUser3 r;
2305 bool ret = true;
2306 struct lsa_String server, account, account_bad;
2307 struct samr_CryptPassword nt_pass, lm_pass;
2308 struct samr_Password nt_verifier, lm_verifier;
2309 char *oldpass;
2310 struct dcerpc_binding_handle *b = p->binding_handle;
2311 uint8_t old_nt_hash[16], new_nt_hash[16];
2312 uint8_t old_lm_hash[16], new_lm_hash[16];
2313 NTTIME t;
2314 struct samr_DomInfo1 *dominfo = NULL;
2315 struct userPwdChangeFailureInformation *reject = NULL;
2317 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2319 if (newpass == NULL) {
2320 do {
2321 if (policy_min_pw_len == 0) {
2322 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2323 } else {
2324 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2326 } while (check_password_quality(newpass) == false);
2327 } else {
2328 torture_comment(tctx, "Using password '%s'\n", newpass);
2331 torture_assert(tctx, *password != NULL,
2332 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2334 oldpass = *password;
2335 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2336 init_lsa_String(&account, account_string);
2338 E_md4hash(oldpass, old_nt_hash);
2339 E_md4hash(newpass, new_nt_hash);
2341 E_deshash(oldpass, old_lm_hash);
2342 E_deshash(newpass, new_lm_hash);
2344 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2345 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2346 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2348 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2349 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2350 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2352 /* Break the verification */
2353 nt_verifier.hash[0]++;
2355 r.in.server = &server;
2356 r.in.account = &account;
2357 r.in.nt_password = &nt_pass;
2358 r.in.nt_verifier = &nt_verifier;
2359 r.in.lm_change = 1;
2360 r.in.lm_password = &lm_pass;
2361 r.in.lm_verifier = &lm_verifier;
2362 r.in.password3 = NULL;
2363 r.out.dominfo = &dominfo;
2364 r.out.reject = &reject;
2366 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2367 "ChangePasswordUser3 failed");
2368 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2369 __location__, __FUNCTION__,
2370 oldpass, newpass, nt_errstr(r.out.result));
2371 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2372 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2373 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2374 nt_errstr(r.out.result));
2375 ret = false;
2378 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2379 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2380 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2382 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2383 /* Break the NT hash */
2384 old_nt_hash[0]++;
2385 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2386 /* Unbreak it again */
2387 old_nt_hash[0]--;
2388 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2390 r.in.server = &server;
2391 r.in.account = &account;
2392 r.in.nt_password = &nt_pass;
2393 r.in.nt_verifier = &nt_verifier;
2394 r.in.lm_change = 1;
2395 r.in.lm_password = &lm_pass;
2396 r.in.lm_verifier = &lm_verifier;
2397 r.in.password3 = NULL;
2398 r.out.dominfo = &dominfo;
2399 r.out.reject = &reject;
2401 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2402 "ChangePasswordUser3 failed");
2403 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2404 __location__, __FUNCTION__,
2405 oldpass, newpass, nt_errstr(r.out.result));
2406 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2407 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2408 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2409 nt_errstr(r.out.result));
2410 ret = false;
2413 /* This shouldn't be a valid name */
2414 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2416 r.in.account = &account_bad;
2417 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2418 "ChangePasswordUser3 failed");
2419 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2420 __location__, __FUNCTION__,
2421 oldpass, newpass, nt_errstr(r.out.result));
2422 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2423 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2424 nt_errstr(r.out.result));
2425 ret = false;
2428 E_md4hash(oldpass, old_nt_hash);
2429 E_md4hash(newpass, new_nt_hash);
2431 E_deshash(oldpass, old_lm_hash);
2432 E_deshash(newpass, new_lm_hash);
2434 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2435 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2436 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2438 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2439 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2440 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2442 r.in.server = &server;
2443 r.in.account = &account;
2444 r.in.nt_password = &nt_pass;
2445 r.in.nt_verifier = &nt_verifier;
2446 r.in.lm_change = 1;
2447 r.in.lm_password = &lm_pass;
2448 r.in.lm_verifier = &lm_verifier;
2449 r.in.password3 = NULL;
2450 r.out.dominfo = &dominfo;
2451 r.out.reject = &reject;
2453 unix_to_nt_time(&t, time(NULL));
2455 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2456 "ChangePasswordUser3 failed");
2457 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2458 __location__, __FUNCTION__,
2459 oldpass, newpass, nt_errstr(r.out.result));
2461 torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2462 "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2463 __location__,
2464 (dominfo == NULL)? "NULL" : "present",
2465 reject ? "true" : "false",
2466 handle_reject_reason ? "true" : "false",
2467 null_nttime(last_password_change) ? "null" : "not null",
2468 dominfo ? (long long)dominfo->min_password_age : (long long)0);
2470 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2471 && dominfo
2472 && reject
2473 && handle_reject_reason
2474 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2475 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2477 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2478 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2479 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2480 return false;
2484 /* We tested the order of precendence which is as follows:
2486 * pwd min_age
2487 * pwd length
2488 * pwd complexity
2489 * pwd history
2491 Guenther */
2493 if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
2494 (last_password_change - dominfo->min_password_age > t)) {
2496 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2497 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2498 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2499 return false;
2502 } else if ((dominfo->min_password_length > 0) &&
2503 (strlen(newpass) < dominfo->min_password_length)) {
2505 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2506 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2507 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2508 return false;
2511 } else if ((dominfo->password_history_length > 0) &&
2512 strequal(oldpass, newpass)) {
2514 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2515 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2516 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2517 return false;
2519 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2521 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2522 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2523 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2524 return false;
2529 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2530 /* retry with adjusted size */
2531 return test_ChangePasswordUser3(p, tctx, account_string,
2532 dominfo->min_password_length,
2533 password, NULL, 0, false);
2537 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2538 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2539 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2540 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2541 return false;
2543 /* Perhaps the server has a 'min password age' set? */
2545 } else {
2546 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2548 *password = talloc_strdup(tctx, newpass);
2551 return ret;
2554 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2555 const char *account_string,
2556 struct policy_handle *handle,
2557 char **password)
2559 NTSTATUS status;
2560 struct samr_ChangePasswordUser3 r;
2561 struct samr_SetUserInfo s;
2562 union samr_UserInfo u;
2563 DATA_BLOB session_key;
2564 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2565 uint8_t confounder[16];
2566 struct MD5Context ctx;
2568 bool ret = true;
2569 struct lsa_String server, account;
2570 struct samr_CryptPassword nt_pass;
2571 struct samr_Password nt_verifier;
2572 DATA_BLOB new_random_pass;
2573 char *newpass;
2574 char *oldpass;
2575 struct dcerpc_binding_handle *b = p->binding_handle;
2576 uint8_t old_nt_hash[16], new_nt_hash[16];
2577 NTTIME t;
2578 struct samr_DomInfo1 *dominfo = NULL;
2579 struct userPwdChangeFailureInformation *reject = NULL;
2581 new_random_pass = samr_very_rand_pass(tctx, 128);
2583 torture_assert(tctx, *password != NULL,
2584 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2586 oldpass = *password;
2587 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2588 init_lsa_String(&account, account_string);
2590 s.in.user_handle = handle;
2591 s.in.info = &u;
2592 s.in.level = 25;
2594 ZERO_STRUCT(u);
2596 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2598 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2600 status = dcerpc_fetch_session_key(p, &session_key);
2601 if (!NT_STATUS_IS_OK(status)) {
2602 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2603 s.in.level, nt_errstr(status));
2604 return false;
2607 generate_random_buffer((uint8_t *)confounder, 16);
2609 MD5Init(&ctx);
2610 MD5Update(&ctx, confounder, 16);
2611 MD5Update(&ctx, session_key.data, session_key.length);
2612 MD5Final(confounded_session_key.data, &ctx);
2614 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2615 memcpy(&u.info25.password.data[516], confounder, 16);
2617 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2619 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2620 "SetUserInfo failed");
2621 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2622 __location__, __FUNCTION__,
2623 oldpass, "RANDOM", nt_errstr(s.out.result));
2624 if (!NT_STATUS_IS_OK(s.out.result)) {
2625 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2626 s.in.level, nt_errstr(s.out.result));
2627 ret = false;
2630 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2632 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2634 new_random_pass = samr_very_rand_pass(tctx, 128);
2636 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2638 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2639 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2640 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2642 r.in.server = &server;
2643 r.in.account = &account;
2644 r.in.nt_password = &nt_pass;
2645 r.in.nt_verifier = &nt_verifier;
2646 r.in.lm_change = 0;
2647 r.in.lm_password = NULL;
2648 r.in.lm_verifier = NULL;
2649 r.in.password3 = NULL;
2650 r.out.dominfo = &dominfo;
2651 r.out.reject = &reject;
2653 unix_to_nt_time(&t, time(NULL));
2655 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2656 "ChangePasswordUser3 failed");
2657 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2658 __location__, __FUNCTION__,
2659 oldpass, "RANDOM", nt_errstr(r.out.result));
2661 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2662 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2663 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2664 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2665 return false;
2667 /* Perhaps the server has a 'min password age' set? */
2669 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2670 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2671 ret = false;
2674 newpass = samr_rand_pass(tctx, 128);
2676 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2678 E_md4hash(newpass, new_nt_hash);
2680 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2681 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2682 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2684 r.in.server = &server;
2685 r.in.account = &account;
2686 r.in.nt_password = &nt_pass;
2687 r.in.nt_verifier = &nt_verifier;
2688 r.in.lm_change = 0;
2689 r.in.lm_password = NULL;
2690 r.in.lm_verifier = NULL;
2691 r.in.password3 = NULL;
2692 r.out.dominfo = &dominfo;
2693 r.out.reject = &reject;
2695 unix_to_nt_time(&t, time(NULL));
2697 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2698 "ChangePasswordUser3 failed");
2699 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2700 __location__, __FUNCTION__,
2701 oldpass, newpass, nt_errstr(r.out.result));
2703 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2704 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2705 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2706 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2707 return false;
2709 /* Perhaps the server has a 'min password age' set? */
2711 } else {
2712 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2713 *password = talloc_strdup(tctx, newpass);
2716 return ret;
2720 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2721 struct torture_context *tctx,
2722 struct policy_handle *alias_handle)
2724 struct samr_GetMembersInAlias r;
2725 struct lsa_SidArray sids;
2727 torture_comment(tctx, "Testing GetMembersInAlias\n");
2729 r.in.alias_handle = alias_handle;
2730 r.out.sids = &sids;
2732 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2733 "GetMembersInAlias failed");
2734 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2736 return true;
2739 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2740 struct torture_context *tctx,
2741 struct policy_handle *alias_handle,
2742 const struct dom_sid *domain_sid)
2744 struct samr_AddAliasMember r;
2745 struct samr_DeleteAliasMember d;
2746 struct dom_sid *sid;
2748 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2750 torture_comment(tctx, "Testing AddAliasMember\n");
2751 r.in.alias_handle = alias_handle;
2752 r.in.sid = sid;
2754 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2755 "AddAliasMember failed");
2756 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2758 d.in.alias_handle = alias_handle;
2759 d.in.sid = sid;
2761 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2762 "DeleteAliasMember failed");
2763 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2765 return true;
2768 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2769 struct torture_context *tctx,
2770 struct policy_handle *alias_handle)
2772 struct samr_AddMultipleMembersToAlias a;
2773 struct samr_RemoveMultipleMembersFromAlias r;
2774 struct lsa_SidArray sids;
2776 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2777 a.in.alias_handle = alias_handle;
2778 a.in.sids = &sids;
2780 sids.num_sids = 3;
2781 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2783 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2784 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2785 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2787 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2788 "AddMultipleMembersToAlias failed");
2789 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2792 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2793 r.in.alias_handle = alias_handle;
2794 r.in.sids = &sids;
2796 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2797 "RemoveMultipleMembersFromAlias failed");
2798 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2800 /* strange! removing twice doesn't give any error */
2801 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2802 "RemoveMultipleMembersFromAlias failed");
2803 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2805 /* but removing an alias that isn't there does */
2806 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2808 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2809 "RemoveMultipleMembersFromAlias failed");
2810 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2812 return true;
2815 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2816 struct torture_context *tctx,
2817 struct policy_handle *domain_handle)
2819 struct samr_GetAliasMembership r;
2820 struct lsa_SidArray sids;
2821 struct samr_Ids rids;
2823 torture_comment(tctx, "Testing GetAliasMembership\n");
2825 r.in.domain_handle = domain_handle;
2826 r.in.sids = &sids;
2827 r.out.rids = &rids;
2829 sids.num_sids = 0;
2830 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2832 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2833 "GetAliasMembership failed");
2834 torture_assert_ntstatus_ok(tctx, r.out.result,
2835 "samr_GetAliasMembership failed");
2837 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2838 "protocol misbehaviour");
2840 sids.num_sids = 1;
2841 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2842 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2844 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2845 "samr_GetAliasMembership failed");
2846 torture_assert_ntstatus_ok(tctx, r.out.result,
2847 "samr_GetAliasMembership failed");
2849 #if 0
2850 /* only true for w2k8 it seems
2851 * win7, xp, w2k3 will return a 0 length array pointer */
2853 if (rids.ids && (rids.count == 0)) {
2854 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2856 #endif
2857 if (!rids.ids && rids.count) {
2858 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2861 return true;
2864 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2865 struct torture_context *tctx,
2866 struct policy_handle *user_handle)
2868 struct samr_TestPrivateFunctionsUser r;
2870 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2872 r.in.user_handle = user_handle;
2874 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2875 "TestPrivateFunctionsUser failed");
2876 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2878 return true;
2881 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2882 struct torture_context *tctx,
2883 struct policy_handle *handle,
2884 bool use_info2,
2885 NTTIME *pwdlastset)
2887 NTSTATUS status;
2888 uint16_t levels[] = { /* 3, */ 5, 21 };
2889 int i;
2890 NTTIME pwdlastset3 = 0;
2891 NTTIME pwdlastset5 = 0;
2892 NTTIME pwdlastset21 = 0;
2894 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2895 use_info2 ? "2":"");
2897 for (i=0; i<ARRAY_SIZE(levels); i++) {
2899 struct samr_QueryUserInfo r;
2900 struct samr_QueryUserInfo2 r2;
2901 union samr_UserInfo *info;
2903 if (use_info2) {
2904 r2.in.user_handle = handle;
2905 r2.in.level = levels[i];
2906 r2.out.info = &info;
2907 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2908 "QueryUserInfo2 failed");
2909 status = r2.out.result;
2911 } else {
2912 r.in.user_handle = handle;
2913 r.in.level = levels[i];
2914 r.out.info = &info;
2915 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2916 "QueryUserInfo failed");
2917 status = r.out.result;
2920 if (!NT_STATUS_IS_OK(status) &&
2921 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2922 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2923 use_info2 ? "2":"", levels[i], nt_errstr(status));
2924 return false;
2927 switch (levels[i]) {
2928 case 3:
2929 pwdlastset3 = info->info3.last_password_change;
2930 break;
2931 case 5:
2932 pwdlastset5 = info->info5.last_password_change;
2933 break;
2934 case 21:
2935 pwdlastset21 = info->info21.last_password_change;
2936 break;
2937 default:
2938 return false;
2941 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2942 "pwdlastset mixup"); */
2943 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2944 "pwdlastset mixup");
2946 *pwdlastset = pwdlastset21;
2948 torture_comment(tctx, "(pwdlastset: %llu)\n",
2949 (unsigned long long) *pwdlastset);
2951 return true;
2954 static bool test_SamLogon(struct torture_context *tctx,
2955 struct dcerpc_pipe *p,
2956 struct cli_credentials *test_credentials,
2957 NTSTATUS expected_result,
2958 bool interactive)
2960 NTSTATUS status;
2961 struct netr_LogonSamLogonEx r;
2962 union netr_LogonLevel logon;
2963 union netr_Validation validation;
2964 uint8_t authoritative;
2965 struct netr_IdentityInfo identity;
2966 struct netr_NetworkInfo ninfo;
2967 struct netr_PasswordInfo pinfo;
2968 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2969 int flags = CLI_CRED_NTLM_AUTH;
2970 uint32_t samlogon_flags = 0;
2971 struct netlogon_creds_CredentialState *creds;
2972 struct netr_Authenticator a;
2973 struct dcerpc_binding_handle *b = p->binding_handle;
2975 torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2977 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
2978 flags |= CLI_CRED_LANMAN_AUTH;
2981 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
2982 flags |= CLI_CRED_NTLMv2_AUTH;
2985 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2986 &identity.account_name.string,
2987 &identity.domain_name.string);
2989 identity.parameter_control =
2990 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2991 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2992 identity.logon_id_low = 0;
2993 identity.logon_id_high = 0;
2994 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2996 if (interactive) {
2997 netlogon_creds_client_authenticator(creds, &a);
2999 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
3000 ZERO_STRUCT(pinfo.lmpassword.hash);
3002 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
3004 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3005 netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
3006 netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
3007 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
3008 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
3009 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
3010 } else {
3011 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
3012 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
3015 pinfo.identity_info = identity;
3016 logon.password = &pinfo;
3018 r.in.logon_level = NetlogonInteractiveInformation;
3019 } else {
3020 generate_random_buffer(ninfo.challenge,
3021 sizeof(ninfo.challenge));
3022 chal = data_blob_const(ninfo.challenge,
3023 sizeof(ninfo.challenge));
3025 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3026 cli_credentials_get_domain(test_credentials));
3028 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3029 &flags,
3030 chal,
3031 names_blob,
3032 &lm_resp, &nt_resp,
3033 NULL, NULL);
3034 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3036 ninfo.lm.data = lm_resp.data;
3037 ninfo.lm.length = lm_resp.length;
3039 ninfo.nt.data = nt_resp.data;
3040 ninfo.nt.length = nt_resp.length;
3042 ninfo.identity_info = identity;
3043 logon.network = &ninfo;
3045 r.in.logon_level = NetlogonNetworkInformation;
3048 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3049 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3050 r.in.logon = &logon;
3051 r.in.flags = &samlogon_flags;
3052 r.out.flags = &samlogon_flags;
3053 r.out.validation = &validation;
3054 r.out.authoritative = &authoritative;
3056 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3058 r.in.validation_level = 6;
3060 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3061 "netr_LogonSamLogonEx failed");
3062 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3063 r.in.validation_level = 3;
3064 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3065 "netr_LogonSamLogonEx failed");
3067 if (!NT_STATUS_IS_OK(r.out.result)) {
3068 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3069 return true;
3070 } else {
3071 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3074 return true;
3077 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3078 struct dcerpc_pipe *p,
3079 struct cli_credentials *machine_creds,
3080 const char *acct_name,
3081 const char *password,
3082 NTSTATUS expected_samlogon_result,
3083 bool interactive)
3085 bool ret = true;
3086 struct cli_credentials *test_credentials;
3088 test_credentials = cli_credentials_init(tctx);
3090 cli_credentials_set_workstation(test_credentials,
3091 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3092 cli_credentials_set_domain(test_credentials,
3093 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3094 cli_credentials_set_username(test_credentials,
3095 acct_name, CRED_SPECIFIED);
3096 cli_credentials_set_password(test_credentials,
3097 password, CRED_SPECIFIED);
3099 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3100 interactive ? "interactive" : "network", acct_name, password);
3102 if (!test_SamLogon(tctx, p, test_credentials,
3103 expected_samlogon_result, interactive)) {
3104 torture_warning(tctx, "new password did not work\n");
3105 ret = false;
3108 return ret;
3111 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3112 struct dcerpc_pipe *np,
3113 struct torture_context *tctx,
3114 struct policy_handle *handle,
3115 uint16_t level,
3116 uint32_t fields_present,
3117 uint8_t password_expired,
3118 bool *matched_expected_error,
3119 bool use_setinfo2,
3120 const char *acct_name,
3121 char **password,
3122 struct cli_credentials *machine_creds,
3123 bool use_queryinfo2,
3124 NTTIME *pwdlastset,
3125 NTSTATUS expected_samlogon_result)
3127 const char *fields = NULL;
3128 bool ret = true;
3129 struct dcerpc_binding_handle *b = p->binding_handle;
3131 switch (level) {
3132 case 21:
3133 case 23:
3134 case 25:
3135 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3136 fields_present);
3137 break;
3138 default:
3139 break;
3142 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3143 "(password_expired: %d) %s\n",
3144 use_setinfo2 ? "2":"", level, password_expired,
3145 fields ? fields : "");
3147 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3148 fields_present,
3149 password,
3150 password_expired,
3151 use_setinfo2,
3152 matched_expected_error)) {
3153 ret = false;
3156 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3157 use_queryinfo2,
3158 pwdlastset)) {
3159 ret = false;
3162 if (*matched_expected_error == true) {
3163 return ret;
3166 if (!test_SamLogon_with_creds(tctx, np,
3167 machine_creds,
3168 acct_name,
3169 *password,
3170 expected_samlogon_result,
3171 false)) {
3172 ret = false;
3175 return ret;
3178 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3179 struct cli_credentials *credentials,
3180 struct dcerpc_pipe **p)
3182 struct dcerpc_binding *b;
3184 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3185 "failed to get rpc binding");
3187 /* We have to use schannel, otherwise the SamLogonEx fails
3188 * with INTERNAL_ERROR */
3190 b->flags &= ~DCERPC_AUTH_OPTIONS;
3191 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO;
3193 torture_assert_ntstatus_ok(tctx,
3194 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3195 credentials, tctx->ev, tctx->lp_ctx),
3196 "failed to bind to netlogon");
3198 return true;
3201 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3202 struct torture_context *tctx,
3203 uint32_t acct_flags,
3204 const char *acct_name,
3205 struct policy_handle *handle,
3206 char **password,
3207 struct cli_credentials *machine_credentials)
3209 int s = 0, q = 0, f = 0, l = 0, z = 0;
3210 bool ret = true;
3211 int delay = 50000;
3212 bool set_levels[] = { false, true };
3213 bool query_levels[] = { false, true };
3214 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3215 uint32_t nonzeros[] = { 1, 24 };
3216 uint32_t fields_present[] = {
3218 SAMR_FIELD_EXPIRED_FLAG,
3219 SAMR_FIELD_LAST_PWD_CHANGE,
3220 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3221 SAMR_FIELD_COMMENT,
3222 SAMR_FIELD_NT_PASSWORD_PRESENT,
3223 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3224 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3225 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3226 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3227 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3228 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3230 struct dcerpc_pipe *np = NULL;
3232 if (torture_setting_bool(tctx, "samba3", false) ||
3233 torture_setting_bool(tctx, "samba4", false)) {
3234 delay = 999999;
3235 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3236 delay);
3239 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3241 /* set to 1 to enable testing for all possible opcode
3242 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3243 combinations */
3244 #if 0
3245 #define TEST_ALL_LEVELS 1
3246 #define TEST_SET_LEVELS 1
3247 #define TEST_QUERY_LEVELS 1
3248 #endif
3249 #ifdef TEST_ALL_LEVELS
3250 for (l=0; l<ARRAY_SIZE(levels); l++) {
3251 #else
3252 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3253 #endif
3254 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3255 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3256 #ifdef TEST_SET_LEVELS
3257 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3258 #endif
3259 #ifdef TEST_QUERY_LEVELS
3260 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3261 #endif
3262 NTTIME pwdlastset_old = 0;
3263 NTTIME pwdlastset_new = 0;
3264 bool matched_expected_error = false;
3265 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3267 torture_comment(tctx, "------------------------------\n"
3268 "Testing pwdLastSet attribute for flags: 0x%08x "
3269 "(s: %d (l: %d), q: %d)\n",
3270 acct_flags, s, levels[l], q);
3272 switch (levels[l]) {
3273 case 21:
3274 case 23:
3275 case 25:
3276 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3277 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3278 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3280 break;
3284 /* set #1 */
3286 /* set a password and force password change (pwdlastset 0) by
3287 * setting the password expired flag to a non-0 value */
3289 if (!test_SetPassword_level(p, np, tctx, handle,
3290 levels[l],
3291 fields_present[f],
3292 nonzeros[z],
3293 &matched_expected_error,
3294 set_levels[s],
3295 acct_name,
3296 password,
3297 machine_credentials,
3298 query_levels[q],
3299 &pwdlastset_new,
3300 expected_samlogon_result)) {
3301 ret = false;
3304 if (matched_expected_error == true) {
3305 /* skipping on expected failure */
3306 continue;
3309 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3310 * set without the SAMR_FIELD_EXPIRED_FLAG */
3312 switch (levels[l]) {
3313 case 21:
3314 case 23:
3315 case 25:
3316 if ((pwdlastset_new != 0) &&
3317 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3318 torture_comment(tctx, "not considering a non-0 "
3319 "pwdLastSet as a an error as the "
3320 "SAMR_FIELD_EXPIRED_FLAG has not "
3321 "been set\n");
3322 break;
3324 break;
3325 default:
3326 if (pwdlastset_new != 0) {
3327 torture_warning(tctx, "pwdLastSet test failed: "
3328 "expected pwdLastSet 0 but got %llu\n",
3329 (unsigned long long) pwdlastset_old);
3330 ret = false;
3332 break;
3335 switch (levels[l]) {
3336 case 21:
3337 case 23:
3338 case 25:
3339 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3340 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3341 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3342 (pwdlastset_old >= pwdlastset_new)) {
3343 torture_warning(tctx, "pwdlastset not increasing\n");
3344 ret = false;
3346 break;
3349 pwdlastset_old = pwdlastset_new;
3351 usleep(delay);
3353 /* set #2 */
3355 /* set a password, pwdlastset needs to get updated (increased
3356 * value), password_expired value used here is 0 */
3358 if (!test_SetPassword_level(p, np, tctx, handle,
3359 levels[l],
3360 fields_present[f],
3362 &matched_expected_error,
3363 set_levels[s],
3364 acct_name,
3365 password,
3366 machine_credentials,
3367 query_levels[q],
3368 &pwdlastset_new,
3369 expected_samlogon_result)) {
3370 ret = false;
3373 /* when a password has been changed, pwdlastset must not be 0 afterwards
3374 * and must be larger then the old value */
3376 switch (levels[l]) {
3377 case 21:
3378 case 23:
3379 case 25:
3380 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3381 * password has been changed, old and new pwdlastset
3382 * need to be the same value */
3384 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3385 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3386 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3388 torture_assert_int_equal(tctx, pwdlastset_old,
3389 pwdlastset_new, "pwdlastset must be equal");
3390 break;
3392 break;
3393 default:
3394 if (pwdlastset_old >= pwdlastset_new) {
3395 torture_warning(tctx, "pwdLastSet test failed: "
3396 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3397 (unsigned long long) pwdlastset_old,
3398 (unsigned long long) pwdlastset_new);
3399 ret = false;
3401 if (pwdlastset_new == 0) {
3402 torture_warning(tctx, "pwdLastSet test failed: "
3403 "expected non-0 pwdlastset, got: %llu\n",
3404 (unsigned long long) pwdlastset_new);
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_warning(tctx, "pwdlastset not increasing\n");
3419 ret = false;
3421 break;
3424 pwdlastset_old = pwdlastset_new;
3426 usleep(delay);
3428 /* set #2b */
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:
3456 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3457 * password has been changed, old and new pwdlastset
3458 * need to be the same value */
3460 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3461 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3462 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3464 torture_assert_int_equal(tctx, pwdlastset_old,
3465 pwdlastset_new, "pwdlastset must be equal");
3466 break;
3468 break;
3469 default:
3470 if (pwdlastset_old >= pwdlastset_new) {
3471 torture_warning(tctx, "pwdLastSet test failed: "
3472 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3473 (unsigned long long) pwdlastset_old,
3474 (unsigned long long) pwdlastset_new);
3475 ret = false;
3477 if (pwdlastset_new == 0) {
3478 torture_warning(tctx, "pwdLastSet test failed: "
3479 "expected non-0 pwdlastset, got: %llu\n",
3480 (unsigned long long) pwdlastset_new);
3481 ret = false;
3483 break;
3486 switch (levels[l]) {
3487 case 21:
3488 case 23:
3489 case 25:
3490 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3491 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3492 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3493 (pwdlastset_old >= pwdlastset_new)) {
3494 torture_warning(tctx, "pwdlastset not increasing\n");
3495 ret = false;
3497 break;
3500 pwdlastset_old = pwdlastset_new;
3502 usleep(delay);
3504 /* set #3 */
3506 /* set a password and force password change (pwdlastset 0) by
3507 * setting the password expired flag to a non-0 value */
3509 if (!test_SetPassword_level(p, np, tctx, handle,
3510 levels[l],
3511 fields_present[f],
3512 nonzeros[z],
3513 &matched_expected_error,
3514 set_levels[s],
3515 acct_name,
3516 password,
3517 machine_credentials,
3518 query_levels[q],
3519 &pwdlastset_new,
3520 expected_samlogon_result)) {
3521 ret = false;
3524 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3525 * set without the SAMR_FIELD_EXPIRED_FLAG */
3527 switch (levels[l]) {
3528 case 21:
3529 case 23:
3530 case 25:
3531 if ((pwdlastset_new != 0) &&
3532 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3533 torture_comment(tctx, "not considering a non-0 "
3534 "pwdLastSet as a an error as the "
3535 "SAMR_FIELD_EXPIRED_FLAG has not "
3536 "been set\n");
3537 break;
3540 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3541 * password has been changed, old and new pwdlastset
3542 * need to be the same value */
3544 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3545 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3546 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3548 torture_assert_int_equal(tctx, pwdlastset_old,
3549 pwdlastset_new, "pwdlastset must be equal");
3550 break;
3552 break;
3553 default:
3554 if (pwdlastset_new != 0) {
3555 torture_warning(tctx, "pwdLastSet test failed: "
3556 "expected pwdLastSet 0, got %llu\n",
3557 (unsigned long long) pwdlastset_old);
3558 ret = false;
3560 break;
3563 switch (levels[l]) {
3564 case 21:
3565 case 23:
3566 case 25:
3567 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3568 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3569 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3570 (pwdlastset_old >= pwdlastset_new)) {
3571 torture_warning(tctx, "pwdlastset not increasing\n");
3572 ret = false;
3574 break;
3577 /* if the level we are testing does not have a fields_present
3578 * field, skip all fields present tests by setting f to to
3579 * arraysize */
3580 switch (levels[l]) {
3581 case 18:
3582 case 24:
3583 case 26:
3584 f = ARRAY_SIZE(fields_present);
3585 break;
3588 #ifdef TEST_QUERY_LEVELS
3590 #endif
3591 #ifdef TEST_SET_LEVELS
3593 #endif
3594 } /* fields present */
3595 } /* nonzeros */
3596 } /* levels */
3598 #undef TEST_SET_LEVELS
3599 #undef TEST_QUERY_LEVELS
3601 talloc_free(np);
3603 return ret;
3606 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3607 struct torture_context *tctx,
3608 struct policy_handle *handle,
3609 uint32_t *badpwdcount)
3611 union samr_UserInfo *info;
3612 struct samr_QueryUserInfo r;
3614 r.in.user_handle = handle;
3615 r.in.level = 3;
3616 r.out.info = &info;
3618 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3620 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3621 "failed to query userinfo");
3622 torture_assert_ntstatus_ok(tctx, r.out.result,
3623 "failed to query userinfo");
3625 *badpwdcount = info->info3.bad_password_count;
3627 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3629 return true;
3632 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3633 struct torture_context *tctx,
3634 struct policy_handle *user_handle,
3635 uint32_t acct_flags)
3637 struct samr_SetUserInfo r;
3638 union samr_UserInfo user_info;
3640 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3642 user_info.info16.acct_flags = acct_flags;
3644 r.in.user_handle = user_handle;
3645 r.in.level = 16;
3646 r.in.info = &user_info;
3648 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3649 "failed to set account flags");
3650 torture_assert_ntstatus_ok(tctx, r.out.result,
3651 "failed to set account flags");
3653 return true;
3656 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3657 struct torture_context *tctx,
3658 struct policy_handle *user_handle,
3659 uint32_t acct_flags,
3660 char **password)
3662 struct dcerpc_binding_handle *b = p->binding_handle;
3664 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3665 "failed to set password");
3667 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3669 torture_assert(tctx,
3670 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3671 acct_flags & ~ACB_DISABLED),
3672 "failed to enable user");
3674 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3675 "failed to set password");
3677 return true;
3680 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3681 struct torture_context *tctx,
3682 struct policy_handle *domain_handle,
3683 enum samr_DomainInfoClass level,
3684 union samr_DomainInfo *info)
3686 struct samr_SetDomainInfo r;
3688 r.in.domain_handle = domain_handle;
3689 r.in.level = level;
3690 r.in.info = info;
3692 torture_assert_ntstatus_ok(tctx,
3693 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3694 "failed to set domain info");
3695 torture_assert_ntstatus_ok(tctx, r.out.result,
3696 "failed to set domain info");
3698 return true;
3701 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3702 struct torture_context *tctx,
3703 struct policy_handle *domain_handle,
3704 enum samr_DomainInfoClass level,
3705 union samr_DomainInfo *info,
3706 NTSTATUS expected)
3708 struct samr_SetDomainInfo r;
3710 r.in.domain_handle = domain_handle;
3711 r.in.level = level;
3712 r.in.info = info;
3714 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3715 "SetDomainInfo failed");
3716 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3718 return true;
3721 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3722 struct torture_context *tctx,
3723 struct policy_handle *domain_handle,
3724 enum samr_DomainInfoClass level,
3725 union samr_DomainInfo **q_info)
3727 struct samr_QueryDomainInfo2 r;
3729 r.in.domain_handle = domain_handle;
3730 r.in.level = level;
3731 r.out.info = q_info;
3733 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3734 "failed to query domain info");
3735 torture_assert_ntstatus_ok(tctx, r.out.result,
3736 "failed to query domain info");
3738 return true;
3741 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3742 struct dcerpc_pipe *np,
3743 struct torture_context *tctx,
3744 uint32_t acct_flags,
3745 const char *acct_name,
3746 struct policy_handle *domain_handle,
3747 struct policy_handle *user_handle,
3748 char **password,
3749 struct cli_credentials *machine_credentials,
3750 const char *comment,
3751 bool disable,
3752 bool interactive,
3753 NTSTATUS expected_success_status,
3754 struct samr_DomInfo1 *info1,
3755 struct samr_DomInfo12 *info12)
3757 union samr_DomainInfo info;
3758 char **passwords;
3759 int i;
3760 uint32_t badpwdcount, tmp;
3761 uint32_t password_history_length = 12;
3762 uint32_t lockout_threshold = 15;
3763 struct dcerpc_binding_handle *b = p->binding_handle;
3765 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3767 torture_assert(tctx, password_history_length < lockout_threshold,
3768 "password history length needs to be smaller than account lockout threshold for this test");
3771 /* set policies */
3773 info.info1 = *info1;
3774 info.info1.password_history_length = password_history_length;
3776 torture_assert(tctx,
3777 test_SetDomainInfo(b, tctx, domain_handle,
3778 DomainPasswordInformation, &info),
3779 "failed to set password history length");
3781 info.info12 = *info12;
3782 info.info12.lockout_threshold = lockout_threshold;
3784 torture_assert(tctx,
3785 test_SetDomainInfo(b, tctx, domain_handle,
3786 DomainLockoutInformation, &info),
3787 "failed to set lockout threshold");
3789 /* reset bad pwd count */
3791 torture_assert(tctx,
3792 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3795 /* enable or disable account */
3796 if (disable) {
3797 torture_assert(tctx,
3798 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3799 acct_flags | ACB_DISABLED),
3800 "failed to disable user");
3801 } else {
3802 torture_assert(tctx,
3803 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3804 acct_flags & ~ACB_DISABLED),
3805 "failed to enable user");
3809 /* setup password history */
3811 passwords = talloc_array(tctx, char *, password_history_length);
3813 for (i=0; i < password_history_length; i++) {
3815 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3816 "failed to set password");
3817 passwords[i] = talloc_strdup(tctx, *password);
3819 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3820 acct_name, passwords[i],
3821 expected_success_status, interactive)) {
3822 torture_fail(tctx, "failed to auth with latest password");
3825 torture_assert(tctx,
3826 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3828 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3832 /* test with wrong password */
3834 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3835 acct_name, "random_crap",
3836 NT_STATUS_WRONG_PASSWORD, interactive)) {
3837 torture_fail(tctx, "succeeded to authenticate with wrong password");
3840 torture_assert(tctx,
3841 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3843 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3846 /* test with latest good password */
3848 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3849 passwords[password_history_length-1],
3850 expected_success_status, interactive)) {
3851 torture_fail(tctx, "succeeded to authenticate with wrong password");
3854 torture_assert(tctx,
3855 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3857 if (disable) {
3858 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3859 } else {
3860 /* only enabled accounts get the bad pwd count reset upon
3861 * successful logon */
3862 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3865 tmp = badpwdcount;
3868 /* test password history */
3870 for (i=0; i < password_history_length; i++) {
3872 torture_comment(tctx, "Testing bad password count behavior with "
3873 "password #%d of #%d\n", i, password_history_length);
3875 /* - network samlogon will succeed auth and not
3876 * increase badpwdcount for 2 last entries
3877 * - interactive samlogon only for the last one */
3879 if (i == password_history_length - 1 ||
3880 (i == password_history_length - 2 && !interactive)) {
3882 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3883 acct_name, passwords[i],
3884 expected_success_status, interactive)) {
3885 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3888 torture_assert(tctx,
3889 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3891 if (disable) {
3892 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3893 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3894 } else {
3895 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3896 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3899 tmp = badpwdcount;
3901 continue;
3904 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3905 acct_name, passwords[i],
3906 NT_STATUS_WRONG_PASSWORD, interactive)) {
3907 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3910 torture_assert(tctx,
3911 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3913 /* - network samlogon will fail auth but not increase
3914 * badpwdcount for 3rd last entry
3915 * - interactive samlogon for 3rd and 2nd last entry */
3917 if (i == password_history_length - 3 ||
3918 (i == password_history_length - 2 && interactive)) {
3919 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3920 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3921 } else {
3922 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3923 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3926 tmp = badpwdcount;
3929 return true;
3932 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3933 struct torture_context *tctx,
3934 uint32_t acct_flags,
3935 const char *acct_name,
3936 struct policy_handle *domain_handle,
3937 struct policy_handle *user_handle,
3938 char **password,
3939 struct cli_credentials *machine_credentials)
3941 union samr_DomainInfo *q_info, s_info;
3942 struct samr_DomInfo1 info1, _info1;
3943 struct samr_DomInfo12 info12, _info12;
3944 bool ret = true;
3945 struct dcerpc_binding_handle *b = p->binding_handle;
3946 struct dcerpc_pipe *np;
3947 int i;
3949 struct {
3950 const char *comment;
3951 bool disabled;
3952 bool interactive;
3953 NTSTATUS expected_success_status;
3954 } creds[] = {
3956 .comment = "network logon (disabled account)",
3957 .disabled = true,
3958 .interactive = false,
3959 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3962 .comment = "network logon (enabled account)",
3963 .disabled = false,
3964 .interactive = false,
3965 .expected_success_status= NT_STATUS_OK
3968 .comment = "interactive logon (disabled account)",
3969 .disabled = true,
3970 .interactive = true,
3971 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3974 .comment = "interactive logon (enabled account)",
3975 .disabled = false,
3976 .interactive = true,
3977 .expected_success_status= NT_STATUS_OK
3981 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3983 /* backup old policies */
3985 torture_assert(tctx,
3986 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3987 DomainPasswordInformation, &q_info),
3988 "failed to query domain info level 1");
3990 info1 = q_info->info1;
3991 _info1 = info1;
3993 torture_assert(tctx,
3994 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3995 DomainLockoutInformation, &q_info),
3996 "failed to query domain info level 12");
3998 info12 = q_info->info12;
3999 _info12 = info12;
4001 /* run tests */
4003 for (i=0; i < ARRAY_SIZE(creds); i++) {
4005 /* skip trust tests for now */
4006 if (acct_flags & ACB_WSTRUST ||
4007 acct_flags & ACB_SVRTRUST ||
4008 acct_flags & ACB_DOMTRUST) {
4009 continue;
4012 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4013 domain_handle, user_handle, password,
4014 machine_credentials,
4015 creds[i].comment,
4016 creds[i].disabled,
4017 creds[i].interactive,
4018 creds[i].expected_success_status,
4019 &_info1, &_info12);
4020 if (!ret) {
4021 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4022 } else {
4023 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4027 /* restore policies */
4029 s_info.info1 = info1;
4031 torture_assert(tctx,
4032 test_SetDomainInfo(b, tctx, domain_handle,
4033 DomainPasswordInformation, &s_info),
4034 "failed to set password information");
4036 s_info.info12 = info12;
4038 torture_assert(tctx,
4039 test_SetDomainInfo(b, tctx, domain_handle,
4040 DomainLockoutInformation, &s_info),
4041 "failed to set lockout information");
4043 return ret;
4046 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
4047 struct torture_context *tctx,
4048 struct policy_handle *handle,
4049 uint32_t *acct_flags)
4051 union samr_UserInfo *info;
4052 struct samr_QueryUserInfo r;
4054 r.in.user_handle = handle;
4055 r.in.level = 16;
4056 r.out.info = &info;
4058 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4060 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4061 "failed to query userinfo");
4062 torture_assert_ntstatus_ok(tctx, r.out.result,
4063 "failed to query userinfo");
4065 *acct_flags = info->info16.acct_flags;
4067 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
4069 return true;
4072 static bool test_Password_lockout(struct dcerpc_pipe *p,
4073 struct dcerpc_pipe *np,
4074 struct torture_context *tctx,
4075 uint32_t acct_flags,
4076 const char *acct_name,
4077 struct policy_handle *domain_handle,
4078 struct policy_handle *user_handle,
4079 char **password,
4080 struct cli_credentials *machine_credentials,
4081 const char *comment,
4082 bool disable,
4083 bool interactive,
4084 NTSTATUS expected_success_status,
4085 struct samr_DomInfo1 *info1,
4086 struct samr_DomInfo12 *info12)
4088 union samr_DomainInfo info;
4089 uint32_t badpwdcount;
4090 uint32_t password_history_length = 1;
4091 uint64_t lockout_threshold = 1;
4092 uint32_t lockout_seconds = 5;
4093 uint64_t delta_time_factor = 10 * 1000 * 1000;
4094 struct dcerpc_binding_handle *b = p->binding_handle;
4096 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4098 /* set policies */
4100 info.info1 = *info1;
4102 torture_comment(tctx, "setting password history length.\n");
4103 info.info1.password_history_length = password_history_length;
4105 torture_assert(tctx,
4106 test_SetDomainInfo(b, tctx, domain_handle,
4107 DomainPasswordInformation, &info),
4108 "failed to set password history length");
4110 info.info12 = *info12;
4111 info.info12.lockout_threshold = lockout_threshold;
4113 /* set lockout duration < lockout window: should fail */
4114 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4115 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4117 torture_assert(tctx,
4118 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4119 DomainLockoutInformation, &info,
4120 NT_STATUS_INVALID_PARAMETER),
4121 "setting lockout duration < lockout window gave unexpected result");
4123 info.info12.lockout_duration = 0;
4124 info.info12.lockout_window = 0;
4126 torture_assert(tctx,
4127 test_SetDomainInfo(b, tctx, domain_handle,
4128 DomainLockoutInformation, &info),
4129 "failed to set lockout window and duration to 0");
4132 /* set lockout duration of 5 seconds */
4133 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4134 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4136 torture_assert(tctx,
4137 test_SetDomainInfo(b, tctx, domain_handle,
4138 DomainLockoutInformation, &info),
4139 "failed to set lockout window and duration to 5 seconds");
4141 /* reset bad pwd count */
4143 torture_assert(tctx,
4144 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4147 /* enable or disable account */
4149 if (disable) {
4150 torture_assert(tctx,
4151 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4152 acct_flags | ACB_DISABLED),
4153 "failed to disable user");
4154 } else {
4155 torture_assert(tctx,
4156 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4157 acct_flags & ~ACB_DISABLED),
4158 "failed to enable user");
4162 /* test logon with right password */
4164 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4165 acct_name, *password,
4166 expected_success_status, interactive)) {
4167 torture_fail(tctx, "failed to auth with latest password");
4170 torture_assert(tctx,
4171 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4172 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4175 /* test with wrong password ==> lockout */
4177 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4178 acct_name, "random_crap",
4179 NT_STATUS_WRONG_PASSWORD, interactive)) {
4180 torture_fail(tctx, "succeeded to authenticate with wrong password");
4183 torture_assert(tctx,
4184 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4185 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4187 torture_assert(tctx,
4188 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4189 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4190 "expected account to be locked");
4193 /* test with good password */
4195 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4196 *password,
4197 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4199 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4202 /* bad pwd count should not get updated */
4203 torture_assert(tctx,
4204 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4205 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4207 /* curiously, windows does _not_ set the autlock flag */
4208 torture_assert(tctx,
4209 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4210 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4211 "expected account to be locked");
4214 /* with bad password */
4216 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4217 acct_name, "random_crap2",
4218 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4220 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4223 /* bad pwd count should not get updated */
4224 torture_assert(tctx,
4225 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4226 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4228 /* curiously, windows does _not_ set the autlock flag */
4229 torture_assert(tctx,
4230 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4231 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4232 "expected account to be locked");
4235 /* let lockout duration expire ==> unlock */
4237 torture_comment(tctx, "let lockout duration expire...\n");
4238 sleep(lockout_seconds + 1);
4240 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4241 *password,
4242 expected_success_status, interactive))
4244 torture_fail(tctx, "failed to authenticate after lockout expired");
4247 torture_assert(tctx,
4248 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4249 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4250 "expected account not to be locked");
4252 return true;
4255 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4256 struct torture_context *tctx,
4257 uint32_t acct_flags,
4258 const char *acct_name,
4259 struct policy_handle *domain_handle,
4260 struct policy_handle *user_handle,
4261 char **password,
4262 struct cli_credentials *machine_credentials)
4264 union samr_DomainInfo *q_info, s_info;
4265 struct samr_DomInfo1 info1, _info1;
4266 struct samr_DomInfo12 info12, _info12;
4267 bool ret = true;
4268 struct dcerpc_binding_handle *b = p->binding_handle;
4269 struct dcerpc_pipe *np;
4270 int i;
4272 struct {
4273 const char *comment;
4274 bool disabled;
4275 bool interactive;
4276 NTSTATUS expected_success_status;
4277 } creds[] = {
4279 .comment = "network logon (disabled account)",
4280 .disabled = true,
4281 .interactive = false,
4282 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4285 .comment = "network logon (enabled account)",
4286 .disabled = false,
4287 .interactive = false,
4288 .expected_success_status= NT_STATUS_OK
4291 .comment = "interactive logon (disabled account)",
4292 .disabled = true,
4293 .interactive = true,
4294 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4297 .comment = "interactive logon (enabled account)",
4298 .disabled = false,
4299 .interactive = true,
4300 .expected_success_status= NT_STATUS_OK
4304 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4306 /* backup old policies */
4308 torture_assert(tctx,
4309 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4310 DomainPasswordInformation, &q_info),
4311 "failed to query domain info level 1");
4313 info1 = q_info->info1;
4314 _info1 = info1;
4316 torture_assert(tctx,
4317 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4318 DomainLockoutInformation, &q_info),
4319 "failed to query domain info level 12");
4321 info12 = q_info->info12;
4322 _info12 = info12;
4324 /* run tests */
4326 for (i=0; i < ARRAY_SIZE(creds); i++) {
4328 /* skip trust tests for now */
4329 if (acct_flags & ACB_WSTRUST ||
4330 acct_flags & ACB_SVRTRUST ||
4331 acct_flags & ACB_DOMTRUST) {
4332 continue;
4335 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4336 domain_handle, user_handle, password,
4337 machine_credentials,
4338 creds[i].comment,
4339 creds[i].disabled,
4340 creds[i].interactive,
4341 creds[i].expected_success_status,
4342 &_info1, &_info12);
4343 if (!ret) {
4344 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4345 } else {
4346 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4350 /* restore policies */
4352 s_info.info1 = info1;
4354 torture_assert(tctx,
4355 test_SetDomainInfo(b, tctx, domain_handle,
4356 DomainPasswordInformation, &s_info),
4357 "failed to set password information");
4359 s_info.info12 = info12;
4361 torture_assert(tctx,
4362 test_SetDomainInfo(b, tctx, domain_handle,
4363 DomainLockoutInformation, &s_info),
4364 "failed to set lockout information");
4366 return ret;
4369 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4370 struct dcerpc_pipe *lp,
4371 struct torture_context *tctx,
4372 struct policy_handle *domain_handle,
4373 struct policy_handle *lsa_handle,
4374 struct policy_handle *user_handle,
4375 const struct dom_sid *domain_sid,
4376 uint32_t rid,
4377 struct cli_credentials *machine_credentials)
4379 bool ret = true;
4380 struct dcerpc_binding_handle *b = p->binding_handle;
4381 struct dcerpc_binding_handle *lb = lp->binding_handle;
4383 struct policy_handle lsa_acct_handle;
4384 struct dom_sid *user_sid;
4386 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4389 struct lsa_EnumAccountRights r;
4390 struct lsa_RightSet rights;
4392 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4394 r.in.handle = lsa_handle;
4395 r.in.sid = user_sid;
4396 r.out.rights = &rights;
4398 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4399 "lsa_EnumAccountRights failed");
4400 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4401 "Expected enum rights for account to fail");
4405 struct lsa_RightSet rights;
4406 struct lsa_StringLarge names[2];
4407 struct lsa_AddAccountRights r;
4409 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4411 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4412 init_lsa_StringLarge(&names[1], NULL);
4414 rights.count = 1;
4415 rights.names = names;
4417 r.in.handle = lsa_handle;
4418 r.in.sid = user_sid;
4419 r.in.rights = &rights;
4421 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4422 "lsa_AddAccountRights failed");
4423 torture_assert_ntstatus_ok(tctx, r.out.result,
4424 "Failed to add privileges");
4428 struct lsa_EnumAccounts r;
4429 uint32_t resume_handle = 0;
4430 struct lsa_SidArray lsa_sid_array;
4431 int i;
4432 bool found_sid = false;
4434 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4436 r.in.handle = lsa_handle;
4437 r.in.num_entries = 0x1000;
4438 r.in.resume_handle = &resume_handle;
4439 r.out.sids = &lsa_sid_array;
4440 r.out.resume_handle = &resume_handle;
4442 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4443 "lsa_EnumAccounts failed");
4444 torture_assert_ntstatus_ok(tctx, r.out.result,
4445 "Failed to enum accounts");
4447 for (i=0; i < lsa_sid_array.num_sids; i++) {
4448 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4449 found_sid = true;
4453 torture_assert(tctx, found_sid,
4454 "failed to list privileged account");
4458 struct lsa_EnumAccountRights r;
4459 struct lsa_RightSet user_rights;
4461 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4463 r.in.handle = lsa_handle;
4464 r.in.sid = user_sid;
4465 r.out.rights = &user_rights;
4467 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4468 "lsa_EnumAccountRights failed");
4469 torture_assert_ntstatus_ok(tctx, r.out.result,
4470 "Failed to enum rights for account");
4472 if (user_rights.count < 1) {
4473 torture_warning(tctx, "failed to find newly added rights");
4474 return false;
4479 struct lsa_OpenAccount r;
4481 torture_comment(tctx, "Testing LSA OpenAccount\n");
4483 r.in.handle = lsa_handle;
4484 r.in.sid = user_sid;
4485 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4486 r.out.acct_handle = &lsa_acct_handle;
4488 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4489 "lsa_OpenAccount failed");
4490 torture_assert_ntstatus_ok(tctx, r.out.result,
4491 "Failed to open lsa account");
4495 struct lsa_GetSystemAccessAccount r;
4496 uint32_t access_mask;
4498 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4500 r.in.handle = &lsa_acct_handle;
4501 r.out.access_mask = &access_mask;
4503 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4504 "lsa_GetSystemAccessAccount failed");
4505 torture_assert_ntstatus_ok(tctx, r.out.result,
4506 "Failed to get lsa system access account");
4510 struct lsa_Close r;
4512 torture_comment(tctx, "Testing LSA Close\n");
4514 r.in.handle = &lsa_acct_handle;
4515 r.out.handle = &lsa_acct_handle;
4517 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4518 "lsa_Close failed");
4519 torture_assert_ntstatus_ok(tctx, r.out.result,
4520 "Failed to close lsa");
4524 struct samr_DeleteUser r;
4526 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4528 r.in.user_handle = user_handle;
4529 r.out.user_handle = user_handle;
4531 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4532 "DeleteUser failed");
4533 torture_assert_ntstatus_ok(tctx, r.out.result,
4534 "DeleteUser failed");
4538 struct lsa_EnumAccounts r;
4539 uint32_t resume_handle = 0;
4540 struct lsa_SidArray lsa_sid_array;
4541 int i;
4542 bool found_sid = false;
4544 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4546 r.in.handle = lsa_handle;
4547 r.in.num_entries = 0x1000;
4548 r.in.resume_handle = &resume_handle;
4549 r.out.sids = &lsa_sid_array;
4550 r.out.resume_handle = &resume_handle;
4552 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4553 "lsa_EnumAccounts failed");
4554 torture_assert_ntstatus_ok(tctx, r.out.result,
4555 "Failed to enum accounts");
4557 for (i=0; i < lsa_sid_array.num_sids; i++) {
4558 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4559 found_sid = true;
4563 torture_assert(tctx, found_sid,
4564 "failed to list privileged account");
4568 struct lsa_EnumAccountRights r;
4569 struct lsa_RightSet user_rights;
4571 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4573 r.in.handle = lsa_handle;
4574 r.in.sid = user_sid;
4575 r.out.rights = &user_rights;
4577 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4578 "lsa_EnumAccountRights failed");
4579 torture_assert_ntstatus_ok(tctx, r.out.result,
4580 "Failed to enum rights for account");
4582 if (user_rights.count < 1) {
4583 torture_warning(tctx, "failed to find newly added rights");
4584 return false;
4589 struct lsa_OpenAccount r;
4591 torture_comment(tctx, "Testing LSA OpenAccount\n");
4593 r.in.handle = lsa_handle;
4594 r.in.sid = user_sid;
4595 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4596 r.out.acct_handle = &lsa_acct_handle;
4598 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4599 "lsa_OpenAccount failed");
4600 torture_assert_ntstatus_ok(tctx, r.out.result,
4601 "Failed to open lsa account");
4605 struct lsa_GetSystemAccessAccount r;
4606 uint32_t access_mask;
4608 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4610 r.in.handle = &lsa_acct_handle;
4611 r.out.access_mask = &access_mask;
4613 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4614 "lsa_GetSystemAccessAccount failed");
4615 torture_assert_ntstatus_ok(tctx, r.out.result,
4616 "Failed to get lsa system access account");
4620 struct lsa_DeleteObject r;
4622 torture_comment(tctx, "Testing LSA DeleteObject\n");
4624 r.in.handle = &lsa_acct_handle;
4625 r.out.handle = &lsa_acct_handle;
4627 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4628 "lsa_DeleteObject failed");
4629 torture_assert_ntstatus_ok(tctx, r.out.result,
4630 "Failed to delete object");
4634 struct lsa_EnumAccounts r;
4635 uint32_t resume_handle = 0;
4636 struct lsa_SidArray lsa_sid_array;
4637 int i;
4638 bool found_sid = false;
4640 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4642 r.in.handle = lsa_handle;
4643 r.in.num_entries = 0x1000;
4644 r.in.resume_handle = &resume_handle;
4645 r.out.sids = &lsa_sid_array;
4646 r.out.resume_handle = &resume_handle;
4648 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4649 "lsa_EnumAccounts failed");
4650 torture_assert_ntstatus_ok(tctx, r.out.result,
4651 "Failed to enum accounts");
4653 for (i=0; i < lsa_sid_array.num_sids; i++) {
4654 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4655 found_sid = true;
4659 torture_assert(tctx, !found_sid,
4660 "should not have listed privileged account");
4664 struct lsa_EnumAccountRights r;
4665 struct lsa_RightSet user_rights;
4667 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4669 r.in.handle = lsa_handle;
4670 r.in.sid = user_sid;
4671 r.out.rights = &user_rights;
4673 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4674 "lsa_EnumAccountRights failed");
4675 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4676 "Failed to enum rights for account");
4679 return ret;
4682 static bool test_user_ops(struct dcerpc_pipe *p,
4683 struct torture_context *tctx,
4684 struct policy_handle *user_handle,
4685 struct policy_handle *domain_handle,
4686 const struct dom_sid *domain_sid,
4687 uint32_t base_acct_flags,
4688 const char *base_acct_name, enum torture_samr_choice which_ops,
4689 struct cli_credentials *machine_credentials)
4691 char *password = NULL;
4692 struct samr_QueryUserInfo q;
4693 union samr_UserInfo *info;
4694 NTSTATUS status;
4695 struct dcerpc_binding_handle *b = p->binding_handle;
4697 bool ret = true;
4698 int i;
4699 uint32_t rid;
4700 const uint32_t password_fields[] = {
4701 SAMR_FIELD_NT_PASSWORD_PRESENT,
4702 SAMR_FIELD_LM_PASSWORD_PRESENT,
4703 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4707 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4708 if (!NT_STATUS_IS_OK(status)) {
4709 ret = false;
4712 switch (which_ops) {
4713 case TORTURE_SAMR_USER_ATTRIBUTES:
4714 if (!test_QuerySecurity(b, tctx, user_handle)) {
4715 ret = false;
4718 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4719 ret = false;
4722 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4723 ret = false;
4726 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4727 base_acct_name)) {
4728 ret = false;
4731 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4732 ret = false;
4735 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4736 ret = false;
4739 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4740 ret = false;
4742 break;
4743 case TORTURE_SAMR_PASSWORDS:
4744 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4745 char simple_pass[9];
4746 char *v = generate_random_str(tctx, 1);
4748 ZERO_STRUCT(simple_pass);
4749 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4751 torture_comment(tctx, "Testing machine account password policy rules\n");
4753 /* Workstation trust accounts don't seem to need to honour password quality policy */
4754 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4755 ret = false;
4758 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4759 ret = false;
4762 /* reset again, to allow another 'user' password change */
4763 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4764 ret = false;
4767 /* Try a 'short' password */
4768 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4769 ret = false;
4772 /* Try a compleatly random password */
4773 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4774 ret = false;
4778 for (i = 0; password_fields[i]; i++) {
4779 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4780 ret = false;
4783 /* check it was set right */
4784 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4785 ret = false;
4789 for (i = 0; password_fields[i]; i++) {
4790 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4791 ret = false;
4794 /* check it was set right */
4795 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4796 ret = false;
4800 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4801 ret = false;
4804 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4805 ret = false;
4808 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4809 ret = false;
4812 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4813 ret = false;
4816 for (i = 0; password_fields[i]; i++) {
4818 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4819 /* we need to skip as that would break
4820 * the ChangePasswordUser3 verify */
4821 continue;
4824 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4825 ret = false;
4828 /* check it was set right */
4829 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4830 ret = false;
4834 q.in.user_handle = user_handle;
4835 q.in.level = 5;
4836 q.out.info = &info;
4838 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4839 "QueryUserInfo failed");
4840 if (!NT_STATUS_IS_OK(q.out.result)) {
4841 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4842 q.in.level, nt_errstr(q.out.result));
4843 ret = false;
4844 } else {
4845 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4846 if ((info->info5.acct_flags) != expected_flags) {
4847 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4848 info->info5.acct_flags,
4849 expected_flags);
4850 /* FIXME: GD */
4851 if (!torture_setting_bool(tctx, "samba3", false)) {
4852 ret = false;
4855 if (info->info5.rid != rid) {
4856 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4857 info->info5.rid, rid);
4862 break;
4864 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4866 /* test last password change timestamp behaviour */
4867 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4868 base_acct_name,
4869 user_handle, &password,
4870 machine_credentials)) {
4871 ret = false;
4874 if (ret == true) {
4875 torture_comment(tctx, "pwdLastSet test succeeded\n");
4876 } else {
4877 torture_warning(tctx, "pwdLastSet test failed\n");
4880 break;
4882 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4884 /* test bad pwd count change behaviour */
4885 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4886 base_acct_name,
4887 domain_handle,
4888 user_handle, &password,
4889 machine_credentials)) {
4890 ret = false;
4893 if (ret == true) {
4894 torture_comment(tctx, "badPwdCount test succeeded\n");
4895 } else {
4896 torture_warning(tctx, "badPwdCount test failed\n");
4899 break;
4901 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4903 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4904 base_acct_name,
4905 domain_handle,
4906 user_handle, &password,
4907 machine_credentials))
4909 ret = false;
4912 if (ret == true) {
4913 torture_comment(tctx, "lockout test succeeded\n");
4914 } else {
4915 torture_warning(tctx, "lockout test failed\n");
4918 break;
4921 case TORTURE_SAMR_USER_PRIVILEGES: {
4923 struct dcerpc_pipe *lp;
4924 struct policy_handle *lsa_handle;
4925 struct dcerpc_binding_handle *lb;
4927 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4928 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4929 lb = lp->binding_handle;
4931 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4932 ret = false;
4935 if (!test_DeleteUser_with_privs(p, lp, tctx,
4936 domain_handle, lsa_handle, user_handle,
4937 domain_sid, rid,
4938 machine_credentials)) {
4939 ret = false;
4942 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4943 ret = false;
4946 if (!ret) {
4947 torture_warning(tctx, "privileged user delete test failed\n");
4950 break;
4952 case TORTURE_SAMR_OTHER:
4953 case TORTURE_SAMR_MANY_ACCOUNTS:
4954 case TORTURE_SAMR_MANY_GROUPS:
4955 case TORTURE_SAMR_MANY_ALIASES:
4956 /* We just need the account to exist */
4957 break;
4959 return ret;
4962 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4963 struct torture_context *tctx,
4964 struct policy_handle *alias_handle,
4965 const struct dom_sid *domain_sid)
4967 bool ret = true;
4969 if (!torture_setting_bool(tctx, "samba3", false)) {
4970 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4971 ret = false;
4975 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4976 ret = false;
4979 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4980 ret = false;
4983 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
4984 ret = false;
4987 if (torture_setting_bool(tctx, "samba3", false) ||
4988 torture_setting_bool(tctx, "samba4", false)) {
4989 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4990 return ret;
4993 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
4994 ret = false;
4997 return ret;
5001 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
5002 struct torture_context *tctx,
5003 struct policy_handle *user_handle)
5005 struct samr_DeleteUser d;
5006 torture_comment(tctx, "Testing DeleteUser\n");
5008 d.in.user_handle = user_handle;
5009 d.out.user_handle = user_handle;
5011 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5012 "DeleteUser failed");
5013 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5015 return true;
5018 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5019 struct torture_context *tctx,
5020 struct policy_handle *handle, const char *name)
5022 NTSTATUS status;
5023 struct samr_DeleteUser d;
5024 struct policy_handle user_handle;
5025 uint32_t rid;
5027 status = test_LookupName(b, tctx, handle, name, &rid);
5028 if (!NT_STATUS_IS_OK(status)) {
5029 goto failed;
5032 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5033 if (!NT_STATUS_IS_OK(status)) {
5034 goto failed;
5037 d.in.user_handle = &user_handle;
5038 d.out.user_handle = &user_handle;
5039 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5040 "DeleteUser failed");
5041 if (!NT_STATUS_IS_OK(d.out.result)) {
5042 status = d.out.result;
5043 goto failed;
5046 return true;
5048 failed:
5049 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
5050 return false;
5054 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
5055 struct torture_context *tctx,
5056 struct policy_handle *handle, const char *name)
5058 NTSTATUS status;
5059 struct samr_OpenGroup r;
5060 struct samr_DeleteDomainGroup d;
5061 struct policy_handle group_handle;
5062 uint32_t rid;
5064 status = test_LookupName(b, tctx, handle, name, &rid);
5065 if (!NT_STATUS_IS_OK(status)) {
5066 goto failed;
5069 r.in.domain_handle = handle;
5070 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5071 r.in.rid = rid;
5072 r.out.group_handle = &group_handle;
5073 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5074 "OpenGroup failed");
5075 if (!NT_STATUS_IS_OK(r.out.result)) {
5076 status = r.out.result;
5077 goto failed;
5080 d.in.group_handle = &group_handle;
5081 d.out.group_handle = &group_handle;
5082 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
5083 "DeleteDomainGroup failed");
5084 if (!NT_STATUS_IS_OK(d.out.result)) {
5085 status = d.out.result;
5086 goto failed;
5089 return true;
5091 failed:
5092 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
5093 return false;
5097 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
5098 struct torture_context *tctx,
5099 struct policy_handle *domain_handle,
5100 const char *name)
5102 NTSTATUS status;
5103 struct samr_OpenAlias r;
5104 struct samr_DeleteDomAlias d;
5105 struct policy_handle alias_handle;
5106 uint32_t rid;
5108 torture_comment(tctx, "Testing DeleteAlias_byname\n");
5110 status = test_LookupName(b, tctx, domain_handle, name, &rid);
5111 if (!NT_STATUS_IS_OK(status)) {
5112 goto failed;
5115 r.in.domain_handle = domain_handle;
5116 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5117 r.in.rid = rid;
5118 r.out.alias_handle = &alias_handle;
5119 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5120 "OpenAlias failed");
5121 if (!NT_STATUS_IS_OK(r.out.result)) {
5122 status = r.out.result;
5123 goto failed;
5126 d.in.alias_handle = &alias_handle;
5127 d.out.alias_handle = &alias_handle;
5128 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5129 "DeleteDomAlias failed");
5130 if (!NT_STATUS_IS_OK(d.out.result)) {
5131 status = d.out.result;
5132 goto failed;
5135 return true;
5137 failed:
5138 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5139 return false;
5142 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5143 struct torture_context *tctx,
5144 struct policy_handle *alias_handle)
5146 struct samr_DeleteDomAlias d;
5147 bool ret = true;
5149 torture_comment(tctx, "Testing DeleteAlias\n");
5151 d.in.alias_handle = alias_handle;
5152 d.out.alias_handle = alias_handle;
5154 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5155 "DeleteDomAlias failed");
5156 if (!NT_STATUS_IS_OK(d.out.result)) {
5157 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5158 ret = false;
5161 return ret;
5164 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5165 struct torture_context *tctx,
5166 struct policy_handle *domain_handle,
5167 const char *alias_name,
5168 struct policy_handle *alias_handle,
5169 const struct dom_sid *domain_sid,
5170 bool test_alias)
5172 struct samr_CreateDomAlias r;
5173 struct lsa_String name;
5174 uint32_t rid;
5175 bool ret = true;
5177 init_lsa_String(&name, alias_name);
5178 r.in.domain_handle = domain_handle;
5179 r.in.alias_name = &name;
5180 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5181 r.out.alias_handle = alias_handle;
5182 r.out.rid = &rid;
5184 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5186 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5187 "CreateDomAlias failed");
5189 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5190 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5191 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5192 return true;
5193 } else {
5194 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5195 nt_errstr(r.out.result));
5196 return false;
5200 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5201 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5202 return false;
5204 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5205 "CreateDomAlias failed");
5208 if (!NT_STATUS_IS_OK(r.out.result)) {
5209 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5210 return false;
5213 if (!test_alias) {
5214 return ret;
5217 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5218 ret = false;
5221 return ret;
5224 static bool test_ChangePassword(struct dcerpc_pipe *p,
5225 struct torture_context *tctx,
5226 const char *acct_name,
5227 struct policy_handle *domain_handle, char **password)
5229 bool ret = true;
5230 struct dcerpc_binding_handle *b = p->binding_handle;
5232 if (!*password) {
5233 return false;
5236 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5237 ret = false;
5240 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5241 ret = false;
5244 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5245 ret = false;
5248 /* test what happens when setting the old password again */
5249 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5250 ret = false;
5254 char simple_pass[9];
5255 char *v = generate_random_str(tctx, 1);
5257 ZERO_STRUCT(simple_pass);
5258 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5260 /* test what happens when picking a simple password */
5261 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5262 ret = false;
5266 /* set samr_SetDomainInfo level 1 with min_length 5 */
5268 struct samr_QueryDomainInfo r;
5269 union samr_DomainInfo *info = NULL;
5270 struct samr_SetDomainInfo s;
5271 uint16_t len_old, len;
5272 uint32_t pwd_prop_old;
5273 int64_t min_pwd_age_old;
5275 len = 5;
5277 r.in.domain_handle = domain_handle;
5278 r.in.level = 1;
5279 r.out.info = &info;
5281 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5282 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5283 "QueryDomainInfo failed");
5284 if (!NT_STATUS_IS_OK(r.out.result)) {
5285 return false;
5288 s.in.domain_handle = domain_handle;
5289 s.in.level = 1;
5290 s.in.info = info;
5292 /* remember the old min length, so we can reset it */
5293 len_old = s.in.info->info1.min_password_length;
5294 s.in.info->info1.min_password_length = len;
5295 pwd_prop_old = s.in.info->info1.password_properties;
5296 /* turn off password complexity checks for this test */
5297 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5299 min_pwd_age_old = s.in.info->info1.min_password_age;
5300 s.in.info->info1.min_password_age = 0;
5302 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5303 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5304 "SetDomainInfo failed");
5305 if (!NT_STATUS_IS_OK(s.out.result)) {
5306 return false;
5309 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5311 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5312 ret = false;
5315 s.in.info->info1.min_password_length = len_old;
5316 s.in.info->info1.password_properties = pwd_prop_old;
5317 s.in.info->info1.min_password_age = min_pwd_age_old;
5319 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5320 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5321 "SetDomainInfo failed");
5322 if (!NT_STATUS_IS_OK(s.out.result)) {
5323 return false;
5329 struct samr_OpenUser r;
5330 struct samr_QueryUserInfo q;
5331 union samr_UserInfo *info;
5332 struct samr_LookupNames n;
5333 struct policy_handle user_handle;
5334 struct samr_Ids rids, types;
5336 n.in.domain_handle = domain_handle;
5337 n.in.num_names = 1;
5338 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5339 n.in.names[0].string = acct_name;
5340 n.out.rids = &rids;
5341 n.out.types = &types;
5343 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5344 "LookupNames failed");
5345 if (!NT_STATUS_IS_OK(n.out.result)) {
5346 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5347 return false;
5350 r.in.domain_handle = domain_handle;
5351 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5352 r.in.rid = n.out.rids->ids[0];
5353 r.out.user_handle = &user_handle;
5355 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5356 "OpenUser failed");
5357 if (!NT_STATUS_IS_OK(r.out.result)) {
5358 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5359 return false;
5362 q.in.user_handle = &user_handle;
5363 q.in.level = 5;
5364 q.out.info = &info;
5366 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5367 "QueryUserInfo failed");
5368 if (!NT_STATUS_IS_OK(q.out.result)) {
5369 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5370 return false;
5373 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5375 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5376 info->info5.last_password_change, true)) {
5377 ret = false;
5381 /* we change passwords twice - this has the effect of verifying
5382 they were changed correctly for the final call */
5383 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5384 ret = false;
5387 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5388 ret = false;
5391 return ret;
5394 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5395 struct policy_handle *domain_handle,
5396 const char *user_name,
5397 struct policy_handle *user_handle_out,
5398 struct dom_sid *domain_sid,
5399 enum torture_samr_choice which_ops,
5400 struct cli_credentials *machine_credentials,
5401 bool test_user)
5404 TALLOC_CTX *user_ctx;
5406 struct samr_CreateUser r;
5407 struct samr_QueryUserInfo q;
5408 union samr_UserInfo *info;
5409 struct samr_DeleteUser d;
5410 uint32_t rid;
5412 /* This call creates a 'normal' account - check that it really does */
5413 const uint32_t acct_flags = ACB_NORMAL;
5414 struct lsa_String name;
5415 bool ret = true;
5416 struct dcerpc_binding_handle *b = p->binding_handle;
5418 struct policy_handle user_handle;
5419 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5420 init_lsa_String(&name, user_name);
5422 r.in.domain_handle = domain_handle;
5423 r.in.account_name = &name;
5424 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5425 r.out.user_handle = &user_handle;
5426 r.out.rid = &rid;
5428 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5430 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5431 "CreateUser failed");
5433 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5434 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5435 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5436 return true;
5437 } else {
5438 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5439 nt_errstr(r.out.result));
5440 return false;
5444 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5445 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5446 talloc_free(user_ctx);
5447 return false;
5449 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5450 "CreateUser failed");
5453 if (!NT_STATUS_IS_OK(r.out.result)) {
5454 talloc_free(user_ctx);
5455 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5456 return false;
5459 if (!test_user) {
5460 if (user_handle_out) {
5461 *user_handle_out = user_handle;
5463 return ret;
5467 q.in.user_handle = &user_handle;
5468 q.in.level = 16;
5469 q.out.info = &info;
5471 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5472 "QueryUserInfo failed");
5473 if (!NT_STATUS_IS_OK(q.out.result)) {
5474 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5475 q.in.level, nt_errstr(q.out.result));
5476 ret = false;
5477 } else {
5478 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5479 torture_warning(tctx, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5480 info->info16.acct_flags,
5481 acct_flags);
5482 ret = false;
5486 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5487 domain_sid, acct_flags, name.string, which_ops,
5488 machine_credentials)) {
5489 ret = false;
5492 if (user_handle_out) {
5493 *user_handle_out = user_handle;
5494 } else {
5495 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5497 d.in.user_handle = &user_handle;
5498 d.out.user_handle = &user_handle;
5500 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5501 "DeleteUser failed");
5502 if (!NT_STATUS_IS_OK(d.out.result)) {
5503 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5504 ret = false;
5510 talloc_free(user_ctx);
5512 return ret;
5516 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5517 struct policy_handle *domain_handle,
5518 struct dom_sid *domain_sid,
5519 enum torture_samr_choice which_ops,
5520 struct cli_credentials *machine_credentials)
5522 struct samr_CreateUser2 r;
5523 struct samr_QueryUserInfo q;
5524 union samr_UserInfo *info;
5525 struct samr_DeleteUser d;
5526 struct policy_handle user_handle;
5527 uint32_t rid;
5528 struct lsa_String name;
5529 bool ret = true;
5530 int i;
5531 struct dcerpc_binding_handle *b = p->binding_handle;
5533 struct {
5534 uint32_t acct_flags;
5535 const char *account_name;
5536 NTSTATUS nt_status;
5537 } account_types[] = {
5538 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5539 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5540 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5541 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5542 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5543 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5544 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5545 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5546 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5547 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5548 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5549 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5550 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5551 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5552 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5555 for (i = 0; account_types[i].account_name; i++) {
5556 TALLOC_CTX *user_ctx;
5557 uint32_t acct_flags = account_types[i].acct_flags;
5558 uint32_t access_granted;
5559 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5560 init_lsa_String(&name, account_types[i].account_name);
5562 r.in.domain_handle = domain_handle;
5563 r.in.account_name = &name;
5564 r.in.acct_flags = acct_flags;
5565 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5566 r.out.user_handle = &user_handle;
5567 r.out.access_granted = &access_granted;
5568 r.out.rid = &rid;
5570 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5572 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5573 "CreateUser2 failed");
5575 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5576 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5577 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5578 continue;
5579 } else {
5580 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5581 nt_errstr(r.out.result));
5582 ret = false;
5583 continue;
5587 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5588 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5589 talloc_free(user_ctx);
5590 ret = false;
5591 continue;
5593 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5594 "CreateUser2 failed");
5597 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5598 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5599 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5600 ret = false;
5603 if (NT_STATUS_IS_OK(r.out.result)) {
5604 q.in.user_handle = &user_handle;
5605 q.in.level = 5;
5606 q.out.info = &info;
5608 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5609 "QueryUserInfo failed");
5610 if (!NT_STATUS_IS_OK(q.out.result)) {
5611 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5612 q.in.level, nt_errstr(q.out.result));
5613 ret = false;
5614 } else {
5615 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5616 if (acct_flags == ACB_NORMAL) {
5617 expected_flags |= ACB_PW_EXPIRED;
5619 if ((info->info5.acct_flags) != expected_flags) {
5620 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5621 info->info5.acct_flags,
5622 expected_flags);
5623 ret = false;
5625 switch (acct_flags) {
5626 case ACB_SVRTRUST:
5627 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5628 torture_warning(tctx, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5629 DOMAIN_RID_DCS, info->info5.primary_gid);
5630 ret = false;
5632 break;
5633 case ACB_WSTRUST:
5634 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5635 torture_warning(tctx, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5636 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5637 ret = false;
5639 break;
5640 case ACB_NORMAL:
5641 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5642 torture_warning(tctx, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5643 DOMAIN_RID_USERS, info->info5.primary_gid);
5644 ret = false;
5646 break;
5650 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5651 domain_sid, acct_flags, name.string, which_ops,
5652 machine_credentials)) {
5653 ret = false;
5656 if (!ndr_policy_handle_empty(&user_handle)) {
5657 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5659 d.in.user_handle = &user_handle;
5660 d.out.user_handle = &user_handle;
5662 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5663 "DeleteUser failed");
5664 if (!NT_STATUS_IS_OK(d.out.result)) {
5665 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5666 ret = false;
5670 talloc_free(user_ctx);
5673 return ret;
5676 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5677 struct torture_context *tctx,
5678 struct policy_handle *handle)
5680 struct samr_QueryAliasInfo r;
5681 union samr_AliasInfo *info;
5682 uint16_t levels[] = {1, 2, 3};
5683 int i;
5684 bool ret = true;
5686 for (i=0;i<ARRAY_SIZE(levels);i++) {
5687 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5689 r.in.alias_handle = handle;
5690 r.in.level = levels[i];
5691 r.out.info = &info;
5693 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5694 "QueryAliasInfo failed");
5695 if (!NT_STATUS_IS_OK(r.out.result)) {
5696 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5697 levels[i], nt_errstr(r.out.result));
5698 ret = false;
5702 return ret;
5705 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5706 struct torture_context *tctx,
5707 struct policy_handle *handle)
5709 struct samr_QueryGroupInfo r;
5710 union samr_GroupInfo *info;
5711 uint16_t levels[] = {1, 2, 3, 4, 5};
5712 int i;
5713 bool ret = true;
5715 for (i=0;i<ARRAY_SIZE(levels);i++) {
5716 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5718 r.in.group_handle = handle;
5719 r.in.level = levels[i];
5720 r.out.info = &info;
5722 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5723 "QueryGroupInfo failed");
5724 if (!NT_STATUS_IS_OK(r.out.result)) {
5725 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5726 levels[i], nt_errstr(r.out.result));
5727 ret = false;
5731 return ret;
5734 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5735 struct torture_context *tctx,
5736 struct policy_handle *handle)
5738 struct samr_QueryGroupMember r;
5739 struct samr_RidAttrArray *rids = NULL;
5740 bool ret = true;
5742 torture_comment(tctx, "Testing QueryGroupMember\n");
5744 r.in.group_handle = handle;
5745 r.out.rids = &rids;
5747 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5748 "QueryGroupMember failed");
5749 if (!NT_STATUS_IS_OK(r.out.result)) {
5750 torture_warning(tctx, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
5751 ret = false;
5754 return ret;
5758 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5759 struct torture_context *tctx,
5760 struct policy_handle *handle)
5762 struct samr_QueryGroupInfo r;
5763 union samr_GroupInfo *info;
5764 struct samr_SetGroupInfo s;
5765 uint16_t levels[] = {1, 2, 3, 4};
5766 uint16_t set_ok[] = {0, 1, 1, 1};
5767 int i;
5768 bool ret = true;
5770 for (i=0;i<ARRAY_SIZE(levels);i++) {
5771 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5773 r.in.group_handle = handle;
5774 r.in.level = levels[i];
5775 r.out.info = &info;
5777 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5778 "QueryGroupInfo failed");
5779 if (!NT_STATUS_IS_OK(r.out.result)) {
5780 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5781 levels[i], nt_errstr(r.out.result));
5782 ret = false;
5785 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5787 s.in.group_handle = handle;
5788 s.in.level = levels[i];
5789 s.in.info = *r.out.info;
5791 #if 0
5792 /* disabled this, as it changes the name only from the point of view of samr,
5793 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5794 the name is still reserved, so creating the old name fails, but deleting by the old name
5795 also fails */
5796 if (s.in.level == 2) {
5797 init_lsa_String(&s.in.info->string, "NewName");
5799 #endif
5801 if (s.in.level == 4) {
5802 init_lsa_String(&s.in.info->description, "test description");
5805 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5806 "SetGroupInfo failed");
5807 if (set_ok[i]) {
5808 if (!NT_STATUS_IS_OK(s.out.result)) {
5809 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5810 r.in.level, nt_errstr(s.out.result));
5811 ret = false;
5812 continue;
5814 } else {
5815 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5816 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5817 r.in.level, nt_errstr(s.out.result));
5818 ret = false;
5819 continue;
5824 return ret;
5827 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5828 struct torture_context *tctx,
5829 struct policy_handle *handle)
5831 struct samr_QueryUserInfo r;
5832 union samr_UserInfo *info;
5833 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5834 11, 12, 13, 14, 16, 17, 20, 21};
5835 int i;
5836 bool ret = true;
5838 for (i=0;i<ARRAY_SIZE(levels);i++) {
5839 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5841 r.in.user_handle = handle;
5842 r.in.level = levels[i];
5843 r.out.info = &info;
5845 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5846 "QueryUserInfo failed");
5847 if (!NT_STATUS_IS_OK(r.out.result)) {
5848 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5849 levels[i], nt_errstr(r.out.result));
5850 ret = false;
5854 return ret;
5857 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5858 struct torture_context *tctx,
5859 struct policy_handle *handle)
5861 struct samr_QueryUserInfo2 r;
5862 union samr_UserInfo *info;
5863 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5864 11, 12, 13, 14, 16, 17, 20, 21};
5865 int i;
5866 bool ret = true;
5868 for (i=0;i<ARRAY_SIZE(levels);i++) {
5869 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5871 r.in.user_handle = handle;
5872 r.in.level = levels[i];
5873 r.out.info = &info;
5875 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5876 "QueryUserInfo2 failed");
5877 if (!NT_STATUS_IS_OK(r.out.result)) {
5878 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5879 levels[i], nt_errstr(r.out.result));
5880 ret = false;
5884 return ret;
5887 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5888 struct torture_context *tctx,
5889 struct policy_handle *handle, uint32_t rid)
5891 struct samr_OpenUser r;
5892 struct policy_handle user_handle;
5893 bool ret = true;
5895 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5897 r.in.domain_handle = handle;
5898 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5899 r.in.rid = rid;
5900 r.out.user_handle = &user_handle;
5902 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5903 "OpenUser failed");
5904 if (!NT_STATUS_IS_OK(r.out.result)) {
5905 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5906 return false;
5909 if (!test_QuerySecurity(b, tctx, &user_handle)) {
5910 ret = false;
5913 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5914 ret = false;
5917 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5918 ret = false;
5921 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5922 ret = false;
5925 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5926 ret = false;
5929 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5930 ret = false;
5933 return ret;
5936 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5937 struct torture_context *tctx,
5938 struct policy_handle *handle, uint32_t rid)
5940 struct samr_OpenGroup r;
5941 struct policy_handle group_handle;
5942 bool ret = true;
5944 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5946 r.in.domain_handle = handle;
5947 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5948 r.in.rid = rid;
5949 r.out.group_handle = &group_handle;
5951 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5952 "OpenGroup failed");
5953 if (!NT_STATUS_IS_OK(r.out.result)) {
5954 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5955 return false;
5958 if (!torture_setting_bool(tctx, "samba3", false)) {
5959 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5960 ret = false;
5964 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5965 ret = false;
5968 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5969 ret = false;
5972 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5973 ret = false;
5976 return ret;
5979 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5980 struct torture_context *tctx,
5981 struct policy_handle *handle, uint32_t rid)
5983 struct samr_OpenAlias r;
5984 struct policy_handle alias_handle;
5985 bool ret = true;
5987 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5989 r.in.domain_handle = handle;
5990 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5991 r.in.rid = rid;
5992 r.out.alias_handle = &alias_handle;
5994 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5995 "OpenAlias failed");
5996 if (!NT_STATUS_IS_OK(r.out.result)) {
5997 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5998 return false;
6001 if (!torture_setting_bool(tctx, "samba3", false)) {
6002 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
6003 ret = false;
6007 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6008 ret = false;
6011 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6012 ret = false;
6015 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6016 ret = false;
6019 return ret;
6022 static bool check_mask(struct dcerpc_binding_handle *b,
6023 struct torture_context *tctx,
6024 struct policy_handle *handle, uint32_t rid,
6025 uint32_t acct_flag_mask)
6027 struct samr_OpenUser r;
6028 struct samr_QueryUserInfo q;
6029 union samr_UserInfo *info;
6030 struct policy_handle user_handle;
6031 bool ret = true;
6033 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6035 r.in.domain_handle = handle;
6036 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6037 r.in.rid = rid;
6038 r.out.user_handle = &user_handle;
6040 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6041 "OpenUser failed");
6042 if (!NT_STATUS_IS_OK(r.out.result)) {
6043 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6044 return false;
6047 q.in.user_handle = &user_handle;
6048 q.in.level = 16;
6049 q.out.info = &info;
6051 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6052 "QueryUserInfo failed");
6053 if (!NT_STATUS_IS_OK(q.out.result)) {
6054 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
6055 nt_errstr(q.out.result));
6056 ret = false;
6057 } else {
6058 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
6059 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
6060 acct_flag_mask, info->info16.acct_flags, rid);
6061 ret = false;
6065 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6066 ret = false;
6069 return ret;
6072 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
6073 struct torture_context *tctx,
6074 struct policy_handle *handle)
6076 struct samr_EnumDomainUsers r;
6077 uint32_t mask, resume_handle=0;
6078 int i, mask_idx;
6079 bool ret = true;
6080 struct samr_LookupNames n;
6081 struct samr_LookupRids lr ;
6082 struct lsa_Strings names;
6083 struct samr_Ids rids, types;
6084 struct samr_SamArray *sam = NULL;
6085 uint32_t num_entries = 0;
6087 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
6088 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
6089 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
6090 ACB_PWNOEXP, 0};
6092 torture_comment(tctx, "Testing EnumDomainUsers\n");
6094 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
6095 r.in.domain_handle = handle;
6096 r.in.resume_handle = &resume_handle;
6097 r.in.acct_flags = mask = masks[mask_idx];
6098 r.in.max_size = (uint32_t)-1;
6099 r.out.resume_handle = &resume_handle;
6100 r.out.num_entries = &num_entries;
6101 r.out.sam = &sam;
6103 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
6104 "EnumDomainUsers failed");
6105 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6106 !NT_STATUS_IS_OK(r.out.result)) {
6107 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
6108 return false;
6111 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6113 if (sam->count == 0) {
6114 continue;
6117 for (i=0;i<sam->count;i++) {
6118 if (mask) {
6119 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6120 ret = false;
6122 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6123 ret = false;
6128 torture_comment(tctx, "Testing LookupNames\n");
6129 n.in.domain_handle = handle;
6130 n.in.num_names = sam->count;
6131 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6132 n.out.rids = &rids;
6133 n.out.types = &types;
6134 for (i=0;i<sam->count;i++) {
6135 n.in.names[i].string = sam->entries[i].name.string;
6137 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6138 "LookupNames failed");
6139 if (!NT_STATUS_IS_OK(n.out.result)) {
6140 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6141 ret = false;
6145 torture_comment(tctx, "Testing LookupRids\n");
6146 lr.in.domain_handle = handle;
6147 lr.in.num_rids = sam->count;
6148 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6149 lr.out.names = &names;
6150 lr.out.types = &types;
6151 for (i=0;i<sam->count;i++) {
6152 lr.in.rids[i] = sam->entries[i].idx;
6154 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6155 "LookupRids failed");
6156 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6158 return ret;
6162 try blasting the server with a bunch of sync requests
6164 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6165 struct policy_handle *handle)
6167 struct samr_EnumDomainUsers r;
6168 uint32_t resume_handle=0;
6169 int i;
6170 #define ASYNC_COUNT 100
6171 struct tevent_req *req[ASYNC_COUNT];
6173 if (!torture_setting_bool(tctx, "dangerous", false)) {
6174 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6177 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6179 r.in.domain_handle = handle;
6180 r.in.resume_handle = &resume_handle;
6181 r.in.acct_flags = 0;
6182 r.in.max_size = (uint32_t)-1;
6183 r.out.resume_handle = &resume_handle;
6185 for (i=0;i<ASYNC_COUNT;i++) {
6186 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6189 for (i=0;i<ASYNC_COUNT;i++) {
6190 tevent_req_poll(req[i], tctx->ev);
6191 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6192 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6193 i, nt_errstr(r.out.result)));
6196 torture_comment(tctx, "%d async requests OK\n", i);
6198 return true;
6201 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6202 struct torture_context *tctx,
6203 struct policy_handle *handle)
6205 struct samr_EnumDomainGroups r;
6206 uint32_t resume_handle=0;
6207 struct samr_SamArray *sam = NULL;
6208 uint32_t num_entries = 0;
6209 int i;
6210 bool ret = true;
6211 bool universal_group_found = false;
6213 torture_comment(tctx, "Testing EnumDomainGroups\n");
6215 r.in.domain_handle = handle;
6216 r.in.resume_handle = &resume_handle;
6217 r.in.max_size = (uint32_t)-1;
6218 r.out.resume_handle = &resume_handle;
6219 r.out.num_entries = &num_entries;
6220 r.out.sam = &sam;
6222 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6223 "EnumDomainGroups failed");
6224 if (!NT_STATUS_IS_OK(r.out.result)) {
6225 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6226 return false;
6229 if (!sam) {
6230 return false;
6233 for (i=0;i<sam->count;i++) {
6234 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6235 ret = false;
6237 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6238 "Enterprise Admins") == 0)) {
6239 universal_group_found = true;
6243 /* when we are running this on s4 we should get back at least the
6244 * "Enterprise Admins" universal group. If we don't get a group entry
6245 * at all we probably are performing the test on the builtin domain.
6246 * So ignore this case. */
6247 if (torture_setting_bool(tctx, "samba4", false)) {
6248 if ((sam->count > 0) && (!universal_group_found)) {
6249 ret = false;
6253 return ret;
6256 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6257 struct torture_context *tctx,
6258 struct policy_handle *handle)
6260 struct samr_EnumDomainAliases r;
6261 uint32_t resume_handle=0;
6262 struct samr_SamArray *sam = NULL;
6263 uint32_t num_entries = 0;
6264 int i;
6265 bool ret = true;
6267 torture_comment(tctx, "Testing EnumDomainAliases\n");
6269 r.in.domain_handle = handle;
6270 r.in.resume_handle = &resume_handle;
6271 r.in.max_size = (uint32_t)-1;
6272 r.out.sam = &sam;
6273 r.out.num_entries = &num_entries;
6274 r.out.resume_handle = &resume_handle;
6276 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6277 "EnumDomainAliases failed");
6278 if (!NT_STATUS_IS_OK(r.out.result)) {
6279 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6280 return false;
6283 if (!sam) {
6284 return false;
6287 for (i=0;i<sam->count;i++) {
6288 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6289 ret = false;
6293 return ret;
6296 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6297 struct torture_context *tctx,
6298 struct policy_handle *handle)
6300 struct samr_GetDisplayEnumerationIndex r;
6301 bool ret = true;
6302 uint16_t levels[] = {1, 2, 3, 4, 5};
6303 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6304 struct lsa_String name;
6305 uint32_t idx = 0;
6306 int i;
6308 for (i=0;i<ARRAY_SIZE(levels);i++) {
6309 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6311 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6313 r.in.domain_handle = handle;
6314 r.in.level = levels[i];
6315 r.in.name = &name;
6316 r.out.idx = &idx;
6318 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6319 "GetDisplayEnumerationIndex failed");
6321 if (ok_lvl[i] &&
6322 !NT_STATUS_IS_OK(r.out.result) &&
6323 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6324 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6325 levels[i], nt_errstr(r.out.result));
6326 ret = false;
6329 init_lsa_String(&name, "zzzzzzzz");
6331 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6332 "GetDisplayEnumerationIndex failed");
6334 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6335 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6336 levels[i], nt_errstr(r.out.result));
6337 ret = false;
6341 return ret;
6344 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6345 struct torture_context *tctx,
6346 struct policy_handle *handle)
6348 struct samr_GetDisplayEnumerationIndex2 r;
6349 bool ret = true;
6350 uint16_t levels[] = {1, 2, 3, 4, 5};
6351 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6352 struct lsa_String name;
6353 uint32_t idx = 0;
6354 int i;
6356 for (i=0;i<ARRAY_SIZE(levels);i++) {
6357 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6359 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6361 r.in.domain_handle = handle;
6362 r.in.level = levels[i];
6363 r.in.name = &name;
6364 r.out.idx = &idx;
6366 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6367 "GetDisplayEnumerationIndex2 failed");
6368 if (ok_lvl[i] &&
6369 !NT_STATUS_IS_OK(r.out.result) &&
6370 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6371 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6372 levels[i], nt_errstr(r.out.result));
6373 ret = false;
6376 init_lsa_String(&name, "zzzzzzzz");
6378 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6379 "GetDisplayEnumerationIndex2 failed");
6380 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6381 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6382 levels[i], nt_errstr(r.out.result));
6383 ret = false;
6387 return ret;
6390 #define STRING_EQUAL_QUERY(s1, s2, user) \
6391 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6392 /* odd, but valid */ \
6393 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6394 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6395 #s1, user.string, s1.string, s2.string, __location__); \
6396 ret = false; \
6398 #define INT_EQUAL_QUERY(s1, s2, user) \
6399 if (s1 != s2) { \
6400 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6401 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6402 ret = false; \
6405 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6406 struct torture_context *tctx,
6407 struct samr_QueryDisplayInfo *querydisplayinfo,
6408 bool *seen_testuser)
6410 struct samr_OpenUser r;
6411 struct samr_QueryUserInfo q;
6412 union samr_UserInfo *info;
6413 struct policy_handle user_handle;
6414 int i, ret = true;
6415 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6416 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6417 for (i = 0; ; i++) {
6418 switch (querydisplayinfo->in.level) {
6419 case 1:
6420 if (i >= querydisplayinfo->out.info->info1.count) {
6421 return ret;
6423 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6424 break;
6425 case 2:
6426 if (i >= querydisplayinfo->out.info->info2.count) {
6427 return ret;
6429 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6430 break;
6431 case 3:
6432 /* Groups */
6433 case 4:
6434 case 5:
6435 /* Not interested in validating just the account name */
6436 return true;
6439 r.out.user_handle = &user_handle;
6441 switch (querydisplayinfo->in.level) {
6442 case 1:
6443 case 2:
6444 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6445 "OpenUser failed");
6446 if (!NT_STATUS_IS_OK(r.out.result)) {
6447 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6448 return false;
6452 q.in.user_handle = &user_handle;
6453 q.in.level = 21;
6454 q.out.info = &info;
6455 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6456 "QueryUserInfo failed");
6457 if (!NT_STATUS_IS_OK(r.out.result)) {
6458 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6459 return false;
6462 switch (querydisplayinfo->in.level) {
6463 case 1:
6464 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6465 *seen_testuser = true;
6467 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6468 info->info21.full_name, info->info21.account_name);
6469 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6470 info->info21.account_name, info->info21.account_name);
6471 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6472 info->info21.description, info->info21.account_name);
6473 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6474 info->info21.rid, info->info21.account_name);
6475 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6476 info->info21.acct_flags, info->info21.account_name);
6478 break;
6479 case 2:
6480 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6481 info->info21.account_name, info->info21.account_name);
6482 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6483 info->info21.description, info->info21.account_name);
6484 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6485 info->info21.rid, info->info21.account_name);
6486 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6487 info->info21.acct_flags, info->info21.account_name);
6489 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6490 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6491 info->info21.account_name.string);
6494 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6495 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6496 info->info21.account_name.string,
6497 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6498 info->info21.acct_flags);
6499 return false;
6502 break;
6505 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6506 return false;
6509 return ret;
6512 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6513 struct torture_context *tctx,
6514 struct policy_handle *handle)
6516 struct samr_QueryDisplayInfo r;
6517 struct samr_QueryDomainInfo dom_info;
6518 union samr_DomainInfo *info = NULL;
6519 bool ret = true;
6520 uint16_t levels[] = {1, 2, 3, 4, 5};
6521 int i;
6522 bool seen_testuser = false;
6523 uint32_t total_size;
6524 uint32_t returned_size;
6525 union samr_DispInfo disp_info;
6528 for (i=0;i<ARRAY_SIZE(levels);i++) {
6529 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6531 r.in.start_idx = 0;
6532 r.out.result = STATUS_MORE_ENTRIES;
6533 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6534 r.in.domain_handle = handle;
6535 r.in.level = levels[i];
6536 r.in.max_entries = 2;
6537 r.in.buf_size = (uint32_t)-1;
6538 r.out.total_size = &total_size;
6539 r.out.returned_size = &returned_size;
6540 r.out.info = &disp_info;
6542 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6543 "QueryDisplayInfo failed");
6544 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6545 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6546 levels[i], nt_errstr(r.out.result));
6547 ret = false;
6549 switch (r.in.level) {
6550 case 1:
6551 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6552 ret = false;
6554 r.in.start_idx += r.out.info->info1.count;
6555 break;
6556 case 2:
6557 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6558 ret = false;
6560 r.in.start_idx += r.out.info->info2.count;
6561 break;
6562 case 3:
6563 r.in.start_idx += r.out.info->info3.count;
6564 break;
6565 case 4:
6566 r.in.start_idx += r.out.info->info4.count;
6567 break;
6568 case 5:
6569 r.in.start_idx += r.out.info->info5.count;
6570 break;
6573 dom_info.in.domain_handle = handle;
6574 dom_info.in.level = 2;
6575 dom_info.out.info = &info;
6577 /* Check number of users returned is correct */
6578 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6579 "QueryDomainInfo failed");
6580 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6581 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6582 r.in.level, nt_errstr(dom_info.out.result));
6583 ret = false;
6584 break;
6586 switch (r.in.level) {
6587 case 1:
6588 case 4:
6589 if (info->general.num_users < r.in.start_idx) {
6590 /* On AD deployments this numbers don't match
6591 * since QueryDisplayInfo returns universal and
6592 * global groups, QueryDomainInfo only global
6593 * ones. */
6594 if (torture_setting_bool(tctx, "samba3", false)) {
6595 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6596 r.in.start_idx, info->general.num_groups,
6597 info->general.domain_name.string);
6598 ret = false;
6601 if (!seen_testuser) {
6602 struct policy_handle user_handle;
6603 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6604 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6605 info->general.domain_name.string);
6606 ret = false;
6607 test_samr_handle_Close(b, tctx, &user_handle);
6610 break;
6611 case 3:
6612 case 5:
6613 if (info->general.num_groups != r.in.start_idx) {
6614 /* On AD deployments this numbers don't match
6615 * since QueryDisplayInfo returns universal and
6616 * global groups, QueryDomainInfo only global
6617 * ones. */
6618 if (torture_setting_bool(tctx, "samba3", false)) {
6619 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6620 r.in.start_idx, info->general.num_groups,
6621 info->general.domain_name.string);
6622 ret = false;
6626 break;
6631 return ret;
6634 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6635 struct torture_context *tctx,
6636 struct policy_handle *handle)
6638 struct samr_QueryDisplayInfo2 r;
6639 bool ret = true;
6640 uint16_t levels[] = {1, 2, 3, 4, 5};
6641 int i;
6642 uint32_t total_size;
6643 uint32_t returned_size;
6644 union samr_DispInfo info;
6646 for (i=0;i<ARRAY_SIZE(levels);i++) {
6647 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6649 r.in.domain_handle = handle;
6650 r.in.level = levels[i];
6651 r.in.start_idx = 0;
6652 r.in.max_entries = 1000;
6653 r.in.buf_size = (uint32_t)-1;
6654 r.out.total_size = &total_size;
6655 r.out.returned_size = &returned_size;
6656 r.out.info = &info;
6658 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6659 "QueryDisplayInfo2 failed");
6660 if (!NT_STATUS_IS_OK(r.out.result)) {
6661 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6662 levels[i], nt_errstr(r.out.result));
6663 ret = false;
6667 return ret;
6670 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6671 struct torture_context *tctx,
6672 struct policy_handle *handle)
6674 struct samr_QueryDisplayInfo3 r;
6675 bool ret = true;
6676 uint16_t levels[] = {1, 2, 3, 4, 5};
6677 int i;
6678 uint32_t total_size;
6679 uint32_t returned_size;
6680 union samr_DispInfo info;
6682 for (i=0;i<ARRAY_SIZE(levels);i++) {
6683 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6685 r.in.domain_handle = handle;
6686 r.in.level = levels[i];
6687 r.in.start_idx = 0;
6688 r.in.max_entries = 1000;
6689 r.in.buf_size = (uint32_t)-1;
6690 r.out.total_size = &total_size;
6691 r.out.returned_size = &returned_size;
6692 r.out.info = &info;
6694 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6695 "QueryDisplayInfo3 failed");
6696 if (!NT_STATUS_IS_OK(r.out.result)) {
6697 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6698 levels[i], nt_errstr(r.out.result));
6699 ret = false;
6703 return ret;
6707 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6708 struct torture_context *tctx,
6709 struct policy_handle *handle)
6711 struct samr_QueryDisplayInfo r;
6712 bool ret = true;
6713 uint32_t total_size;
6714 uint32_t returned_size;
6715 union samr_DispInfo info;
6717 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6719 r.in.domain_handle = handle;
6720 r.in.level = 1;
6721 r.in.start_idx = 0;
6722 r.in.max_entries = 1;
6723 r.in.buf_size = (uint32_t)-1;
6724 r.out.total_size = &total_size;
6725 r.out.returned_size = &returned_size;
6726 r.out.info = &info;
6728 do {
6729 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6730 "QueryDisplayInfo failed");
6731 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6732 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6733 torture_warning(tctx, "expected idx %d but got %d\n",
6734 r.in.start_idx + 1,
6735 r.out.info->info1.entries[0].idx);
6736 break;
6739 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6740 !NT_STATUS_IS_OK(r.out.result)) {
6741 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6742 r.in.level, nt_errstr(r.out.result));
6743 ret = false;
6744 break;
6746 r.in.start_idx++;
6747 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6748 NT_STATUS_IS_OK(r.out.result)) &&
6749 *r.out.returned_size != 0);
6751 return ret;
6754 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6755 struct torture_context *tctx,
6756 struct policy_handle *handle)
6758 struct samr_QueryDomainInfo r;
6759 union samr_DomainInfo *info = NULL;
6760 struct samr_SetDomainInfo s;
6761 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6762 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6763 int i;
6764 bool ret = true;
6765 struct dcerpc_binding_handle *b = p->binding_handle;
6766 const char *domain_comment = talloc_asprintf(tctx,
6767 "Tortured by Samba4 RPC-SAMR: %s",
6768 timestring(tctx, time(NULL)));
6770 s.in.domain_handle = handle;
6771 s.in.level = 4;
6772 s.in.info = talloc(tctx, union samr_DomainInfo);
6774 s.in.info->oem.oem_information.string = domain_comment;
6775 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6776 "SetDomainInfo failed");
6777 if (!NT_STATUS_IS_OK(s.out.result)) {
6778 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6779 s.in.level, nt_errstr(s.out.result));
6780 return false;
6783 for (i=0;i<ARRAY_SIZE(levels);i++) {
6784 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6786 r.in.domain_handle = handle;
6787 r.in.level = levels[i];
6788 r.out.info = &info;
6790 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6791 "QueryDomainInfo failed");
6792 if (!NT_STATUS_IS_OK(r.out.result)) {
6793 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6794 r.in.level, nt_errstr(r.out.result));
6795 ret = false;
6796 continue;
6799 switch (levels[i]) {
6800 case 2:
6801 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6802 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6803 levels[i], info->general.oem_information.string, domain_comment);
6804 if (!torture_setting_bool(tctx, "samba3", false)) {
6805 ret = false;
6808 if (!info->general.primary.string) {
6809 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6810 levels[i]);
6811 ret = false;
6812 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6813 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6814 if (torture_setting_bool(tctx, "samba3", false)) {
6815 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6816 levels[i], info->general.primary.string, dcerpc_server_name(p));
6820 break;
6821 case 4:
6822 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6823 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6824 levels[i], info->oem.oem_information.string, domain_comment);
6825 if (!torture_setting_bool(tctx, "samba3", false)) {
6826 ret = false;
6829 break;
6830 case 6:
6831 if (!info->info6.primary.string) {
6832 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6833 levels[i]);
6834 ret = false;
6836 break;
6837 case 11:
6838 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6839 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6840 levels[i], info->general2.general.oem_information.string, domain_comment);
6841 if (!torture_setting_bool(tctx, "samba3", false)) {
6842 ret = false;
6845 break;
6848 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6850 s.in.domain_handle = handle;
6851 s.in.level = levels[i];
6852 s.in.info = info;
6854 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6855 "SetDomainInfo failed");
6856 if (set_ok[i]) {
6857 if (!NT_STATUS_IS_OK(s.out.result)) {
6858 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6859 r.in.level, nt_errstr(s.out.result));
6860 ret = false;
6861 continue;
6863 } else {
6864 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6865 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6866 r.in.level, nt_errstr(s.out.result));
6867 ret = false;
6868 continue;
6872 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6873 "QueryDomainInfo failed");
6874 if (!NT_STATUS_IS_OK(r.out.result)) {
6875 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6876 r.in.level, nt_errstr(r.out.result));
6877 ret = false;
6878 continue;
6882 return ret;
6886 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6887 struct torture_context *tctx,
6888 struct policy_handle *handle)
6890 struct samr_QueryDomainInfo2 r;
6891 union samr_DomainInfo *info = NULL;
6892 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6893 int i;
6894 bool ret = true;
6896 for (i=0;i<ARRAY_SIZE(levels);i++) {
6897 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6899 r.in.domain_handle = handle;
6900 r.in.level = levels[i];
6901 r.out.info = &info;
6903 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6904 "QueryDomainInfo2 failed");
6905 if (!NT_STATUS_IS_OK(r.out.result)) {
6906 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6907 r.in.level, nt_errstr(r.out.result));
6908 ret = false;
6909 continue;
6913 return true;
6916 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6917 set of group names. */
6918 static bool test_GroupList(struct dcerpc_binding_handle *b,
6919 struct torture_context *tctx,
6920 struct dom_sid *domain_sid,
6921 struct policy_handle *handle)
6923 struct samr_EnumDomainGroups q1;
6924 struct samr_QueryDisplayInfo q2;
6925 NTSTATUS status;
6926 uint32_t resume_handle=0;
6927 struct samr_SamArray *sam = NULL;
6928 uint32_t num_entries = 0;
6929 int i;
6930 bool ret = true;
6931 uint32_t total_size;
6932 uint32_t returned_size;
6933 union samr_DispInfo info;
6935 int num_names = 0;
6936 const char **names = NULL;
6938 bool builtin_domain = dom_sid_compare(domain_sid,
6939 &global_sid_Builtin) == 0;
6941 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6943 q1.in.domain_handle = handle;
6944 q1.in.resume_handle = &resume_handle;
6945 q1.in.max_size = 5;
6946 q1.out.resume_handle = &resume_handle;
6947 q1.out.num_entries = &num_entries;
6948 q1.out.sam = &sam;
6950 status = STATUS_MORE_ENTRIES;
6951 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6952 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6953 "EnumDomainGroups failed");
6954 status = q1.out.result;
6956 if (!NT_STATUS_IS_OK(status) &&
6957 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6958 break;
6960 for (i=0; i<*q1.out.num_entries; i++) {
6961 add_string_to_array(tctx,
6962 sam->entries[i].name.string,
6963 &names, &num_names);
6967 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6969 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6971 if (builtin_domain) {
6972 torture_assert(tctx, num_names == 0,
6973 "EnumDomainGroups shouldn't return any group in the builtin domain!");
6976 q2.in.domain_handle = handle;
6977 q2.in.level = 5;
6978 q2.in.start_idx = 0;
6979 q2.in.max_entries = 5;
6980 q2.in.buf_size = (uint32_t)-1;
6981 q2.out.total_size = &total_size;
6982 q2.out.returned_size = &returned_size;
6983 q2.out.info = &info;
6985 status = STATUS_MORE_ENTRIES;
6986 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6987 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
6988 "QueryDisplayInfo failed");
6989 status = q2.out.result;
6990 if (!NT_STATUS_IS_OK(status) &&
6991 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6992 break;
6994 for (i=0; i<q2.out.info->info5.count; i++) {
6995 int j;
6996 const char *name = q2.out.info->info5.entries[i].account_name.string;
6997 bool found = false;
6998 for (j=0; j<num_names; j++) {
6999 if (names[j] == NULL)
7000 continue;
7001 if (strequal(names[j], name)) {
7002 names[j] = NULL;
7003 found = true;
7004 break;
7008 if ((!found) && (!builtin_domain)) {
7009 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7010 name);
7011 ret = false;
7014 q2.in.start_idx += q2.out.info->info5.count;
7017 if (!NT_STATUS_IS_OK(status)) {
7018 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
7019 nt_errstr(status));
7020 ret = false;
7023 if (builtin_domain) {
7024 torture_assert(tctx, q2.in.start_idx != 0,
7025 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
7028 for (i=0; i<num_names; i++) {
7029 if (names[i] != NULL) {
7030 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
7031 names[i]);
7032 ret = false;
7036 return ret;
7039 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
7040 struct torture_context *tctx,
7041 struct policy_handle *group_handle)
7043 struct samr_DeleteDomainGroup d;
7045 torture_comment(tctx, "Testing DeleteDomainGroup\n");
7047 d.in.group_handle = group_handle;
7048 d.out.group_handle = group_handle;
7050 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
7051 "DeleteDomainGroup failed");
7052 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
7054 return true;
7057 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
7058 struct torture_context *tctx,
7059 struct policy_handle *domain_handle)
7061 struct samr_TestPrivateFunctionsDomain r;
7062 bool ret = true;
7064 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
7066 r.in.domain_handle = domain_handle;
7068 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
7069 "TestPrivateFunctionsDomain failed");
7070 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
7072 return ret;
7075 static bool test_RidToSid(struct dcerpc_binding_handle *b,
7076 struct torture_context *tctx,
7077 struct dom_sid *domain_sid,
7078 struct policy_handle *domain_handle)
7080 struct samr_RidToSid r;
7081 bool ret = true;
7082 struct dom_sid *calc_sid, *out_sid;
7083 int rids[] = { 0, 42, 512, 10200 };
7084 int i;
7086 for (i=0;i<ARRAY_SIZE(rids);i++) {
7087 torture_comment(tctx, "Testing RidToSid\n");
7089 calc_sid = dom_sid_dup(tctx, domain_sid);
7090 r.in.domain_handle = domain_handle;
7091 r.in.rid = rids[i];
7092 r.out.sid = &out_sid;
7094 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
7095 "RidToSid failed");
7096 if (!NT_STATUS_IS_OK(r.out.result)) {
7097 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
7098 ret = false;
7099 } else {
7100 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
7102 if (!dom_sid_equal(calc_sid, out_sid)) {
7103 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
7104 dom_sid_string(tctx, out_sid),
7105 dom_sid_string(tctx, calc_sid));
7106 ret = false;
7111 return ret;
7114 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7115 struct torture_context *tctx,
7116 struct policy_handle *domain_handle)
7118 struct samr_GetBootKeyInformation r;
7119 bool ret = true;
7120 uint32_t unknown = 0;
7121 NTSTATUS status;
7123 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7125 r.in.domain_handle = domain_handle;
7126 r.out.unknown = &unknown;
7128 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7129 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7130 status = r.out.result;
7132 if (!NT_STATUS_IS_OK(status)) {
7133 /* w2k3 seems to fail this sometimes and pass it sometimes */
7134 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7137 return ret;
7140 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7141 struct torture_context *tctx,
7142 struct policy_handle *domain_handle,
7143 struct policy_handle *group_handle)
7145 NTSTATUS status;
7146 struct samr_AddGroupMember r;
7147 struct samr_DeleteGroupMember d;
7148 struct samr_QueryGroupMember q;
7149 struct samr_RidAttrArray *rids = NULL;
7150 struct samr_SetMemberAttributesOfGroup s;
7151 uint32_t rid;
7152 bool found_member = false;
7153 int i;
7155 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7156 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7158 r.in.group_handle = group_handle;
7159 r.in.rid = rid;
7160 r.in.flags = 0; /* ??? */
7162 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7164 d.in.group_handle = group_handle;
7165 d.in.rid = rid;
7167 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7168 "DeleteGroupMember failed");
7169 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7171 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7172 "AddGroupMember failed");
7173 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7175 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7176 "AddGroupMember failed");
7177 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7179 if (torture_setting_bool(tctx, "samba4", false) ||
7180 torture_setting_bool(tctx, "samba3", false)) {
7181 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7182 } else {
7183 /* this one is quite strange. I am using random inputs in the
7184 hope of triggering an error that might give us a clue */
7186 s.in.group_handle = group_handle;
7187 s.in.unknown1 = random();
7188 s.in.unknown2 = random();
7190 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7191 "SetMemberAttributesOfGroup failed");
7192 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7195 q.in.group_handle = group_handle;
7196 q.out.rids = &rids;
7198 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7199 "QueryGroupMember failed");
7200 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7201 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7203 for (i=0; i < rids->count; i++) {
7204 if (rids->rids[i] == rid) {
7205 found_member = true;
7209 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7211 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7212 "DeleteGroupMember failed");
7213 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7215 rids = NULL;
7216 found_member = false;
7218 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7219 "QueryGroupMember failed");
7220 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7221 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7223 for (i=0; i < rids->count; i++) {
7224 if (rids->rids[i] == rid) {
7225 found_member = true;
7229 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7231 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7232 "AddGroupMember failed");
7233 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7235 return true;
7239 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7240 struct torture_context *tctx,
7241 struct policy_handle *domain_handle,
7242 const char *group_name,
7243 struct policy_handle *group_handle,
7244 struct dom_sid *domain_sid,
7245 bool test_group)
7247 struct samr_CreateDomainGroup r;
7248 uint32_t rid;
7249 struct lsa_String name;
7250 bool ret = true;
7252 init_lsa_String(&name, group_name);
7254 r.in.domain_handle = domain_handle;
7255 r.in.name = &name;
7256 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7257 r.out.group_handle = group_handle;
7258 r.out.rid = &rid;
7260 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7262 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7263 "CreateDomainGroup failed");
7265 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7266 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7267 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7268 return true;
7269 } else {
7270 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7271 nt_errstr(r.out.result));
7272 return false;
7276 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7277 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7278 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7279 nt_errstr(r.out.result));
7280 return false;
7282 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7283 "CreateDomainGroup failed");
7285 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7286 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7288 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7289 nt_errstr(r.out.result));
7290 return false;
7292 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7293 "CreateDomainGroup failed");
7295 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7297 if (!test_group) {
7298 return ret;
7301 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7302 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7303 ret = false;
7306 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7307 ret = false;
7310 return ret;
7315 its not totally clear what this does. It seems to accept any sid you like.
7317 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7318 struct torture_context *tctx,
7319 struct policy_handle *domain_handle)
7321 struct samr_RemoveMemberFromForeignDomain r;
7323 r.in.domain_handle = domain_handle;
7324 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7326 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7327 "RemoveMemberFromForeignDomain failed");
7328 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7330 return true;
7333 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7334 struct torture_context *tctx,
7335 struct policy_handle *domain_handle,
7336 uint32_t *total_num_entries_p)
7338 NTSTATUS status;
7339 struct samr_EnumDomainUsers r;
7340 uint32_t resume_handle = 0;
7341 uint32_t num_entries = 0;
7342 uint32_t total_num_entries = 0;
7343 struct samr_SamArray *sam;
7345 r.in.domain_handle = domain_handle;
7346 r.in.acct_flags = 0;
7347 r.in.max_size = (uint32_t)-1;
7348 r.in.resume_handle = &resume_handle;
7350 r.out.sam = &sam;
7351 r.out.num_entries = &num_entries;
7352 r.out.resume_handle = &resume_handle;
7354 torture_comment(tctx, "Testing EnumDomainUsers\n");
7356 do {
7357 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7358 "EnumDomainUsers failed");
7359 if (NT_STATUS_IS_ERR(r.out.result)) {
7360 torture_assert_ntstatus_ok(tctx, r.out.result,
7361 "failed to enumerate users");
7363 status = r.out.result;
7365 total_num_entries += num_entries;
7366 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7368 if (total_num_entries_p) {
7369 *total_num_entries_p = total_num_entries;
7372 return true;
7375 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7376 struct torture_context *tctx,
7377 struct policy_handle *domain_handle,
7378 uint32_t *total_num_entries_p)
7380 NTSTATUS status;
7381 struct samr_EnumDomainGroups r;
7382 uint32_t resume_handle = 0;
7383 uint32_t num_entries = 0;
7384 uint32_t total_num_entries = 0;
7385 struct samr_SamArray *sam;
7387 r.in.domain_handle = domain_handle;
7388 r.in.max_size = (uint32_t)-1;
7389 r.in.resume_handle = &resume_handle;
7391 r.out.sam = &sam;
7392 r.out.num_entries = &num_entries;
7393 r.out.resume_handle = &resume_handle;
7395 torture_comment(tctx, "Testing EnumDomainGroups\n");
7397 do {
7398 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7399 "EnumDomainGroups failed");
7400 if (NT_STATUS_IS_ERR(r.out.result)) {
7401 torture_assert_ntstatus_ok(tctx, r.out.result,
7402 "failed to enumerate groups");
7404 status = r.out.result;
7406 total_num_entries += num_entries;
7407 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7409 if (total_num_entries_p) {
7410 *total_num_entries_p = total_num_entries;
7413 return true;
7416 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7417 struct torture_context *tctx,
7418 struct policy_handle *domain_handle,
7419 uint32_t *total_num_entries_p)
7421 NTSTATUS status;
7422 struct samr_EnumDomainAliases r;
7423 uint32_t resume_handle = 0;
7424 uint32_t num_entries = 0;
7425 uint32_t total_num_entries = 0;
7426 struct samr_SamArray *sam;
7428 r.in.domain_handle = domain_handle;
7429 r.in.max_size = (uint32_t)-1;
7430 r.in.resume_handle = &resume_handle;
7432 r.out.sam = &sam;
7433 r.out.num_entries = &num_entries;
7434 r.out.resume_handle = &resume_handle;
7436 torture_comment(tctx, "Testing EnumDomainAliases\n");
7438 do {
7439 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7440 "EnumDomainAliases failed");
7441 if (NT_STATUS_IS_ERR(r.out.result)) {
7442 torture_assert_ntstatus_ok(tctx, r.out.result,
7443 "failed to enumerate aliases");
7445 status = r.out.result;
7447 total_num_entries += num_entries;
7448 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7450 if (total_num_entries_p) {
7451 *total_num_entries_p = total_num_entries;
7454 return true;
7457 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7458 struct torture_context *tctx,
7459 struct policy_handle *handle,
7460 uint16_t level,
7461 uint32_t *total_num_entries_p)
7463 NTSTATUS status;
7464 struct samr_QueryDisplayInfo r;
7465 uint32_t total_num_entries = 0;
7467 r.in.domain_handle = handle;
7468 r.in.level = level;
7469 r.in.start_idx = 0;
7470 r.in.max_entries = (uint32_t)-1;
7471 r.in.buf_size = (uint32_t)-1;
7473 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7475 do {
7476 uint32_t total_size;
7477 uint32_t returned_size;
7478 union samr_DispInfo info;
7480 r.out.total_size = &total_size;
7481 r.out.returned_size = &returned_size;
7482 r.out.info = &info;
7484 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7485 "failed to query displayinfo");
7486 if (NT_STATUS_IS_ERR(r.out.result)) {
7487 torture_assert_ntstatus_ok(tctx, r.out.result,
7488 "failed to query displayinfo");
7490 status = r.out.result;
7492 if (*r.out.returned_size == 0) {
7493 break;
7496 switch (r.in.level) {
7497 case 1:
7498 total_num_entries += info.info1.count;
7499 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7500 break;
7501 case 2:
7502 total_num_entries += info.info2.count;
7503 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7504 break;
7505 case 3:
7506 total_num_entries += info.info3.count;
7507 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7508 break;
7509 case 4:
7510 total_num_entries += info.info4.count;
7511 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7512 break;
7513 case 5:
7514 total_num_entries += info.info5.count;
7515 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7516 break;
7517 default:
7518 return false;
7521 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7523 if (total_num_entries_p) {
7524 *total_num_entries_p = total_num_entries;
7527 return true;
7530 static bool test_ManyObjects(struct dcerpc_pipe *p,
7531 struct torture_context *tctx,
7532 struct policy_handle *domain_handle,
7533 struct dom_sid *domain_sid,
7534 struct torture_samr_context *ctx)
7536 uint32_t num_total = ctx->num_objects_large_dc;
7537 uint32_t num_enum = 0;
7538 uint32_t num_disp = 0;
7539 uint32_t num_created = 0;
7540 uint32_t num_anounced = 0;
7541 uint32_t i;
7542 struct dcerpc_binding_handle *b = p->binding_handle;
7544 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7546 /* query */
7549 struct samr_QueryDomainInfo2 r;
7550 union samr_DomainInfo *info;
7551 r.in.domain_handle = domain_handle;
7552 r.in.level = 2;
7553 r.out.info = &info;
7555 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7556 "QueryDomainInfo2 failed");
7557 torture_assert_ntstatus_ok(tctx, r.out.result,
7558 "failed to query domain info");
7560 switch (ctx->choice) {
7561 case TORTURE_SAMR_MANY_ACCOUNTS:
7562 num_anounced = info->general.num_users;
7563 break;
7564 case TORTURE_SAMR_MANY_GROUPS:
7565 num_anounced = info->general.num_groups;
7566 break;
7567 case TORTURE_SAMR_MANY_ALIASES:
7568 num_anounced = info->general.num_aliases;
7569 break;
7570 default:
7571 return false;
7575 /* create */
7577 for (i=0; i < num_total; i++) {
7579 const char *name = NULL;
7581 switch (ctx->choice) {
7582 case TORTURE_SAMR_MANY_ACCOUNTS:
7583 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7584 torture_assert(tctx,
7585 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7586 "failed to create user");
7587 break;
7588 case TORTURE_SAMR_MANY_GROUPS:
7589 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7590 torture_assert(tctx,
7591 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7592 "failed to create group");
7593 break;
7594 case TORTURE_SAMR_MANY_ALIASES:
7595 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7596 torture_assert(tctx,
7597 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7598 "failed to create alias");
7599 break;
7600 default:
7601 return false;
7603 if (!ndr_policy_handle_empty(&handles[i])) {
7604 num_created++;
7608 /* enum */
7610 switch (ctx->choice) {
7611 case TORTURE_SAMR_MANY_ACCOUNTS:
7612 torture_assert(tctx,
7613 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7614 "failed to enum users");
7615 break;
7616 case TORTURE_SAMR_MANY_GROUPS:
7617 torture_assert(tctx,
7618 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7619 "failed to enum groups");
7620 break;
7621 case TORTURE_SAMR_MANY_ALIASES:
7622 torture_assert(tctx,
7623 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7624 "failed to enum aliases");
7625 break;
7626 default:
7627 return false;
7630 /* dispinfo */
7632 switch (ctx->choice) {
7633 case TORTURE_SAMR_MANY_ACCOUNTS:
7634 torture_assert(tctx,
7635 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
7636 "failed to query display info");
7637 break;
7638 case TORTURE_SAMR_MANY_GROUPS:
7639 torture_assert(tctx,
7640 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
7641 "failed to query display info");
7642 break;
7643 case TORTURE_SAMR_MANY_ALIASES:
7644 /* no aliases in dispinfo */
7645 break;
7646 default:
7647 return false;
7650 /* close or delete */
7652 for (i=0; i < num_total; i++) {
7654 if (ndr_policy_handle_empty(&handles[i])) {
7655 continue;
7658 if (torture_setting_bool(tctx, "samba3", false)) {
7659 torture_assert(tctx,
7660 test_samr_handle_Close(b, tctx, &handles[i]),
7661 "failed to close handle");
7662 } else {
7663 switch (ctx->choice) {
7664 case TORTURE_SAMR_MANY_ACCOUNTS:
7665 torture_assert(tctx,
7666 test_DeleteUser(b, tctx, &handles[i]),
7667 "failed to delete user");
7668 break;
7669 case TORTURE_SAMR_MANY_GROUPS:
7670 torture_assert(tctx,
7671 test_DeleteDomainGroup(b, tctx, &handles[i]),
7672 "failed to delete group");
7673 break;
7674 case TORTURE_SAMR_MANY_ALIASES:
7675 torture_assert(tctx,
7676 test_DeleteAlias(b, tctx, &handles[i]),
7677 "failed to delete alias");
7678 break;
7679 default:
7680 return false;
7685 talloc_free(handles);
7687 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7688 torture_comment(tctx,
7689 "unexpected number of results (%u) returned in enum call, expected %u\n",
7690 num_enum, num_anounced + num_created);
7692 torture_comment(tctx,
7693 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7694 num_disp, num_anounced + num_created);
7697 return true;
7700 static bool test_Connect(struct dcerpc_binding_handle *b,
7701 struct torture_context *tctx,
7702 struct policy_handle *handle);
7704 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7705 struct torture_samr_context *ctx, struct dom_sid *sid)
7707 struct samr_OpenDomain r;
7708 struct policy_handle domain_handle;
7709 struct policy_handle alias_handle;
7710 struct policy_handle user_handle;
7711 struct policy_handle group_handle;
7712 bool ret = true;
7713 struct dcerpc_binding_handle *b = p->binding_handle;
7715 ZERO_STRUCT(alias_handle);
7716 ZERO_STRUCT(user_handle);
7717 ZERO_STRUCT(group_handle);
7718 ZERO_STRUCT(domain_handle);
7720 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7722 r.in.connect_handle = &ctx->handle;
7723 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7724 r.in.sid = sid;
7725 r.out.domain_handle = &domain_handle;
7727 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7728 "OpenDomain failed");
7729 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7731 /* run the domain tests with the main handle closed - this tests
7732 the servers reference counting */
7733 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7735 switch (ctx->choice) {
7736 case TORTURE_SAMR_PASSWORDS:
7737 case TORTURE_SAMR_USER_PRIVILEGES:
7738 if (!torture_setting_bool(tctx, "samba3", false)) {
7739 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7741 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7742 if (!ret) {
7743 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7745 break;
7746 case TORTURE_SAMR_USER_ATTRIBUTES:
7747 if (!torture_setting_bool(tctx, "samba3", false)) {
7748 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7750 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7751 /* This test needs 'complex' users to validate */
7752 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7753 if (!ret) {
7754 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7756 break;
7757 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7758 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7759 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7760 if (!torture_setting_bool(tctx, "samba3", false)) {
7761 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7763 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7764 if (!ret) {
7765 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7767 break;
7768 case TORTURE_SAMR_MANY_ACCOUNTS:
7769 case TORTURE_SAMR_MANY_GROUPS:
7770 case TORTURE_SAMR_MANY_ALIASES:
7771 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7772 if (!ret) {
7773 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7775 break;
7776 case TORTURE_SAMR_OTHER:
7777 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7778 if (!ret) {
7779 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7781 if (!torture_setting_bool(tctx, "samba3", false)) {
7782 ret &= test_QuerySecurity(b, tctx, &domain_handle);
7784 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7785 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7786 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7787 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7788 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7789 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7790 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7791 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7792 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7793 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7794 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7795 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7796 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7798 if (torture_setting_bool(tctx, "samba4", false)) {
7799 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7800 } else {
7801 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7802 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7804 ret &= test_GroupList(b, tctx, sid, &domain_handle);
7805 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7806 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7807 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7808 if (!ret) {
7809 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7811 break;
7814 if (!ndr_policy_handle_empty(&user_handle) &&
7815 !test_DeleteUser(b, tctx, &user_handle)) {
7816 ret = false;
7819 if (!ndr_policy_handle_empty(&alias_handle) &&
7820 !test_DeleteAlias(b, tctx, &alias_handle)) {
7821 ret = false;
7824 if (!ndr_policy_handle_empty(&group_handle) &&
7825 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7826 ret = false;
7829 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7831 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7832 /* reconnect the main handle */
7834 if (!ret) {
7835 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7838 return ret;
7841 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7842 struct torture_samr_context *ctx, const char *domain)
7844 struct samr_LookupDomain r;
7845 struct dom_sid2 *sid = NULL;
7846 struct lsa_String n1;
7847 struct lsa_String n2;
7848 bool ret = true;
7849 struct dcerpc_binding_handle *b = p->binding_handle;
7851 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7853 /* check for correct error codes */
7854 r.in.connect_handle = &ctx->handle;
7855 r.in.domain_name = &n2;
7856 r.out.sid = &sid;
7857 n2.string = NULL;
7859 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7860 "LookupDomain failed");
7861 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7863 init_lsa_String(&n2, "xxNODOMAINxx");
7865 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7866 "LookupDomain failed");
7867 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7869 r.in.connect_handle = &ctx->handle;
7871 init_lsa_String(&n1, domain);
7872 r.in.domain_name = &n1;
7874 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7875 "LookupDomain failed");
7876 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7878 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7879 ret = false;
7882 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7883 ret = false;
7886 return ret;
7890 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7891 struct torture_samr_context *ctx)
7893 struct samr_EnumDomains r;
7894 uint32_t resume_handle = 0;
7895 uint32_t num_entries = 0;
7896 struct samr_SamArray *sam = NULL;
7897 int i;
7898 bool ret = true;
7899 struct dcerpc_binding_handle *b = p->binding_handle;
7901 r.in.connect_handle = &ctx->handle;
7902 r.in.resume_handle = &resume_handle;
7903 r.in.buf_size = (uint32_t)-1;
7904 r.out.resume_handle = &resume_handle;
7905 r.out.num_entries = &num_entries;
7906 r.out.sam = &sam;
7908 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7909 "EnumDomains failed");
7910 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7912 if (!*r.out.sam) {
7913 return false;
7916 for (i=0;i<sam->count;i++) {
7917 if (!test_LookupDomain(p, tctx, ctx,
7918 sam->entries[i].name.string)) {
7919 ret = false;
7923 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7924 "EnumDomains failed");
7925 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7927 return ret;
7931 static bool test_Connect(struct dcerpc_binding_handle *b,
7932 struct torture_context *tctx,
7933 struct policy_handle *handle)
7935 struct samr_Connect r;
7936 struct samr_Connect2 r2;
7937 struct samr_Connect3 r3;
7938 struct samr_Connect4 r4;
7939 struct samr_Connect5 r5;
7940 union samr_ConnectInfo info;
7941 struct policy_handle h;
7942 uint32_t level_out = 0;
7943 bool ret = true, got_handle = false;
7945 torture_comment(tctx, "Testing samr_Connect\n");
7947 r.in.system_name = NULL;
7948 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7949 r.out.connect_handle = &h;
7951 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7952 "Connect failed");
7953 if (!NT_STATUS_IS_OK(r.out.result)) {
7954 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7955 ret = false;
7956 } else {
7957 got_handle = true;
7958 *handle = h;
7961 torture_comment(tctx, "Testing samr_Connect2\n");
7963 r2.in.system_name = NULL;
7964 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7965 r2.out.connect_handle = &h;
7967 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7968 "Connect2 failed");
7969 if (!NT_STATUS_IS_OK(r2.out.result)) {
7970 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7971 ret = false;
7972 } else {
7973 if (got_handle) {
7974 test_samr_handle_Close(b, tctx, handle);
7976 got_handle = true;
7977 *handle = h;
7980 torture_comment(tctx, "Testing samr_Connect3\n");
7982 r3.in.system_name = NULL;
7983 r3.in.unknown = 0;
7984 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7985 r3.out.connect_handle = &h;
7987 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
7988 "Connect3 failed");
7989 if (!NT_STATUS_IS_OK(r3.out.result)) {
7990 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
7991 ret = false;
7992 } else {
7993 if (got_handle) {
7994 test_samr_handle_Close(b, tctx, handle);
7996 got_handle = true;
7997 *handle = h;
8000 torture_comment(tctx, "Testing samr_Connect4\n");
8002 r4.in.system_name = "";
8003 r4.in.client_version = 0;
8004 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8005 r4.out.connect_handle = &h;
8007 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8008 "Connect4 failed");
8009 if (!NT_STATUS_IS_OK(r4.out.result)) {
8010 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8011 ret = false;
8012 } else {
8013 if (got_handle) {
8014 test_samr_handle_Close(b, tctx, handle);
8016 got_handle = true;
8017 *handle = h;
8020 torture_comment(tctx, "Testing samr_Connect5\n");
8022 info.info1.client_version = 0;
8023 info.info1.unknown2 = 0;
8025 r5.in.system_name = "";
8026 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8027 r5.in.level_in = 1;
8028 r5.out.level_out = &level_out;
8029 r5.in.info_in = &info;
8030 r5.out.info_out = &info;
8031 r5.out.connect_handle = &h;
8033 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
8034 "Connect5 failed");
8035 if (!NT_STATUS_IS_OK(r5.out.result)) {
8036 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
8037 ret = false;
8038 } else {
8039 if (got_handle) {
8040 test_samr_handle_Close(b, tctx, handle);
8042 got_handle = true;
8043 *handle = h;
8046 return ret;
8050 static bool test_samr_ValidatePassword(struct torture_context *tctx,
8051 struct dcerpc_pipe *p)
8053 struct samr_ValidatePassword r;
8054 union samr_ValidatePasswordReq req;
8055 union samr_ValidatePasswordRep *repp = NULL;
8056 NTSTATUS status;
8057 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
8058 int i;
8059 struct dcerpc_binding_handle *b = p->binding_handle;
8061 torture_comment(tctx, "Testing samr_ValidatePassword\n");
8063 if (p->conn->transport.transport != NCACN_IP_TCP) {
8064 torture_comment(tctx, "samr_ValidatePassword only should succeed over NCACN_IP_TCP!\n");
8067 ZERO_STRUCT(r);
8068 r.in.level = NetValidatePasswordReset;
8069 r.in.req = &req;
8070 r.out.rep = &repp;
8072 ZERO_STRUCT(req);
8073 req.req3.account.string = "non-existent-account-aklsdji";
8075 for (i=0; passwords[i]; i++) {
8076 req.req3.password.string = passwords[i];
8078 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
8079 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
8080 torture_skip(tctx, "ValidatePassword not supported by server\n");
8082 torture_assert_ntstatus_ok(tctx, status,
8083 "samr_ValidatePassword failed");
8084 torture_assert_ntstatus_ok(tctx, r.out.result,
8085 "samr_ValidatePassword failed");
8086 torture_comment(tctx, "Server %s password '%s' with code %i\n",
8087 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
8088 req.req3.password.string, repp->ctr3.status);
8091 return true;
8094 bool torture_rpc_samr(struct torture_context *torture)
8096 NTSTATUS status;
8097 struct dcerpc_pipe *p;
8098 bool ret = true;
8099 struct torture_samr_context *ctx;
8100 struct dcerpc_binding_handle *b;
8102 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8103 if (!NT_STATUS_IS_OK(status)) {
8104 return false;
8106 b = p->binding_handle;
8108 ctx = talloc_zero(torture, struct torture_samr_context);
8110 ctx->choice = TORTURE_SAMR_OTHER;
8112 ret &= test_Connect(b, torture, &ctx->handle);
8114 if (!torture_setting_bool(torture, "samba3", false)) {
8115 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8118 ret &= test_EnumDomains(p, torture, ctx);
8120 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8122 ret &= test_Shutdown(b, torture, &ctx->handle);
8124 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8126 return ret;
8130 bool torture_rpc_samr_users(struct torture_context *torture)
8132 NTSTATUS status;
8133 struct dcerpc_pipe *p;
8134 bool ret = true;
8135 struct torture_samr_context *ctx;
8136 struct dcerpc_binding_handle *b;
8138 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8139 if (!NT_STATUS_IS_OK(status)) {
8140 return false;
8142 b = p->binding_handle;
8144 ctx = talloc_zero(torture, struct torture_samr_context);
8146 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8148 ret &= test_Connect(b, torture, &ctx->handle);
8150 if (!torture_setting_bool(torture, "samba3", false)) {
8151 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8154 ret &= test_EnumDomains(p, torture, ctx);
8156 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8158 ret &= test_Shutdown(b, torture, &ctx->handle);
8160 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8162 return ret;
8166 bool torture_rpc_samr_passwords(struct torture_context *torture)
8168 NTSTATUS status;
8169 struct dcerpc_pipe *p;
8170 bool ret = true;
8171 struct torture_samr_context *ctx;
8172 struct dcerpc_binding_handle *b;
8174 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8175 if (!NT_STATUS_IS_OK(status)) {
8176 return false;
8178 b = p->binding_handle;
8180 ctx = talloc_zero(torture, struct torture_samr_context);
8182 ctx->choice = TORTURE_SAMR_PASSWORDS;
8184 ret &= test_Connect(b, torture, &ctx->handle);
8186 ret &= test_EnumDomains(p, torture, ctx);
8188 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8190 return ret;
8193 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8194 struct dcerpc_pipe *p2,
8195 struct cli_credentials *machine_credentials)
8197 NTSTATUS status;
8198 struct dcerpc_pipe *p;
8199 bool ret = true;
8200 struct torture_samr_context *ctx;
8201 struct dcerpc_binding_handle *b;
8203 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8204 if (!NT_STATUS_IS_OK(status)) {
8205 return false;
8207 b = p->binding_handle;
8209 ctx = talloc_zero(torture, struct torture_samr_context);
8211 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8212 ctx->machine_credentials = machine_credentials;
8214 ret &= test_Connect(b, torture, &ctx->handle);
8216 ret &= test_EnumDomains(p, torture, ctx);
8218 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8220 return ret;
8223 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8225 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8226 struct torture_rpc_tcase *tcase;
8228 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8229 &ndr_table_samr,
8230 TEST_ACCOUNT_NAME_PWD);
8232 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8233 torture_rpc_samr_pwdlastset);
8235 return suite;
8238 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8239 struct dcerpc_pipe *p2,
8240 struct cli_credentials *machine_credentials)
8242 NTSTATUS status;
8243 struct dcerpc_pipe *p;
8244 bool ret = true;
8245 struct torture_samr_context *ctx;
8246 struct dcerpc_binding_handle *b;
8248 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8249 if (!NT_STATUS_IS_OK(status)) {
8250 return false;
8252 b = p->binding_handle;
8254 ctx = talloc_zero(torture, struct torture_samr_context);
8256 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8257 ctx->machine_credentials = machine_credentials;
8259 ret &= test_Connect(b, torture, &ctx->handle);
8261 ret &= test_EnumDomains(p, torture, ctx);
8263 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8265 return ret;
8268 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8270 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8271 struct torture_rpc_tcase *tcase;
8273 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8274 &ndr_table_samr,
8275 TEST_ACCOUNT_NAME_PWD);
8277 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8278 torture_rpc_samr_users_privileges_delete_user);
8280 return suite;
8283 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8284 struct dcerpc_pipe *p2,
8285 void *data)
8287 NTSTATUS status;
8288 struct dcerpc_pipe *p;
8289 bool ret = true;
8290 struct torture_samr_context *ctx =
8291 talloc_get_type_abort(data, struct torture_samr_context);
8292 struct dcerpc_binding_handle *b;
8294 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8295 if (!NT_STATUS_IS_OK(status)) {
8296 return false;
8298 b = p->binding_handle;
8300 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8301 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8302 ctx->num_objects_large_dc);
8304 ret &= test_Connect(b, torture, &ctx->handle);
8306 ret &= test_EnumDomains(p, torture, ctx);
8308 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8310 return ret;
8313 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8314 struct dcerpc_pipe *p2,
8315 void *data)
8317 NTSTATUS status;
8318 struct dcerpc_pipe *p;
8319 bool ret = true;
8320 struct torture_samr_context *ctx =
8321 talloc_get_type_abort(data, struct torture_samr_context);
8322 struct dcerpc_binding_handle *b;
8324 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8325 if (!NT_STATUS_IS_OK(status)) {
8326 return false;
8328 b = p->binding_handle;
8330 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8331 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8332 ctx->num_objects_large_dc);
8334 ret &= test_Connect(b, torture, &ctx->handle);
8336 ret &= test_EnumDomains(p, torture, ctx);
8338 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8340 return ret;
8343 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8344 struct dcerpc_pipe *p2,
8345 void *data)
8347 NTSTATUS status;
8348 struct dcerpc_pipe *p;
8349 bool ret = true;
8350 struct torture_samr_context *ctx =
8351 talloc_get_type_abort(data, struct torture_samr_context);
8352 struct dcerpc_binding_handle *b;
8354 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8355 if (!NT_STATUS_IS_OK(status)) {
8356 return false;
8358 b = p->binding_handle;
8360 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8361 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8362 ctx->num_objects_large_dc);
8364 ret &= test_Connect(b, torture, &ctx->handle);
8366 ret &= test_EnumDomains(p, torture, ctx);
8368 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8370 return ret;
8373 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8375 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8376 struct torture_rpc_tcase *tcase;
8377 struct torture_samr_context *ctx;
8379 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8381 ctx = talloc_zero(suite, struct torture_samr_context);
8382 ctx->num_objects_large_dc = 150;
8384 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8385 torture_rpc_samr_many_aliases, ctx);
8386 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8387 torture_rpc_samr_many_groups, ctx);
8388 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8389 torture_rpc_samr_many_accounts, ctx);
8391 return suite;
8394 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8395 struct dcerpc_pipe *p2,
8396 struct cli_credentials *machine_credentials)
8398 NTSTATUS status;
8399 struct dcerpc_pipe *p;
8400 bool ret = true;
8401 struct torture_samr_context *ctx;
8402 struct dcerpc_binding_handle *b;
8404 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8405 if (!NT_STATUS_IS_OK(status)) {
8406 return false;
8408 b = p->binding_handle;
8410 ctx = talloc_zero(torture, struct torture_samr_context);
8412 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8413 ctx->machine_credentials = machine_credentials;
8415 ret &= test_Connect(b, torture, &ctx->handle);
8417 ret &= test_EnumDomains(p, torture, ctx);
8419 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8421 return ret;
8424 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8426 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8427 struct torture_rpc_tcase *tcase;
8429 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8430 &ndr_table_samr,
8431 TEST_ACCOUNT_NAME_PWD);
8433 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8434 torture_rpc_samr_badpwdcount);
8436 return suite;
8439 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8440 struct dcerpc_pipe *p2,
8441 struct cli_credentials *machine_credentials)
8443 NTSTATUS status;
8444 struct dcerpc_pipe *p;
8445 bool ret = true;
8446 struct torture_samr_context *ctx;
8447 struct dcerpc_binding_handle *b;
8449 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8450 if (!NT_STATUS_IS_OK(status)) {
8451 return false;
8453 b = p->binding_handle;
8455 ctx = talloc_zero(torture, struct torture_samr_context);
8457 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8458 ctx->machine_credentials = machine_credentials;
8460 ret &= test_Connect(b, torture, &ctx->handle);
8462 ret &= test_EnumDomains(p, torture, ctx);
8464 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8466 return ret;
8469 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8471 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8472 struct torture_rpc_tcase *tcase;
8474 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8475 &ndr_table_samr,
8476 TEST_ACCOUNT_NAME_PWD);
8478 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8479 torture_rpc_samr_lockout);
8481 return suite;
8484 struct torture_suite *torture_rpc_samr_passwords_validate(TALLOC_CTX *mem_ctx)
8486 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.validate");
8487 struct torture_rpc_tcase *tcase;
8489 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
8490 &ndr_table_samr);
8491 torture_rpc_tcase_add_test(tcase, "validate",
8492 test_samr_ValidatePassword);
8494 return suite;