s4:torture:rpc:samr: add debugging of result of (many) dcerpc_samr_* calls
[Samba/gebeck_regimport.git] / source4 / torture / rpc / samr.c
blobba0f20bcc888a9fe6037bda1d3c9203fea9e258b
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 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1763 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1765 /* Unbreak the LM hash */
1766 hash1.hash[0]--;
1768 r.in.user_handle = &user_handle;
1769 r.in.lm_present = 1;
1770 r.in.old_lm_crypted = &hash1;
1771 r.in.new_lm_crypted = &hash2;
1772 /* Break the NT hash */
1773 hash3.hash[0]--;
1774 r.in.nt_present = 1;
1775 r.in.old_nt_crypted = &hash3;
1776 r.in.new_nt_crypted = &hash4;
1777 r.in.cross1_present = 1;
1778 r.in.nt_cross = &hash5;
1779 r.in.cross2_present = 1;
1780 r.in.lm_cross = &hash6;
1782 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1783 "ChangePasswordUser failed");
1784 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1785 __location__, __FUNCTION__,
1786 oldpass, newpass, nt_errstr(r.out.result));
1787 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1788 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1790 /* Unbreak the NT hash */
1791 hash3.hash[0]--;
1793 r.in.user_handle = &user_handle;
1794 r.in.lm_present = 1;
1795 r.in.old_lm_crypted = &hash1;
1796 r.in.new_lm_crypted = &hash2;
1797 r.in.nt_present = 1;
1798 r.in.old_nt_crypted = &hash3;
1799 r.in.new_nt_crypted = &hash4;
1800 r.in.cross1_present = 1;
1801 r.in.nt_cross = &hash5;
1802 r.in.cross2_present = 1;
1803 /* Break the LM cross */
1804 hash6.hash[0]++;
1805 r.in.lm_cross = &hash6;
1807 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1808 "ChangePasswordUser failed");
1809 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1810 __location__, __FUNCTION__,
1811 oldpass, newpass, nt_errstr(r.out.result));
1812 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1813 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
1814 ret = false;
1817 /* Unbreak the LM cross */
1818 hash6.hash[0]--;
1820 r.in.user_handle = &user_handle;
1821 r.in.lm_present = 1;
1822 r.in.old_lm_crypted = &hash1;
1823 r.in.new_lm_crypted = &hash2;
1824 r.in.nt_present = 1;
1825 r.in.old_nt_crypted = &hash3;
1826 r.in.new_nt_crypted = &hash4;
1827 r.in.cross1_present = 1;
1828 /* Break the NT cross */
1829 hash5.hash[0]++;
1830 r.in.nt_cross = &hash5;
1831 r.in.cross2_present = 1;
1832 r.in.lm_cross = &hash6;
1834 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1835 "ChangePasswordUser failed");
1836 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1837 __location__, __FUNCTION__,
1838 oldpass, newpass, nt_errstr(r.out.result));
1839 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1840 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
1841 ret = false;
1844 /* Unbreak the NT cross */
1845 hash5.hash[0]--;
1848 /* Reset the hashes to not broken values */
1849 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1850 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1851 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1852 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1853 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1854 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1856 r.in.user_handle = &user_handle;
1857 r.in.lm_present = 1;
1858 r.in.old_lm_crypted = &hash1;
1859 r.in.new_lm_crypted = &hash2;
1860 r.in.nt_present = 1;
1861 r.in.old_nt_crypted = &hash3;
1862 r.in.new_nt_crypted = &hash4;
1863 r.in.cross1_present = 1;
1864 r.in.nt_cross = &hash5;
1865 r.in.cross2_present = 0;
1866 r.in.lm_cross = NULL;
1868 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1869 "ChangePasswordUser failed");
1870 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1871 __location__, __FUNCTION__,
1872 oldpass, newpass, nt_errstr(r.out.result));
1873 if (NT_STATUS_IS_OK(r.out.result)) {
1874 changed = true;
1875 *password = newpass;
1876 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1877 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1878 ret = false;
1881 oldpass = newpass;
1882 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1884 E_md4hash(oldpass, old_nt_hash);
1885 E_md4hash(newpass, new_nt_hash);
1886 E_deshash(oldpass, old_lm_hash);
1887 E_deshash(newpass, new_lm_hash);
1890 /* Reset the hashes to not broken values */
1891 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1892 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1893 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1894 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1895 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1896 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1898 r.in.user_handle = &user_handle;
1899 r.in.lm_present = 1;
1900 r.in.old_lm_crypted = &hash1;
1901 r.in.new_lm_crypted = &hash2;
1902 r.in.nt_present = 1;
1903 r.in.old_nt_crypted = &hash3;
1904 r.in.new_nt_crypted = &hash4;
1905 r.in.cross1_present = 0;
1906 r.in.nt_cross = NULL;
1907 r.in.cross2_present = 1;
1908 r.in.lm_cross = &hash6;
1910 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1911 "ChangePasswordUser failed");
1912 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1913 __location__, __FUNCTION__,
1914 oldpass, newpass, nt_errstr(r.out.result));
1915 if (NT_STATUS_IS_OK(r.out.result)) {
1916 changed = true;
1917 *password = newpass;
1918 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1919 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1920 ret = false;
1923 oldpass = newpass;
1924 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1926 E_md4hash(oldpass, old_nt_hash);
1927 E_md4hash(newpass, new_nt_hash);
1928 E_deshash(oldpass, old_lm_hash);
1929 E_deshash(newpass, new_lm_hash);
1932 /* Reset the hashes to not broken values */
1933 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1934 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1935 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1936 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1937 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1938 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1940 r.in.user_handle = &user_handle;
1941 r.in.lm_present = 1;
1942 r.in.old_lm_crypted = &hash1;
1943 r.in.new_lm_crypted = &hash2;
1944 r.in.nt_present = 1;
1945 r.in.old_nt_crypted = &hash3;
1946 r.in.new_nt_crypted = &hash4;
1947 r.in.cross1_present = 1;
1948 r.in.nt_cross = &hash5;
1949 r.in.cross2_present = 1;
1950 r.in.lm_cross = &hash6;
1952 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1953 "ChangePasswordUser failed");
1954 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1955 __location__, __FUNCTION__,
1956 oldpass, newpass, nt_errstr(r.out.result));
1957 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1958 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1959 } else if (!NT_STATUS_IS_OK(r.out.result)) {
1960 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1961 ret = false;
1962 } else {
1963 changed = true;
1964 *password = newpass;
1967 r.in.user_handle = &user_handle;
1968 r.in.lm_present = 1;
1969 r.in.old_lm_crypted = &hash1;
1970 r.in.new_lm_crypted = &hash2;
1971 r.in.nt_present = 1;
1972 r.in.old_nt_crypted = &hash3;
1973 r.in.new_nt_crypted = &hash4;
1974 r.in.cross1_present = 1;
1975 r.in.nt_cross = &hash5;
1976 r.in.cross2_present = 1;
1977 r.in.lm_cross = &hash6;
1979 if (changed) {
1980 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1981 "ChangePasswordUser failed");
1982 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1983 __location__, __FUNCTION__,
1984 oldpass, newpass, nt_errstr(r.out.result));
1985 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1986 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1987 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1988 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
1989 ret = false;
1994 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
1995 ret = false;
1998 return ret;
2002 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
2003 struct torture_context *tctx,
2004 const char *acct_name,
2005 struct policy_handle *handle, char **password)
2007 struct samr_OemChangePasswordUser2 r;
2008 bool ret = true;
2009 struct samr_Password lm_verifier;
2010 struct samr_CryptPassword lm_pass;
2011 struct lsa_AsciiString server, account, account_bad;
2012 char *oldpass;
2013 char *newpass;
2014 struct dcerpc_binding_handle *b = p->binding_handle;
2015 uint8_t old_lm_hash[16], new_lm_hash[16];
2017 struct samr_GetDomPwInfo dom_pw_info;
2018 struct samr_PwInfo info;
2019 int policy_min_pw_len = 0;
2021 struct lsa_String domain_name;
2023 domain_name.string = "";
2024 dom_pw_info.in.domain_name = &domain_name;
2025 dom_pw_info.out.info = &info;
2027 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
2029 torture_assert(tctx, *password != NULL,
2030 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
2032 oldpass = *password;
2034 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2035 "GetDomPwInfo failed");
2036 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2037 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2040 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2042 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2043 account.string = acct_name;
2045 E_deshash(oldpass, old_lm_hash);
2046 E_deshash(newpass, new_lm_hash);
2048 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2049 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2050 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2052 r.in.server = &server;
2053 r.in.account = &account;
2054 r.in.password = &lm_pass;
2055 r.in.hash = &lm_verifier;
2057 /* Break the verification */
2058 lm_verifier.hash[0]++;
2060 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2061 "OemChangePasswordUser2 failed");
2062 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2063 __location__, __FUNCTION__,
2064 oldpass, newpass, nt_errstr(r.out.result));
2066 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2067 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2068 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2069 nt_errstr(r.out.result));
2070 ret = false;
2073 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2074 /* Break the old password */
2075 old_lm_hash[0]++;
2076 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2077 /* unbreak it for the next operation */
2078 old_lm_hash[0]--;
2079 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2081 r.in.server = &server;
2082 r.in.account = &account;
2083 r.in.password = &lm_pass;
2084 r.in.hash = &lm_verifier;
2086 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2087 "OemChangePasswordUser2 failed");
2088 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2089 __location__, __FUNCTION__,
2090 oldpass, newpass, nt_errstr(r.out.result));
2092 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2093 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2094 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2095 nt_errstr(r.out.result));
2096 ret = false;
2099 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2100 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2102 r.in.server = &server;
2103 r.in.account = &account;
2104 r.in.password = &lm_pass;
2105 r.in.hash = NULL;
2107 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2108 "OemChangePasswordUser2 failed");
2109 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2110 __location__, __FUNCTION__,
2111 oldpass, newpass, nt_errstr(r.out.result));
2113 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2114 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2115 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2116 nt_errstr(r.out.result));
2117 ret = false;
2120 /* This shouldn't be a valid name */
2121 account_bad.string = TEST_ACCOUNT_NAME "XX";
2122 r.in.account = &account_bad;
2124 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2125 "OemChangePasswordUser2 failed");
2126 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2127 __location__, __FUNCTION__,
2128 oldpass, newpass, nt_errstr(r.out.result));
2130 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2131 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2132 nt_errstr(r.out.result));
2133 ret = false;
2136 /* This shouldn't be a valid name */
2137 account_bad.string = TEST_ACCOUNT_NAME "XX";
2138 r.in.account = &account_bad;
2139 r.in.password = &lm_pass;
2140 r.in.hash = &lm_verifier;
2142 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2143 "OemChangePasswordUser2 failed");
2144 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2145 __location__, __FUNCTION__,
2146 oldpass, newpass, nt_errstr(r.out.result));
2148 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2149 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2150 nt_errstr(r.out.result));
2151 ret = false;
2154 /* This shouldn't be a valid name */
2155 account_bad.string = TEST_ACCOUNT_NAME "XX";
2156 r.in.account = &account_bad;
2157 r.in.password = NULL;
2158 r.in.hash = &lm_verifier;
2160 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2161 "OemChangePasswordUser2 failed");
2162 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2163 __location__, __FUNCTION__,
2164 oldpass, newpass, nt_errstr(r.out.result));
2166 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2167 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2168 nt_errstr(r.out.result));
2169 ret = false;
2172 E_deshash(oldpass, old_lm_hash);
2173 E_deshash(newpass, new_lm_hash);
2175 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2176 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2177 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2179 r.in.server = &server;
2180 r.in.account = &account;
2181 r.in.password = &lm_pass;
2182 r.in.hash = &lm_verifier;
2184 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2185 "OemChangePasswordUser2 failed");
2186 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2187 __location__, __FUNCTION__,
2188 oldpass, newpass, nt_errstr(r.out.result));
2190 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2191 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2192 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2193 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2194 ret = false;
2195 } else {
2196 *password = newpass;
2199 return ret;
2203 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2204 const char *acct_name,
2205 char **password,
2206 char *newpass, bool allow_password_restriction)
2208 struct samr_ChangePasswordUser2 r;
2209 bool ret = true;
2210 struct lsa_String server, account;
2211 struct samr_CryptPassword nt_pass, lm_pass;
2212 struct samr_Password nt_verifier, lm_verifier;
2213 char *oldpass;
2214 struct dcerpc_binding_handle *b = p->binding_handle;
2215 uint8_t old_nt_hash[16], new_nt_hash[16];
2216 uint8_t old_lm_hash[16], new_lm_hash[16];
2218 struct samr_GetDomPwInfo dom_pw_info;
2219 struct samr_PwInfo info;
2221 struct lsa_String domain_name;
2223 domain_name.string = "";
2224 dom_pw_info.in.domain_name = &domain_name;
2225 dom_pw_info.out.info = &info;
2227 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2229 torture_assert(tctx, *password != NULL,
2230 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2231 oldpass = *password;
2233 if (!newpass) {
2234 int policy_min_pw_len = 0;
2235 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2236 "GetDomPwInfo failed");
2237 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2238 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2241 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2244 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2245 init_lsa_String(&account, acct_name);
2247 E_md4hash(oldpass, old_nt_hash);
2248 E_md4hash(newpass, new_nt_hash);
2250 E_deshash(oldpass, old_lm_hash);
2251 E_deshash(newpass, new_lm_hash);
2253 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2254 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2255 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2257 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2258 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2259 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2261 r.in.server = &server;
2262 r.in.account = &account;
2263 r.in.nt_password = &nt_pass;
2264 r.in.nt_verifier = &nt_verifier;
2265 r.in.lm_change = 1;
2266 r.in.lm_password = &lm_pass;
2267 r.in.lm_verifier = &lm_verifier;
2269 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2270 "ChangePasswordUser2 failed");
2271 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2272 __location__, __FUNCTION__,
2273 oldpass, newpass, nt_errstr(r.out.result));
2275 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2276 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2277 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2278 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2279 ret = false;
2280 } else {
2281 *password = newpass;
2284 return ret;
2288 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2289 const char *account_string,
2290 int policy_min_pw_len,
2291 char **password,
2292 const char *newpass,
2293 NTTIME last_password_change,
2294 bool handle_reject_reason)
2296 struct samr_ChangePasswordUser3 r;
2297 bool ret = true;
2298 struct lsa_String server, account, account_bad;
2299 struct samr_CryptPassword nt_pass, lm_pass;
2300 struct samr_Password nt_verifier, lm_verifier;
2301 char *oldpass;
2302 struct dcerpc_binding_handle *b = p->binding_handle;
2303 uint8_t old_nt_hash[16], new_nt_hash[16];
2304 uint8_t old_lm_hash[16], new_lm_hash[16];
2305 NTTIME t;
2306 struct samr_DomInfo1 *dominfo = NULL;
2307 struct userPwdChangeFailureInformation *reject = NULL;
2309 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2311 if (newpass == NULL) {
2312 do {
2313 if (policy_min_pw_len == 0) {
2314 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2315 } else {
2316 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2318 } while (check_password_quality(newpass) == false);
2319 } else {
2320 torture_comment(tctx, "Using password '%s'\n", newpass);
2323 torture_assert(tctx, *password != NULL,
2324 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2326 oldpass = *password;
2327 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2328 init_lsa_String(&account, account_string);
2330 E_md4hash(oldpass, old_nt_hash);
2331 E_md4hash(newpass, new_nt_hash);
2333 E_deshash(oldpass, old_lm_hash);
2334 E_deshash(newpass, new_lm_hash);
2336 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2337 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2338 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2340 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2341 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2342 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2344 /* Break the verification */
2345 nt_verifier.hash[0]++;
2347 r.in.server = &server;
2348 r.in.account = &account;
2349 r.in.nt_password = &nt_pass;
2350 r.in.nt_verifier = &nt_verifier;
2351 r.in.lm_change = 1;
2352 r.in.lm_password = &lm_pass;
2353 r.in.lm_verifier = &lm_verifier;
2354 r.in.password3 = NULL;
2355 r.out.dominfo = &dominfo;
2356 r.out.reject = &reject;
2358 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2359 "ChangePasswordUser3 failed");
2360 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2361 __location__, __FUNCTION__,
2362 oldpass, newpass, nt_errstr(r.out.result));
2363 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2364 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2365 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2366 nt_errstr(r.out.result));
2367 ret = false;
2370 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2371 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2372 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2374 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2375 /* Break the NT hash */
2376 old_nt_hash[0]++;
2377 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2378 /* Unbreak it again */
2379 old_nt_hash[0]--;
2380 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2382 r.in.server = &server;
2383 r.in.account = &account;
2384 r.in.nt_password = &nt_pass;
2385 r.in.nt_verifier = &nt_verifier;
2386 r.in.lm_change = 1;
2387 r.in.lm_password = &lm_pass;
2388 r.in.lm_verifier = &lm_verifier;
2389 r.in.password3 = NULL;
2390 r.out.dominfo = &dominfo;
2391 r.out.reject = &reject;
2393 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2394 "ChangePasswordUser3 failed");
2395 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2396 __location__, __FUNCTION__,
2397 oldpass, newpass, nt_errstr(r.out.result));
2398 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2399 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2400 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2401 nt_errstr(r.out.result));
2402 ret = false;
2405 /* This shouldn't be a valid name */
2406 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2408 r.in.account = &account_bad;
2409 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2410 "ChangePasswordUser3 failed");
2411 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2412 __location__, __FUNCTION__,
2413 oldpass, newpass, nt_errstr(r.out.result));
2414 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2415 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2416 nt_errstr(r.out.result));
2417 ret = false;
2420 E_md4hash(oldpass, old_nt_hash);
2421 E_md4hash(newpass, new_nt_hash);
2423 E_deshash(oldpass, old_lm_hash);
2424 E_deshash(newpass, new_lm_hash);
2426 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2427 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2428 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2430 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2431 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2432 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2434 r.in.server = &server;
2435 r.in.account = &account;
2436 r.in.nt_password = &nt_pass;
2437 r.in.nt_verifier = &nt_verifier;
2438 r.in.lm_change = 1;
2439 r.in.lm_password = &lm_pass;
2440 r.in.lm_verifier = &lm_verifier;
2441 r.in.password3 = NULL;
2442 r.out.dominfo = &dominfo;
2443 r.out.reject = &reject;
2445 unix_to_nt_time(&t, time(NULL));
2447 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2448 "ChangePasswordUser3 failed");
2449 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2450 __location__, __FUNCTION__,
2451 oldpass, newpass, nt_errstr(r.out.result));
2453 torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2454 "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2455 __location__,
2456 (dominfo == NULL)? "NULL" : "present",
2457 reject ? "true" : "false",
2458 handle_reject_reason ? "true" : "false",
2459 null_nttime(last_password_change) ? "null" : "not null",
2460 dominfo ? (long long)dominfo->min_password_age : (long long)0);
2462 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2463 && dominfo
2464 && reject
2465 && handle_reject_reason
2466 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2467 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2469 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2470 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2471 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2472 return false;
2476 /* We tested the order of precendence which is as follows:
2478 * pwd min_age
2479 * pwd length
2480 * pwd complexity
2481 * pwd history
2483 Guenther */
2485 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2486 (last_password_change + dominfo->min_password_age > t)) {
2488 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2489 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2490 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2491 return false;
2494 } else if ((dominfo->min_password_length > 0) &&
2495 (strlen(newpass) < dominfo->min_password_length)) {
2497 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2498 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2499 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2500 return false;
2503 } else if ((dominfo->password_history_length > 0) &&
2504 strequal(oldpass, newpass)) {
2506 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2507 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2508 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2509 return false;
2511 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2513 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2514 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2515 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2516 return false;
2521 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2522 /* retry with adjusted size */
2523 return test_ChangePasswordUser3(p, tctx, account_string,
2524 dominfo->min_password_length,
2525 password, NULL, 0, false);
2529 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2530 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2531 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2532 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2533 return false;
2535 /* Perhaps the server has a 'min password age' set? */
2537 } else {
2538 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2540 *password = talloc_strdup(tctx, newpass);
2543 return ret;
2546 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2547 const char *account_string,
2548 struct policy_handle *handle,
2549 char **password)
2551 NTSTATUS status;
2552 struct samr_ChangePasswordUser3 r;
2553 struct samr_SetUserInfo s;
2554 union samr_UserInfo u;
2555 DATA_BLOB session_key;
2556 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2557 uint8_t confounder[16];
2558 struct MD5Context ctx;
2560 bool ret = true;
2561 struct lsa_String server, account;
2562 struct samr_CryptPassword nt_pass;
2563 struct samr_Password nt_verifier;
2564 DATA_BLOB new_random_pass;
2565 char *newpass;
2566 char *oldpass;
2567 struct dcerpc_binding_handle *b = p->binding_handle;
2568 uint8_t old_nt_hash[16], new_nt_hash[16];
2569 NTTIME t;
2570 struct samr_DomInfo1 *dominfo = NULL;
2571 struct userPwdChangeFailureInformation *reject = NULL;
2573 new_random_pass = samr_very_rand_pass(tctx, 128);
2575 torture_assert(tctx, *password != NULL,
2576 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2578 oldpass = *password;
2579 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2580 init_lsa_String(&account, account_string);
2582 s.in.user_handle = handle;
2583 s.in.info = &u;
2584 s.in.level = 25;
2586 ZERO_STRUCT(u);
2588 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2590 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2592 status = dcerpc_fetch_session_key(p, &session_key);
2593 if (!NT_STATUS_IS_OK(status)) {
2594 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2595 s.in.level, nt_errstr(status));
2596 return false;
2599 generate_random_buffer((uint8_t *)confounder, 16);
2601 MD5Init(&ctx);
2602 MD5Update(&ctx, confounder, 16);
2603 MD5Update(&ctx, session_key.data, session_key.length);
2604 MD5Final(confounded_session_key.data, &ctx);
2606 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2607 memcpy(&u.info25.password.data[516], confounder, 16);
2609 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2611 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2612 "SetUserInfo failed");
2613 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2614 __location__, __FUNCTION__,
2615 oldpass, "RANDOM", nt_errstr(s.out.result));
2616 if (!NT_STATUS_IS_OK(s.out.result)) {
2617 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2618 s.in.level, nt_errstr(s.out.result));
2619 ret = false;
2622 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2624 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2626 new_random_pass = samr_very_rand_pass(tctx, 128);
2628 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2630 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2631 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2632 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2634 r.in.server = &server;
2635 r.in.account = &account;
2636 r.in.nt_password = &nt_pass;
2637 r.in.nt_verifier = &nt_verifier;
2638 r.in.lm_change = 0;
2639 r.in.lm_password = NULL;
2640 r.in.lm_verifier = NULL;
2641 r.in.password3 = NULL;
2642 r.out.dominfo = &dominfo;
2643 r.out.reject = &reject;
2645 unix_to_nt_time(&t, time(NULL));
2647 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2648 "ChangePasswordUser3 failed");
2649 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2650 __location__, __FUNCTION__,
2651 oldpass, "RANDOM", nt_errstr(r.out.result));
2653 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2654 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2655 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2656 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2657 return false;
2659 /* Perhaps the server has a 'min password age' set? */
2661 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2662 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2663 ret = false;
2666 newpass = samr_rand_pass(tctx, 128);
2668 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2670 E_md4hash(newpass, new_nt_hash);
2672 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2673 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2674 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2676 r.in.server = &server;
2677 r.in.account = &account;
2678 r.in.nt_password = &nt_pass;
2679 r.in.nt_verifier = &nt_verifier;
2680 r.in.lm_change = 0;
2681 r.in.lm_password = NULL;
2682 r.in.lm_verifier = NULL;
2683 r.in.password3 = NULL;
2684 r.out.dominfo = &dominfo;
2685 r.out.reject = &reject;
2687 unix_to_nt_time(&t, time(NULL));
2689 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2690 "ChangePasswordUser3 failed");
2691 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2692 __location__, __FUNCTION__,
2693 oldpass, newpass, nt_errstr(r.out.result));
2695 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2696 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2697 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2698 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2699 return false;
2701 /* Perhaps the server has a 'min password age' set? */
2703 } else {
2704 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2705 *password = talloc_strdup(tctx, newpass);
2708 return ret;
2712 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2713 struct torture_context *tctx,
2714 struct policy_handle *alias_handle)
2716 struct samr_GetMembersInAlias r;
2717 struct lsa_SidArray sids;
2719 torture_comment(tctx, "Testing GetMembersInAlias\n");
2721 r.in.alias_handle = alias_handle;
2722 r.out.sids = &sids;
2724 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2725 "GetMembersInAlias failed");
2726 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2728 return true;
2731 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2732 struct torture_context *tctx,
2733 struct policy_handle *alias_handle,
2734 const struct dom_sid *domain_sid)
2736 struct samr_AddAliasMember r;
2737 struct samr_DeleteAliasMember d;
2738 struct dom_sid *sid;
2740 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2742 torture_comment(tctx, "Testing AddAliasMember\n");
2743 r.in.alias_handle = alias_handle;
2744 r.in.sid = sid;
2746 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2747 "AddAliasMember failed");
2748 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2750 d.in.alias_handle = alias_handle;
2751 d.in.sid = sid;
2753 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2754 "DeleteAliasMember failed");
2755 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2757 return true;
2760 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2761 struct torture_context *tctx,
2762 struct policy_handle *alias_handle)
2764 struct samr_AddMultipleMembersToAlias a;
2765 struct samr_RemoveMultipleMembersFromAlias r;
2766 struct lsa_SidArray sids;
2768 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2769 a.in.alias_handle = alias_handle;
2770 a.in.sids = &sids;
2772 sids.num_sids = 3;
2773 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2775 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2776 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2777 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2779 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2780 "AddMultipleMembersToAlias failed");
2781 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2784 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2785 r.in.alias_handle = alias_handle;
2786 r.in.sids = &sids;
2788 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2789 "RemoveMultipleMembersFromAlias failed");
2790 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2792 /* strange! removing twice doesn't give any error */
2793 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2794 "RemoveMultipleMembersFromAlias failed");
2795 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2797 /* but removing an alias that isn't there does */
2798 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2800 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2801 "RemoveMultipleMembersFromAlias failed");
2802 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2804 return true;
2807 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2808 struct torture_context *tctx,
2809 struct policy_handle *domain_handle)
2811 struct samr_GetAliasMembership r;
2812 struct lsa_SidArray sids;
2813 struct samr_Ids rids;
2815 torture_comment(tctx, "Testing GetAliasMembership\n");
2817 r.in.domain_handle = domain_handle;
2818 r.in.sids = &sids;
2819 r.out.rids = &rids;
2821 sids.num_sids = 0;
2822 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2824 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2825 "GetAliasMembership failed");
2826 torture_assert_ntstatus_ok(tctx, r.out.result,
2827 "samr_GetAliasMembership failed");
2829 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2830 "protocol misbehaviour");
2832 sids.num_sids = 1;
2833 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2834 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2836 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2837 "samr_GetAliasMembership failed");
2838 torture_assert_ntstatus_ok(tctx, r.out.result,
2839 "samr_GetAliasMembership failed");
2841 #if 0
2842 /* only true for w2k8 it seems
2843 * win7, xp, w2k3 will return a 0 length array pointer */
2845 if (rids.ids && (rids.count == 0)) {
2846 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2848 #endif
2849 if (!rids.ids && rids.count) {
2850 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2853 return true;
2856 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2857 struct torture_context *tctx,
2858 struct policy_handle *user_handle)
2860 struct samr_TestPrivateFunctionsUser r;
2862 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2864 r.in.user_handle = user_handle;
2866 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2867 "TestPrivateFunctionsUser failed");
2868 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2870 return true;
2873 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2874 struct torture_context *tctx,
2875 struct policy_handle *handle,
2876 bool use_info2,
2877 NTTIME *pwdlastset)
2879 NTSTATUS status;
2880 uint16_t levels[] = { /* 3, */ 5, 21 };
2881 int i;
2882 NTTIME pwdlastset3 = 0;
2883 NTTIME pwdlastset5 = 0;
2884 NTTIME pwdlastset21 = 0;
2886 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2887 use_info2 ? "2":"");
2889 for (i=0; i<ARRAY_SIZE(levels); i++) {
2891 struct samr_QueryUserInfo r;
2892 struct samr_QueryUserInfo2 r2;
2893 union samr_UserInfo *info;
2895 if (use_info2) {
2896 r2.in.user_handle = handle;
2897 r2.in.level = levels[i];
2898 r2.out.info = &info;
2899 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2900 "QueryUserInfo2 failed");
2901 status = r2.out.result;
2903 } else {
2904 r.in.user_handle = handle;
2905 r.in.level = levels[i];
2906 r.out.info = &info;
2907 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2908 "QueryUserInfo failed");
2909 status = r.out.result;
2912 if (!NT_STATUS_IS_OK(status) &&
2913 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2914 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2915 use_info2 ? "2":"", levels[i], nt_errstr(status));
2916 return false;
2919 switch (levels[i]) {
2920 case 3:
2921 pwdlastset3 = info->info3.last_password_change;
2922 break;
2923 case 5:
2924 pwdlastset5 = info->info5.last_password_change;
2925 break;
2926 case 21:
2927 pwdlastset21 = info->info21.last_password_change;
2928 break;
2929 default:
2930 return false;
2933 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2934 "pwdlastset mixup"); */
2935 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2936 "pwdlastset mixup");
2938 *pwdlastset = pwdlastset21;
2940 torture_comment(tctx, "(pwdlastset: %llu)\n",
2941 (unsigned long long) *pwdlastset);
2943 return true;
2946 static bool test_SamLogon(struct torture_context *tctx,
2947 struct dcerpc_pipe *p,
2948 struct cli_credentials *test_credentials,
2949 NTSTATUS expected_result,
2950 bool interactive)
2952 NTSTATUS status;
2953 struct netr_LogonSamLogonEx r;
2954 union netr_LogonLevel logon;
2955 union netr_Validation validation;
2956 uint8_t authoritative;
2957 struct netr_IdentityInfo identity;
2958 struct netr_NetworkInfo ninfo;
2959 struct netr_PasswordInfo pinfo;
2960 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2961 int flags = CLI_CRED_NTLM_AUTH;
2962 uint32_t samlogon_flags = 0;
2963 struct netlogon_creds_CredentialState *creds;
2964 struct netr_Authenticator a;
2965 struct dcerpc_binding_handle *b = p->binding_handle;
2967 torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2969 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
2970 flags |= CLI_CRED_LANMAN_AUTH;
2973 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
2974 flags |= CLI_CRED_NTLMv2_AUTH;
2977 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2978 &identity.account_name.string,
2979 &identity.domain_name.string);
2981 identity.parameter_control =
2982 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2983 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2984 identity.logon_id_low = 0;
2985 identity.logon_id_high = 0;
2986 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2988 if (interactive) {
2989 netlogon_creds_client_authenticator(creds, &a);
2991 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
2992 ZERO_STRUCT(pinfo.lmpassword.hash);
2994 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
2996 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2997 netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
2998 netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
2999 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
3000 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
3001 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
3002 } else {
3003 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
3004 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
3007 pinfo.identity_info = identity;
3008 logon.password = &pinfo;
3010 r.in.logon_level = NetlogonInteractiveInformation;
3011 } else {
3012 generate_random_buffer(ninfo.challenge,
3013 sizeof(ninfo.challenge));
3014 chal = data_blob_const(ninfo.challenge,
3015 sizeof(ninfo.challenge));
3017 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3018 cli_credentials_get_domain(test_credentials));
3020 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3021 &flags,
3022 chal,
3023 names_blob,
3024 &lm_resp, &nt_resp,
3025 NULL, NULL);
3026 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3028 ninfo.lm.data = lm_resp.data;
3029 ninfo.lm.length = lm_resp.length;
3031 ninfo.nt.data = nt_resp.data;
3032 ninfo.nt.length = nt_resp.length;
3034 ninfo.identity_info = identity;
3035 logon.network = &ninfo;
3037 r.in.logon_level = NetlogonNetworkInformation;
3040 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3041 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3042 r.in.logon = &logon;
3043 r.in.flags = &samlogon_flags;
3044 r.out.flags = &samlogon_flags;
3045 r.out.validation = &validation;
3046 r.out.authoritative = &authoritative;
3048 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3050 r.in.validation_level = 6;
3052 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3053 "netr_LogonSamLogonEx failed");
3054 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3055 r.in.validation_level = 3;
3056 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3057 "netr_LogonSamLogonEx failed");
3059 if (!NT_STATUS_IS_OK(r.out.result)) {
3060 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3061 return true;
3062 } else {
3063 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3066 return true;
3069 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3070 struct dcerpc_pipe *p,
3071 struct cli_credentials *machine_creds,
3072 const char *acct_name,
3073 const char *password,
3074 NTSTATUS expected_samlogon_result,
3075 bool interactive)
3077 bool ret = true;
3078 struct cli_credentials *test_credentials;
3080 test_credentials = cli_credentials_init(tctx);
3082 cli_credentials_set_workstation(test_credentials,
3083 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3084 cli_credentials_set_domain(test_credentials,
3085 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3086 cli_credentials_set_username(test_credentials,
3087 acct_name, CRED_SPECIFIED);
3088 cli_credentials_set_password(test_credentials,
3089 password, CRED_SPECIFIED);
3091 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3092 interactive ? "interactive" : "network", acct_name, password);
3094 if (!test_SamLogon(tctx, p, test_credentials,
3095 expected_samlogon_result, interactive)) {
3096 torture_warning(tctx, "new password did not work\n");
3097 ret = false;
3100 return ret;
3103 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3104 struct dcerpc_pipe *np,
3105 struct torture_context *tctx,
3106 struct policy_handle *handle,
3107 uint16_t level,
3108 uint32_t fields_present,
3109 uint8_t password_expired,
3110 bool *matched_expected_error,
3111 bool use_setinfo2,
3112 const char *acct_name,
3113 char **password,
3114 struct cli_credentials *machine_creds,
3115 bool use_queryinfo2,
3116 NTTIME *pwdlastset,
3117 NTSTATUS expected_samlogon_result)
3119 const char *fields = NULL;
3120 bool ret = true;
3121 struct dcerpc_binding_handle *b = p->binding_handle;
3123 switch (level) {
3124 case 21:
3125 case 23:
3126 case 25:
3127 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3128 fields_present);
3129 break;
3130 default:
3131 break;
3134 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3135 "(password_expired: %d) %s\n",
3136 use_setinfo2 ? "2":"", level, password_expired,
3137 fields ? fields : "");
3139 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3140 fields_present,
3141 password,
3142 password_expired,
3143 use_setinfo2,
3144 matched_expected_error)) {
3145 ret = false;
3148 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3149 use_queryinfo2,
3150 pwdlastset)) {
3151 ret = false;
3154 if (*matched_expected_error == true) {
3155 return ret;
3158 if (!test_SamLogon_with_creds(tctx, np,
3159 machine_creds,
3160 acct_name,
3161 *password,
3162 expected_samlogon_result,
3163 false)) {
3164 ret = false;
3167 return ret;
3170 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3171 struct cli_credentials *credentials,
3172 struct dcerpc_pipe **p)
3174 struct dcerpc_binding *b;
3176 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3177 "failed to get rpc binding");
3179 /* We have to use schannel, otherwise the SamLogonEx fails
3180 * with INTERNAL_ERROR */
3182 b->flags &= ~DCERPC_AUTH_OPTIONS;
3183 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO;
3185 torture_assert_ntstatus_ok(tctx,
3186 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3187 credentials, tctx->ev, tctx->lp_ctx),
3188 "failed to bind to netlogon");
3190 return true;
3193 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3194 struct torture_context *tctx,
3195 uint32_t acct_flags,
3196 const char *acct_name,
3197 struct policy_handle *handle,
3198 char **password,
3199 struct cli_credentials *machine_credentials)
3201 int s = 0, q = 0, f = 0, l = 0, z = 0;
3202 bool ret = true;
3203 int delay = 50000;
3204 bool set_levels[] = { false, true };
3205 bool query_levels[] = { false, true };
3206 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3207 uint32_t nonzeros[] = { 1, 24 };
3208 uint32_t fields_present[] = {
3210 SAMR_FIELD_EXPIRED_FLAG,
3211 SAMR_FIELD_LAST_PWD_CHANGE,
3212 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3213 SAMR_FIELD_COMMENT,
3214 SAMR_FIELD_NT_PASSWORD_PRESENT,
3215 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3216 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3217 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3218 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3219 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3220 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3222 struct dcerpc_pipe *np = NULL;
3224 if (torture_setting_bool(tctx, "samba3", false) ||
3225 torture_setting_bool(tctx, "samba4", false)) {
3226 delay = 999999;
3227 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3228 delay);
3231 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3233 /* set to 1 to enable testing for all possible opcode
3234 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3235 combinations */
3236 #if 0
3237 #define TEST_ALL_LEVELS 1
3238 #define TEST_SET_LEVELS 1
3239 #define TEST_QUERY_LEVELS 1
3240 #endif
3241 #ifdef TEST_ALL_LEVELS
3242 for (l=0; l<ARRAY_SIZE(levels); l++) {
3243 #else
3244 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3245 #endif
3246 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3247 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3248 #ifdef TEST_SET_LEVELS
3249 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3250 #endif
3251 #ifdef TEST_QUERY_LEVELS
3252 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3253 #endif
3254 NTTIME pwdlastset_old = 0;
3255 NTTIME pwdlastset_new = 0;
3256 bool matched_expected_error = false;
3257 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3259 torture_comment(tctx, "------------------------------\n"
3260 "Testing pwdLastSet attribute for flags: 0x%08x "
3261 "(s: %d (l: %d), q: %d)\n",
3262 acct_flags, s, levels[l], q);
3264 switch (levels[l]) {
3265 case 21:
3266 case 23:
3267 case 25:
3268 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3269 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3270 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3272 break;
3276 /* set #1 */
3278 /* set a password and force password change (pwdlastset 0) by
3279 * setting the password expired flag to a non-0 value */
3281 if (!test_SetPassword_level(p, np, tctx, handle,
3282 levels[l],
3283 fields_present[f],
3284 nonzeros[z],
3285 &matched_expected_error,
3286 set_levels[s],
3287 acct_name,
3288 password,
3289 machine_credentials,
3290 query_levels[q],
3291 &pwdlastset_new,
3292 expected_samlogon_result)) {
3293 ret = false;
3296 if (matched_expected_error == true) {
3297 /* skipping on expected failure */
3298 continue;
3301 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3302 * set without the SAMR_FIELD_EXPIRED_FLAG */
3304 switch (levels[l]) {
3305 case 21:
3306 case 23:
3307 case 25:
3308 if ((pwdlastset_new != 0) &&
3309 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3310 torture_comment(tctx, "not considering a non-0 "
3311 "pwdLastSet as a an error as the "
3312 "SAMR_FIELD_EXPIRED_FLAG has not "
3313 "been set\n");
3314 break;
3316 break;
3317 default:
3318 if (pwdlastset_new != 0) {
3319 torture_warning(tctx, "pwdLastSet test failed: "
3320 "expected pwdLastSet 0 but got %llu\n",
3321 (unsigned long long) pwdlastset_old);
3322 ret = false;
3324 break;
3327 switch (levels[l]) {
3328 case 21:
3329 case 23:
3330 case 25:
3331 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3332 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3333 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3334 (pwdlastset_old >= pwdlastset_new)) {
3335 torture_warning(tctx, "pwdlastset not increasing\n");
3336 ret = false;
3338 break;
3341 pwdlastset_old = pwdlastset_new;
3343 usleep(delay);
3345 /* set #2 */
3347 /* set a password, pwdlastset needs to get updated (increased
3348 * value), password_expired value used here is 0 */
3350 if (!test_SetPassword_level(p, np, tctx, handle,
3351 levels[l],
3352 fields_present[f],
3354 &matched_expected_error,
3355 set_levels[s],
3356 acct_name,
3357 password,
3358 machine_credentials,
3359 query_levels[q],
3360 &pwdlastset_new,
3361 expected_samlogon_result)) {
3362 ret = false;
3365 /* when a password has been changed, pwdlastset must not be 0 afterwards
3366 * and must be larger then the old value */
3368 switch (levels[l]) {
3369 case 21:
3370 case 23:
3371 case 25:
3372 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3373 * password has been changed, old and new pwdlastset
3374 * need to be the same value */
3376 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3377 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3378 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3380 torture_assert_int_equal(tctx, pwdlastset_old,
3381 pwdlastset_new, "pwdlastset must be equal");
3382 break;
3384 break;
3385 default:
3386 if (pwdlastset_old >= pwdlastset_new) {
3387 torture_warning(tctx, "pwdLastSet test failed: "
3388 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3389 (unsigned long long) pwdlastset_old,
3390 (unsigned long long) pwdlastset_new);
3391 ret = false;
3393 if (pwdlastset_new == 0) {
3394 torture_warning(tctx, "pwdLastSet test failed: "
3395 "expected non-0 pwdlastset, got: %llu\n",
3396 (unsigned long long) pwdlastset_new);
3397 ret = false;
3399 break;
3402 switch (levels[l]) {
3403 case 21:
3404 case 23:
3405 case 25:
3406 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3407 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3408 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3409 (pwdlastset_old >= pwdlastset_new)) {
3410 torture_warning(tctx, "pwdlastset not increasing\n");
3411 ret = false;
3413 break;
3416 pwdlastset_old = pwdlastset_new;
3418 usleep(delay);
3420 /* set #2b */
3422 /* set a password, pwdlastset needs to get updated (increased
3423 * value), password_expired value used here is 0 */
3425 if (!test_SetPassword_level(p, np, tctx, handle,
3426 levels[l],
3427 fields_present[f],
3429 &matched_expected_error,
3430 set_levels[s],
3431 acct_name,
3432 password,
3433 machine_credentials,
3434 query_levels[q],
3435 &pwdlastset_new,
3436 expected_samlogon_result)) {
3437 ret = false;
3440 /* when a password has been changed, pwdlastset must not be 0 afterwards
3441 * and must be larger then the old value */
3443 switch (levels[l]) {
3444 case 21:
3445 case 23:
3446 case 25:
3448 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3449 * password has been changed, old and new pwdlastset
3450 * need to be the same value */
3452 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3453 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3454 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3456 torture_assert_int_equal(tctx, pwdlastset_old,
3457 pwdlastset_new, "pwdlastset must be equal");
3458 break;
3460 break;
3461 default:
3462 if (pwdlastset_old >= pwdlastset_new) {
3463 torture_warning(tctx, "pwdLastSet test failed: "
3464 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3465 (unsigned long long) pwdlastset_old,
3466 (unsigned long long) pwdlastset_new);
3467 ret = false;
3469 if (pwdlastset_new == 0) {
3470 torture_warning(tctx, "pwdLastSet test failed: "
3471 "expected non-0 pwdlastset, got: %llu\n",
3472 (unsigned long long) pwdlastset_new);
3473 ret = false;
3475 break;
3478 switch (levels[l]) {
3479 case 21:
3480 case 23:
3481 case 25:
3482 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3483 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3484 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3485 (pwdlastset_old >= pwdlastset_new)) {
3486 torture_warning(tctx, "pwdlastset not increasing\n");
3487 ret = false;
3489 break;
3492 pwdlastset_old = pwdlastset_new;
3494 usleep(delay);
3496 /* set #3 */
3498 /* set a password and force password change (pwdlastset 0) by
3499 * setting the password expired flag to a non-0 value */
3501 if (!test_SetPassword_level(p, np, tctx, handle,
3502 levels[l],
3503 fields_present[f],
3504 nonzeros[z],
3505 &matched_expected_error,
3506 set_levels[s],
3507 acct_name,
3508 password,
3509 machine_credentials,
3510 query_levels[q],
3511 &pwdlastset_new,
3512 expected_samlogon_result)) {
3513 ret = false;
3516 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3517 * set without the SAMR_FIELD_EXPIRED_FLAG */
3519 switch (levels[l]) {
3520 case 21:
3521 case 23:
3522 case 25:
3523 if ((pwdlastset_new != 0) &&
3524 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3525 torture_comment(tctx, "not considering a non-0 "
3526 "pwdLastSet as a an error as the "
3527 "SAMR_FIELD_EXPIRED_FLAG has not "
3528 "been set\n");
3529 break;
3532 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3533 * password has been changed, old and new pwdlastset
3534 * need to be the same value */
3536 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3537 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3538 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3540 torture_assert_int_equal(tctx, pwdlastset_old,
3541 pwdlastset_new, "pwdlastset must be equal");
3542 break;
3544 break;
3545 default:
3546 if (pwdlastset_new != 0) {
3547 torture_warning(tctx, "pwdLastSet test failed: "
3548 "expected pwdLastSet 0, got %llu\n",
3549 (unsigned long long) pwdlastset_old);
3550 ret = false;
3552 break;
3555 switch (levels[l]) {
3556 case 21:
3557 case 23:
3558 case 25:
3559 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3560 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3561 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3562 (pwdlastset_old >= pwdlastset_new)) {
3563 torture_warning(tctx, "pwdlastset not increasing\n");
3564 ret = false;
3566 break;
3569 /* if the level we are testing does not have a fields_present
3570 * field, skip all fields present tests by setting f to to
3571 * arraysize */
3572 switch (levels[l]) {
3573 case 18:
3574 case 24:
3575 case 26:
3576 f = ARRAY_SIZE(fields_present);
3577 break;
3580 #ifdef TEST_QUERY_LEVELS
3582 #endif
3583 #ifdef TEST_SET_LEVELS
3585 #endif
3586 } /* fields present */
3587 } /* nonzeros */
3588 } /* levels */
3590 #undef TEST_SET_LEVELS
3591 #undef TEST_QUERY_LEVELS
3593 talloc_free(np);
3595 return ret;
3598 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3599 struct torture_context *tctx,
3600 struct policy_handle *handle,
3601 uint32_t *badpwdcount)
3603 union samr_UserInfo *info;
3604 struct samr_QueryUserInfo r;
3606 r.in.user_handle = handle;
3607 r.in.level = 3;
3608 r.out.info = &info;
3610 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3612 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3613 "failed to query userinfo");
3614 torture_assert_ntstatus_ok(tctx, r.out.result,
3615 "failed to query userinfo");
3617 *badpwdcount = info->info3.bad_password_count;
3619 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3621 return true;
3624 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3625 struct torture_context *tctx,
3626 struct policy_handle *user_handle,
3627 uint32_t acct_flags)
3629 struct samr_SetUserInfo r;
3630 union samr_UserInfo user_info;
3632 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3634 user_info.info16.acct_flags = acct_flags;
3636 r.in.user_handle = user_handle;
3637 r.in.level = 16;
3638 r.in.info = &user_info;
3640 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3641 "failed to set account flags");
3642 torture_assert_ntstatus_ok(tctx, r.out.result,
3643 "failed to set account flags");
3645 return true;
3648 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3649 struct torture_context *tctx,
3650 struct policy_handle *user_handle,
3651 uint32_t acct_flags,
3652 char **password)
3654 struct dcerpc_binding_handle *b = p->binding_handle;
3656 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3657 "failed to set password");
3659 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3661 torture_assert(tctx,
3662 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3663 acct_flags & ~ACB_DISABLED),
3664 "failed to enable user");
3666 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3667 "failed to set password");
3669 return true;
3672 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3673 struct torture_context *tctx,
3674 struct policy_handle *domain_handle,
3675 enum samr_DomainInfoClass level,
3676 union samr_DomainInfo *info)
3678 struct samr_SetDomainInfo r;
3680 r.in.domain_handle = domain_handle;
3681 r.in.level = level;
3682 r.in.info = info;
3684 torture_assert_ntstatus_ok(tctx,
3685 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3686 "failed to set domain info");
3687 torture_assert_ntstatus_ok(tctx, r.out.result,
3688 "failed to set domain info");
3690 return true;
3693 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3694 struct torture_context *tctx,
3695 struct policy_handle *domain_handle,
3696 enum samr_DomainInfoClass level,
3697 union samr_DomainInfo *info,
3698 NTSTATUS expected)
3700 struct samr_SetDomainInfo r;
3702 r.in.domain_handle = domain_handle;
3703 r.in.level = level;
3704 r.in.info = info;
3706 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3707 "SetDomainInfo failed");
3708 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3710 return true;
3713 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3714 struct torture_context *tctx,
3715 struct policy_handle *domain_handle,
3716 enum samr_DomainInfoClass level,
3717 union samr_DomainInfo **q_info)
3719 struct samr_QueryDomainInfo2 r;
3721 r.in.domain_handle = domain_handle;
3722 r.in.level = level;
3723 r.out.info = q_info;
3725 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3726 "failed to query domain info");
3727 torture_assert_ntstatus_ok(tctx, r.out.result,
3728 "failed to query domain info");
3730 return true;
3733 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3734 struct dcerpc_pipe *np,
3735 struct torture_context *tctx,
3736 uint32_t acct_flags,
3737 const char *acct_name,
3738 struct policy_handle *domain_handle,
3739 struct policy_handle *user_handle,
3740 char **password,
3741 struct cli_credentials *machine_credentials,
3742 const char *comment,
3743 bool disable,
3744 bool interactive,
3745 NTSTATUS expected_success_status,
3746 struct samr_DomInfo1 *info1,
3747 struct samr_DomInfo12 *info12)
3749 union samr_DomainInfo info;
3750 char **passwords;
3751 int i;
3752 uint32_t badpwdcount, tmp;
3753 uint32_t password_history_length = 12;
3754 uint32_t lockout_threshold = 15;
3755 struct dcerpc_binding_handle *b = p->binding_handle;
3757 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3759 torture_assert(tctx, password_history_length < lockout_threshold,
3760 "password history length needs to be smaller than account lockout threshold for this test");
3763 /* set policies */
3765 info.info1 = *info1;
3766 info.info1.password_history_length = password_history_length;
3768 torture_assert(tctx,
3769 test_SetDomainInfo(b, tctx, domain_handle,
3770 DomainPasswordInformation, &info),
3771 "failed to set password history length");
3773 info.info12 = *info12;
3774 info.info12.lockout_threshold = lockout_threshold;
3776 torture_assert(tctx,
3777 test_SetDomainInfo(b, tctx, domain_handle,
3778 DomainLockoutInformation, &info),
3779 "failed to set lockout threshold");
3781 /* reset bad pwd count */
3783 torture_assert(tctx,
3784 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3787 /* enable or disable account */
3788 if (disable) {
3789 torture_assert(tctx,
3790 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3791 acct_flags | ACB_DISABLED),
3792 "failed to disable user");
3793 } else {
3794 torture_assert(tctx,
3795 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3796 acct_flags & ~ACB_DISABLED),
3797 "failed to enable user");
3801 /* setup password history */
3803 passwords = talloc_array(tctx, char *, password_history_length);
3805 for (i=0; i < password_history_length; i++) {
3807 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3808 "failed to set password");
3809 passwords[i] = talloc_strdup(tctx, *password);
3811 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3812 acct_name, passwords[i],
3813 expected_success_status, interactive)) {
3814 torture_fail(tctx, "failed to auth with latest password");
3817 torture_assert(tctx,
3818 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3820 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3824 /* test with wrong password */
3826 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3827 acct_name, "random_crap",
3828 NT_STATUS_WRONG_PASSWORD, interactive)) {
3829 torture_fail(tctx, "succeeded to authenticate with wrong password");
3832 torture_assert(tctx,
3833 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3835 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3838 /* test with latest good password */
3840 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3841 passwords[password_history_length-1],
3842 expected_success_status, interactive)) {
3843 torture_fail(tctx, "succeeded to authenticate with wrong password");
3846 torture_assert(tctx,
3847 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3849 if (disable) {
3850 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3851 } else {
3852 /* only enabled accounts get the bad pwd count reset upon
3853 * successful logon */
3854 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3857 tmp = badpwdcount;
3860 /* test password history */
3862 for (i=0; i < password_history_length; i++) {
3864 torture_comment(tctx, "Testing bad password count behavior with "
3865 "password #%d of #%d\n", i, password_history_length);
3867 /* - network samlogon will succeed auth and not
3868 * increase badpwdcount for 2 last entries
3869 * - interactive samlogon only for the last one */
3871 if (i == password_history_length - 1 ||
3872 (i == password_history_length - 2 && !interactive)) {
3874 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3875 acct_name, passwords[i],
3876 expected_success_status, interactive)) {
3877 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3880 torture_assert(tctx,
3881 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3883 if (disable) {
3884 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3885 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3886 } else {
3887 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3888 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3891 tmp = badpwdcount;
3893 continue;
3896 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3897 acct_name, passwords[i],
3898 NT_STATUS_WRONG_PASSWORD, interactive)) {
3899 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3902 torture_assert(tctx,
3903 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3905 /* - network samlogon will fail auth but not increase
3906 * badpwdcount for 3rd last entry
3907 * - interactive samlogon for 3rd and 2nd last entry */
3909 if (i == password_history_length - 3 ||
3910 (i == password_history_length - 2 && interactive)) {
3911 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3912 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3913 } else {
3914 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3915 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3918 tmp = badpwdcount;
3921 return true;
3924 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3925 struct torture_context *tctx,
3926 uint32_t acct_flags,
3927 const char *acct_name,
3928 struct policy_handle *domain_handle,
3929 struct policy_handle *user_handle,
3930 char **password,
3931 struct cli_credentials *machine_credentials)
3933 union samr_DomainInfo *q_info, s_info;
3934 struct samr_DomInfo1 info1, _info1;
3935 struct samr_DomInfo12 info12, _info12;
3936 bool ret = true;
3937 struct dcerpc_binding_handle *b = p->binding_handle;
3938 struct dcerpc_pipe *np;
3939 int i;
3941 struct {
3942 const char *comment;
3943 bool disabled;
3944 bool interactive;
3945 NTSTATUS expected_success_status;
3946 } creds[] = {
3948 .comment = "network logon (disabled account)",
3949 .disabled = true,
3950 .interactive = false,
3951 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3954 .comment = "network logon (enabled account)",
3955 .disabled = false,
3956 .interactive = false,
3957 .expected_success_status= NT_STATUS_OK
3960 .comment = "interactive logon (disabled account)",
3961 .disabled = true,
3962 .interactive = true,
3963 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3966 .comment = "interactive logon (enabled account)",
3967 .disabled = false,
3968 .interactive = true,
3969 .expected_success_status= NT_STATUS_OK
3973 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3975 /* backup old policies */
3977 torture_assert(tctx,
3978 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3979 DomainPasswordInformation, &q_info),
3980 "failed to query domain info level 1");
3982 info1 = q_info->info1;
3983 _info1 = info1;
3985 torture_assert(tctx,
3986 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3987 DomainLockoutInformation, &q_info),
3988 "failed to query domain info level 12");
3990 info12 = q_info->info12;
3991 _info12 = info12;
3993 /* run tests */
3995 for (i=0; i < ARRAY_SIZE(creds); i++) {
3997 /* skip trust tests for now */
3998 if (acct_flags & ACB_WSTRUST ||
3999 acct_flags & ACB_SVRTRUST ||
4000 acct_flags & ACB_DOMTRUST) {
4001 continue;
4004 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4005 domain_handle, user_handle, password,
4006 machine_credentials,
4007 creds[i].comment,
4008 creds[i].disabled,
4009 creds[i].interactive,
4010 creds[i].expected_success_status,
4011 &_info1, &_info12);
4012 if (!ret) {
4013 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4014 } else {
4015 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4019 /* restore policies */
4021 s_info.info1 = info1;
4023 torture_assert(tctx,
4024 test_SetDomainInfo(b, tctx, domain_handle,
4025 DomainPasswordInformation, &s_info),
4026 "failed to set password information");
4028 s_info.info12 = info12;
4030 torture_assert(tctx,
4031 test_SetDomainInfo(b, tctx, domain_handle,
4032 DomainLockoutInformation, &s_info),
4033 "failed to set lockout information");
4035 return ret;
4038 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
4039 struct torture_context *tctx,
4040 struct policy_handle *handle,
4041 uint32_t *acct_flags)
4043 union samr_UserInfo *info;
4044 struct samr_QueryUserInfo r;
4046 r.in.user_handle = handle;
4047 r.in.level = 16;
4048 r.out.info = &info;
4050 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4052 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4053 "failed to query userinfo");
4054 torture_assert_ntstatus_ok(tctx, r.out.result,
4055 "failed to query userinfo");
4057 *acct_flags = info->info16.acct_flags;
4059 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
4061 return true;
4064 static bool test_Password_lockout(struct dcerpc_pipe *p,
4065 struct dcerpc_pipe *np,
4066 struct torture_context *tctx,
4067 uint32_t acct_flags,
4068 const char *acct_name,
4069 struct policy_handle *domain_handle,
4070 struct policy_handle *user_handle,
4071 char **password,
4072 struct cli_credentials *machine_credentials,
4073 const char *comment,
4074 bool disable,
4075 bool interactive,
4076 NTSTATUS expected_success_status,
4077 struct samr_DomInfo1 *info1,
4078 struct samr_DomInfo12 *info12)
4080 union samr_DomainInfo info;
4081 uint32_t badpwdcount;
4082 uint32_t password_history_length = 1;
4083 uint64_t lockout_threshold = 1;
4084 uint32_t lockout_seconds = 5;
4085 uint64_t delta_time_factor = 10 * 1000 * 1000;
4086 struct dcerpc_binding_handle *b = p->binding_handle;
4088 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4090 /* set policies */
4092 info.info1 = *info1;
4094 torture_comment(tctx, "setting password history length.\n");
4095 info.info1.password_history_length = password_history_length;
4097 torture_assert(tctx,
4098 test_SetDomainInfo(b, tctx, domain_handle,
4099 DomainPasswordInformation, &info),
4100 "failed to set password history length");
4102 info.info12 = *info12;
4103 info.info12.lockout_threshold = lockout_threshold;
4105 /* set lockout duration < lockout window: should fail */
4106 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4107 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4109 torture_assert(tctx,
4110 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4111 DomainLockoutInformation, &info,
4112 NT_STATUS_INVALID_PARAMETER),
4113 "setting lockout duration < lockout window gave unexpected result");
4115 info.info12.lockout_duration = 0;
4116 info.info12.lockout_window = 0;
4118 torture_assert(tctx,
4119 test_SetDomainInfo(b, tctx, domain_handle,
4120 DomainLockoutInformation, &info),
4121 "failed to set lockout window and duration to 0");
4124 /* set lockout duration of 5 seconds */
4125 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4126 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4128 torture_assert(tctx,
4129 test_SetDomainInfo(b, tctx, domain_handle,
4130 DomainLockoutInformation, &info),
4131 "failed to set lockout window and duration to 5 seconds");
4133 /* reset bad pwd count */
4135 torture_assert(tctx,
4136 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4139 /* enable or disable account */
4141 if (disable) {
4142 torture_assert(tctx,
4143 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4144 acct_flags | ACB_DISABLED),
4145 "failed to disable user");
4146 } else {
4147 torture_assert(tctx,
4148 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4149 acct_flags & ~ACB_DISABLED),
4150 "failed to enable user");
4154 /* test logon with right password */
4156 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4157 acct_name, *password,
4158 expected_success_status, interactive)) {
4159 torture_fail(tctx, "failed to auth with latest password");
4162 torture_assert(tctx,
4163 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4164 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4167 /* test with wrong password ==> lockout */
4169 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4170 acct_name, "random_crap",
4171 NT_STATUS_WRONG_PASSWORD, interactive)) {
4172 torture_fail(tctx, "succeeded to authenticate with wrong password");
4175 torture_assert(tctx,
4176 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4177 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4179 torture_assert(tctx,
4180 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4181 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4182 "expected account to be locked");
4185 /* test with good password */
4187 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4188 *password,
4189 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4191 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4194 /* bad pwd count should not get updated */
4195 torture_assert(tctx,
4196 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4197 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4199 /* curiously, windows does _not_ set the autlock flag */
4200 torture_assert(tctx,
4201 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4202 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4203 "expected account to be locked");
4206 /* with bad password */
4208 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4209 acct_name, "random_crap2",
4210 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4212 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4215 /* bad pwd count should not get updated */
4216 torture_assert(tctx,
4217 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4218 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4220 /* curiously, windows does _not_ set the autlock flag */
4221 torture_assert(tctx,
4222 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4223 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4224 "expected account to be locked");
4227 /* let lockout duration expire ==> unlock */
4229 torture_comment(tctx, "let lockout duration expire...\n");
4230 sleep(lockout_seconds + 1);
4232 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4233 *password,
4234 expected_success_status, interactive))
4236 torture_fail(tctx, "failed to authenticate after lockout expired");
4239 torture_assert(tctx,
4240 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4241 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4242 "expected account not to be locked");
4244 return true;
4247 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4248 struct torture_context *tctx,
4249 uint32_t acct_flags,
4250 const char *acct_name,
4251 struct policy_handle *domain_handle,
4252 struct policy_handle *user_handle,
4253 char **password,
4254 struct cli_credentials *machine_credentials)
4256 union samr_DomainInfo *q_info, s_info;
4257 struct samr_DomInfo1 info1, _info1;
4258 struct samr_DomInfo12 info12, _info12;
4259 bool ret = true;
4260 struct dcerpc_binding_handle *b = p->binding_handle;
4261 struct dcerpc_pipe *np;
4262 int i;
4264 struct {
4265 const char *comment;
4266 bool disabled;
4267 bool interactive;
4268 NTSTATUS expected_success_status;
4269 } creds[] = {
4271 .comment = "network logon (disabled account)",
4272 .disabled = true,
4273 .interactive = false,
4274 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4277 .comment = "network logon (enabled account)",
4278 .disabled = false,
4279 .interactive = false,
4280 .expected_success_status= NT_STATUS_OK
4283 .comment = "interactive logon (disabled account)",
4284 .disabled = true,
4285 .interactive = true,
4286 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4289 .comment = "interactive logon (enabled account)",
4290 .disabled = false,
4291 .interactive = true,
4292 .expected_success_status= NT_STATUS_OK
4296 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4298 /* backup old policies */
4300 torture_assert(tctx,
4301 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4302 DomainPasswordInformation, &q_info),
4303 "failed to query domain info level 1");
4305 info1 = q_info->info1;
4306 _info1 = info1;
4308 torture_assert(tctx,
4309 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4310 DomainLockoutInformation, &q_info),
4311 "failed to query domain info level 12");
4313 info12 = q_info->info12;
4314 _info12 = info12;
4316 /* run tests */
4318 for (i=0; i < ARRAY_SIZE(creds); i++) {
4320 /* skip trust tests for now */
4321 if (acct_flags & ACB_WSTRUST ||
4322 acct_flags & ACB_SVRTRUST ||
4323 acct_flags & ACB_DOMTRUST) {
4324 continue;
4327 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4328 domain_handle, user_handle, password,
4329 machine_credentials,
4330 creds[i].comment,
4331 creds[i].disabled,
4332 creds[i].interactive,
4333 creds[i].expected_success_status,
4334 &_info1, &_info12);
4335 if (!ret) {
4336 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4337 } else {
4338 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4342 /* restore policies */
4344 s_info.info1 = info1;
4346 torture_assert(tctx,
4347 test_SetDomainInfo(b, tctx, domain_handle,
4348 DomainPasswordInformation, &s_info),
4349 "failed to set password information");
4351 s_info.info12 = info12;
4353 torture_assert(tctx,
4354 test_SetDomainInfo(b, tctx, domain_handle,
4355 DomainLockoutInformation, &s_info),
4356 "failed to set lockout information");
4358 return ret;
4361 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4362 struct dcerpc_pipe *lp,
4363 struct torture_context *tctx,
4364 struct policy_handle *domain_handle,
4365 struct policy_handle *lsa_handle,
4366 struct policy_handle *user_handle,
4367 const struct dom_sid *domain_sid,
4368 uint32_t rid,
4369 struct cli_credentials *machine_credentials)
4371 bool ret = true;
4372 struct dcerpc_binding_handle *b = p->binding_handle;
4373 struct dcerpc_binding_handle *lb = lp->binding_handle;
4375 struct policy_handle lsa_acct_handle;
4376 struct dom_sid *user_sid;
4378 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4381 struct lsa_EnumAccountRights r;
4382 struct lsa_RightSet rights;
4384 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4386 r.in.handle = lsa_handle;
4387 r.in.sid = user_sid;
4388 r.out.rights = &rights;
4390 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4391 "lsa_EnumAccountRights failed");
4392 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4393 "Expected enum rights for account to fail");
4397 struct lsa_RightSet rights;
4398 struct lsa_StringLarge names[2];
4399 struct lsa_AddAccountRights r;
4401 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4403 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4404 init_lsa_StringLarge(&names[1], NULL);
4406 rights.count = 1;
4407 rights.names = names;
4409 r.in.handle = lsa_handle;
4410 r.in.sid = user_sid;
4411 r.in.rights = &rights;
4413 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4414 "lsa_AddAccountRights failed");
4415 torture_assert_ntstatus_ok(tctx, r.out.result,
4416 "Failed to add privileges");
4420 struct lsa_EnumAccounts r;
4421 uint32_t resume_handle = 0;
4422 struct lsa_SidArray lsa_sid_array;
4423 int i;
4424 bool found_sid = false;
4426 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4428 r.in.handle = lsa_handle;
4429 r.in.num_entries = 0x1000;
4430 r.in.resume_handle = &resume_handle;
4431 r.out.sids = &lsa_sid_array;
4432 r.out.resume_handle = &resume_handle;
4434 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4435 "lsa_EnumAccounts failed");
4436 torture_assert_ntstatus_ok(tctx, r.out.result,
4437 "Failed to enum accounts");
4439 for (i=0; i < lsa_sid_array.num_sids; i++) {
4440 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4441 found_sid = true;
4445 torture_assert(tctx, found_sid,
4446 "failed to list privileged account");
4450 struct lsa_EnumAccountRights r;
4451 struct lsa_RightSet user_rights;
4453 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4455 r.in.handle = lsa_handle;
4456 r.in.sid = user_sid;
4457 r.out.rights = &user_rights;
4459 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4460 "lsa_EnumAccountRights failed");
4461 torture_assert_ntstatus_ok(tctx, r.out.result,
4462 "Failed to enum rights for account");
4464 if (user_rights.count < 1) {
4465 torture_warning(tctx, "failed to find newly added rights");
4466 return false;
4471 struct lsa_OpenAccount r;
4473 torture_comment(tctx, "Testing LSA OpenAccount\n");
4475 r.in.handle = lsa_handle;
4476 r.in.sid = user_sid;
4477 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4478 r.out.acct_handle = &lsa_acct_handle;
4480 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4481 "lsa_OpenAccount failed");
4482 torture_assert_ntstatus_ok(tctx, r.out.result,
4483 "Failed to open lsa account");
4487 struct lsa_GetSystemAccessAccount r;
4488 uint32_t access_mask;
4490 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4492 r.in.handle = &lsa_acct_handle;
4493 r.out.access_mask = &access_mask;
4495 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4496 "lsa_GetSystemAccessAccount failed");
4497 torture_assert_ntstatus_ok(tctx, r.out.result,
4498 "Failed to get lsa system access account");
4502 struct lsa_Close r;
4504 torture_comment(tctx, "Testing LSA Close\n");
4506 r.in.handle = &lsa_acct_handle;
4507 r.out.handle = &lsa_acct_handle;
4509 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4510 "lsa_Close failed");
4511 torture_assert_ntstatus_ok(tctx, r.out.result,
4512 "Failed to close lsa");
4516 struct samr_DeleteUser r;
4518 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4520 r.in.user_handle = user_handle;
4521 r.out.user_handle = user_handle;
4523 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4524 "DeleteUser failed");
4525 torture_assert_ntstatus_ok(tctx, r.out.result,
4526 "DeleteUser failed");
4530 struct lsa_EnumAccounts r;
4531 uint32_t resume_handle = 0;
4532 struct lsa_SidArray lsa_sid_array;
4533 int i;
4534 bool found_sid = false;
4536 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4538 r.in.handle = lsa_handle;
4539 r.in.num_entries = 0x1000;
4540 r.in.resume_handle = &resume_handle;
4541 r.out.sids = &lsa_sid_array;
4542 r.out.resume_handle = &resume_handle;
4544 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4545 "lsa_EnumAccounts failed");
4546 torture_assert_ntstatus_ok(tctx, r.out.result,
4547 "Failed to enum accounts");
4549 for (i=0; i < lsa_sid_array.num_sids; i++) {
4550 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4551 found_sid = true;
4555 torture_assert(tctx, found_sid,
4556 "failed to list privileged account");
4560 struct lsa_EnumAccountRights r;
4561 struct lsa_RightSet user_rights;
4563 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4565 r.in.handle = lsa_handle;
4566 r.in.sid = user_sid;
4567 r.out.rights = &user_rights;
4569 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4570 "lsa_EnumAccountRights failed");
4571 torture_assert_ntstatus_ok(tctx, r.out.result,
4572 "Failed to enum rights for account");
4574 if (user_rights.count < 1) {
4575 torture_warning(tctx, "failed to find newly added rights");
4576 return false;
4581 struct lsa_OpenAccount r;
4583 torture_comment(tctx, "Testing LSA OpenAccount\n");
4585 r.in.handle = lsa_handle;
4586 r.in.sid = user_sid;
4587 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4588 r.out.acct_handle = &lsa_acct_handle;
4590 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4591 "lsa_OpenAccount failed");
4592 torture_assert_ntstatus_ok(tctx, r.out.result,
4593 "Failed to open lsa account");
4597 struct lsa_GetSystemAccessAccount r;
4598 uint32_t access_mask;
4600 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4602 r.in.handle = &lsa_acct_handle;
4603 r.out.access_mask = &access_mask;
4605 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4606 "lsa_GetSystemAccessAccount failed");
4607 torture_assert_ntstatus_ok(tctx, r.out.result,
4608 "Failed to get lsa system access account");
4612 struct lsa_DeleteObject r;
4614 torture_comment(tctx, "Testing LSA DeleteObject\n");
4616 r.in.handle = &lsa_acct_handle;
4617 r.out.handle = &lsa_acct_handle;
4619 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4620 "lsa_DeleteObject failed");
4621 torture_assert_ntstatus_ok(tctx, r.out.result,
4622 "Failed to delete object");
4626 struct lsa_EnumAccounts r;
4627 uint32_t resume_handle = 0;
4628 struct lsa_SidArray lsa_sid_array;
4629 int i;
4630 bool found_sid = false;
4632 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4634 r.in.handle = lsa_handle;
4635 r.in.num_entries = 0x1000;
4636 r.in.resume_handle = &resume_handle;
4637 r.out.sids = &lsa_sid_array;
4638 r.out.resume_handle = &resume_handle;
4640 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4641 "lsa_EnumAccounts failed");
4642 torture_assert_ntstatus_ok(tctx, r.out.result,
4643 "Failed to enum accounts");
4645 for (i=0; i < lsa_sid_array.num_sids; i++) {
4646 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4647 found_sid = true;
4651 torture_assert(tctx, !found_sid,
4652 "should not have listed privileged account");
4656 struct lsa_EnumAccountRights r;
4657 struct lsa_RightSet user_rights;
4659 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4661 r.in.handle = lsa_handle;
4662 r.in.sid = user_sid;
4663 r.out.rights = &user_rights;
4665 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4666 "lsa_EnumAccountRights failed");
4667 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4668 "Failed to enum rights for account");
4671 return ret;
4674 static bool test_user_ops(struct dcerpc_pipe *p,
4675 struct torture_context *tctx,
4676 struct policy_handle *user_handle,
4677 struct policy_handle *domain_handle,
4678 const struct dom_sid *domain_sid,
4679 uint32_t base_acct_flags,
4680 const char *base_acct_name, enum torture_samr_choice which_ops,
4681 struct cli_credentials *machine_credentials)
4683 char *password = NULL;
4684 struct samr_QueryUserInfo q;
4685 union samr_UserInfo *info;
4686 NTSTATUS status;
4687 struct dcerpc_binding_handle *b = p->binding_handle;
4689 bool ret = true;
4690 int i;
4691 uint32_t rid;
4692 const uint32_t password_fields[] = {
4693 SAMR_FIELD_NT_PASSWORD_PRESENT,
4694 SAMR_FIELD_LM_PASSWORD_PRESENT,
4695 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4699 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 ret = false;
4704 switch (which_ops) {
4705 case TORTURE_SAMR_USER_ATTRIBUTES:
4706 if (!test_QuerySecurity(b, tctx, user_handle)) {
4707 ret = false;
4710 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4711 ret = false;
4714 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4715 ret = false;
4718 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4719 base_acct_name)) {
4720 ret = false;
4723 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4724 ret = false;
4727 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4728 ret = false;
4731 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4732 ret = false;
4734 break;
4735 case TORTURE_SAMR_PASSWORDS:
4736 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4737 char simple_pass[9];
4738 char *v = generate_random_str(tctx, 1);
4740 ZERO_STRUCT(simple_pass);
4741 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4743 torture_comment(tctx, "Testing machine account password policy rules\n");
4745 /* Workstation trust accounts don't seem to need to honour password quality policy */
4746 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4747 ret = false;
4750 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4751 ret = false;
4754 /* reset again, to allow another 'user' password change */
4755 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4756 ret = false;
4759 /* Try a 'short' password */
4760 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4761 ret = false;
4764 /* Try a compleatly random password */
4765 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4766 ret = false;
4770 for (i = 0; password_fields[i]; i++) {
4771 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4772 ret = false;
4775 /* check it was set right */
4776 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4777 ret = false;
4781 for (i = 0; password_fields[i]; i++) {
4782 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4783 ret = false;
4786 /* check it was set right */
4787 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4788 ret = false;
4792 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4793 ret = false;
4796 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4797 ret = false;
4800 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4801 ret = false;
4804 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4805 ret = false;
4808 for (i = 0; password_fields[i]; i++) {
4810 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4811 /* we need to skip as that would break
4812 * the ChangePasswordUser3 verify */
4813 continue;
4816 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4817 ret = false;
4820 /* check it was set right */
4821 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4822 ret = false;
4826 q.in.user_handle = user_handle;
4827 q.in.level = 5;
4828 q.out.info = &info;
4830 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4831 "QueryUserInfo failed");
4832 if (!NT_STATUS_IS_OK(q.out.result)) {
4833 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4834 q.in.level, nt_errstr(q.out.result));
4835 ret = false;
4836 } else {
4837 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4838 if ((info->info5.acct_flags) != expected_flags) {
4839 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4840 info->info5.acct_flags,
4841 expected_flags);
4842 /* FIXME: GD */
4843 if (!torture_setting_bool(tctx, "samba3", false)) {
4844 ret = false;
4847 if (info->info5.rid != rid) {
4848 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4849 info->info5.rid, rid);
4854 break;
4856 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4858 /* test last password change timestamp behaviour */
4859 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4860 base_acct_name,
4861 user_handle, &password,
4862 machine_credentials)) {
4863 ret = false;
4866 if (ret == true) {
4867 torture_comment(tctx, "pwdLastSet test succeeded\n");
4868 } else {
4869 torture_warning(tctx, "pwdLastSet test failed\n");
4872 break;
4874 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4876 /* test bad pwd count change behaviour */
4877 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4878 base_acct_name,
4879 domain_handle,
4880 user_handle, &password,
4881 machine_credentials)) {
4882 ret = false;
4885 if (ret == true) {
4886 torture_comment(tctx, "badPwdCount test succeeded\n");
4887 } else {
4888 torture_warning(tctx, "badPwdCount test failed\n");
4891 break;
4893 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4895 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4896 base_acct_name,
4897 domain_handle,
4898 user_handle, &password,
4899 machine_credentials))
4901 ret = false;
4904 if (ret == true) {
4905 torture_comment(tctx, "lockout test succeeded\n");
4906 } else {
4907 torture_warning(tctx, "lockout test failed\n");
4910 break;
4913 case TORTURE_SAMR_USER_PRIVILEGES: {
4915 struct dcerpc_pipe *lp;
4916 struct policy_handle *lsa_handle;
4917 struct dcerpc_binding_handle *lb;
4919 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4920 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4921 lb = lp->binding_handle;
4923 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4924 ret = false;
4927 if (!test_DeleteUser_with_privs(p, lp, tctx,
4928 domain_handle, lsa_handle, user_handle,
4929 domain_sid, rid,
4930 machine_credentials)) {
4931 ret = false;
4934 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4935 ret = false;
4938 if (!ret) {
4939 torture_warning(tctx, "privileged user delete test failed\n");
4942 break;
4944 case TORTURE_SAMR_OTHER:
4945 case TORTURE_SAMR_MANY_ACCOUNTS:
4946 case TORTURE_SAMR_MANY_GROUPS:
4947 case TORTURE_SAMR_MANY_ALIASES:
4948 /* We just need the account to exist */
4949 break;
4951 return ret;
4954 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4955 struct torture_context *tctx,
4956 struct policy_handle *alias_handle,
4957 const struct dom_sid *domain_sid)
4959 bool ret = true;
4961 if (!torture_setting_bool(tctx, "samba3", false)) {
4962 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4963 ret = false;
4967 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4968 ret = false;
4971 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4972 ret = false;
4975 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
4976 ret = false;
4979 if (torture_setting_bool(tctx, "samba3", false) ||
4980 torture_setting_bool(tctx, "samba4", false)) {
4981 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4982 return ret;
4985 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
4986 ret = false;
4989 return ret;
4993 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
4994 struct torture_context *tctx,
4995 struct policy_handle *user_handle)
4997 struct samr_DeleteUser d;
4998 torture_comment(tctx, "Testing DeleteUser\n");
5000 d.in.user_handle = user_handle;
5001 d.out.user_handle = user_handle;
5003 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5004 "DeleteUser failed");
5005 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5007 return true;
5010 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5011 struct torture_context *tctx,
5012 struct policy_handle *handle, const char *name)
5014 NTSTATUS status;
5015 struct samr_DeleteUser d;
5016 struct policy_handle user_handle;
5017 uint32_t rid;
5019 status = test_LookupName(b, tctx, handle, name, &rid);
5020 if (!NT_STATUS_IS_OK(status)) {
5021 goto failed;
5024 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5025 if (!NT_STATUS_IS_OK(status)) {
5026 goto failed;
5029 d.in.user_handle = &user_handle;
5030 d.out.user_handle = &user_handle;
5031 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5032 "DeleteUser failed");
5033 if (!NT_STATUS_IS_OK(d.out.result)) {
5034 status = d.out.result;
5035 goto failed;
5038 return true;
5040 failed:
5041 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
5042 return false;
5046 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
5047 struct torture_context *tctx,
5048 struct policy_handle *handle, const char *name)
5050 NTSTATUS status;
5051 struct samr_OpenGroup r;
5052 struct samr_DeleteDomainGroup d;
5053 struct policy_handle group_handle;
5054 uint32_t rid;
5056 status = test_LookupName(b, tctx, handle, name, &rid);
5057 if (!NT_STATUS_IS_OK(status)) {
5058 goto failed;
5061 r.in.domain_handle = handle;
5062 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5063 r.in.rid = rid;
5064 r.out.group_handle = &group_handle;
5065 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5066 "OpenGroup failed");
5067 if (!NT_STATUS_IS_OK(r.out.result)) {
5068 status = r.out.result;
5069 goto failed;
5072 d.in.group_handle = &group_handle;
5073 d.out.group_handle = &group_handle;
5074 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
5075 "DeleteDomainGroup failed");
5076 if (!NT_STATUS_IS_OK(d.out.result)) {
5077 status = d.out.result;
5078 goto failed;
5081 return true;
5083 failed:
5084 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
5085 return false;
5089 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
5090 struct torture_context *tctx,
5091 struct policy_handle *domain_handle,
5092 const char *name)
5094 NTSTATUS status;
5095 struct samr_OpenAlias r;
5096 struct samr_DeleteDomAlias d;
5097 struct policy_handle alias_handle;
5098 uint32_t rid;
5100 torture_comment(tctx, "Testing DeleteAlias_byname\n");
5102 status = test_LookupName(b, tctx, domain_handle, name, &rid);
5103 if (!NT_STATUS_IS_OK(status)) {
5104 goto failed;
5107 r.in.domain_handle = domain_handle;
5108 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5109 r.in.rid = rid;
5110 r.out.alias_handle = &alias_handle;
5111 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5112 "OpenAlias failed");
5113 if (!NT_STATUS_IS_OK(r.out.result)) {
5114 status = r.out.result;
5115 goto failed;
5118 d.in.alias_handle = &alias_handle;
5119 d.out.alias_handle = &alias_handle;
5120 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5121 "DeleteDomAlias failed");
5122 if (!NT_STATUS_IS_OK(d.out.result)) {
5123 status = d.out.result;
5124 goto failed;
5127 return true;
5129 failed:
5130 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5131 return false;
5134 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5135 struct torture_context *tctx,
5136 struct policy_handle *alias_handle)
5138 struct samr_DeleteDomAlias d;
5139 bool ret = true;
5141 torture_comment(tctx, "Testing DeleteAlias\n");
5143 d.in.alias_handle = alias_handle;
5144 d.out.alias_handle = alias_handle;
5146 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5147 "DeleteDomAlias failed");
5148 if (!NT_STATUS_IS_OK(d.out.result)) {
5149 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5150 ret = false;
5153 return ret;
5156 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5157 struct torture_context *tctx,
5158 struct policy_handle *domain_handle,
5159 const char *alias_name,
5160 struct policy_handle *alias_handle,
5161 const struct dom_sid *domain_sid,
5162 bool test_alias)
5164 struct samr_CreateDomAlias r;
5165 struct lsa_String name;
5166 uint32_t rid;
5167 bool ret = true;
5169 init_lsa_String(&name, alias_name);
5170 r.in.domain_handle = domain_handle;
5171 r.in.alias_name = &name;
5172 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5173 r.out.alias_handle = alias_handle;
5174 r.out.rid = &rid;
5176 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5178 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5179 "CreateDomAlias failed");
5181 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5182 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5183 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5184 return true;
5185 } else {
5186 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5187 nt_errstr(r.out.result));
5188 return false;
5192 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5193 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5194 return false;
5196 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5197 "CreateDomAlias failed");
5200 if (!NT_STATUS_IS_OK(r.out.result)) {
5201 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5202 return false;
5205 if (!test_alias) {
5206 return ret;
5209 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5210 ret = false;
5213 return ret;
5216 static bool test_ChangePassword(struct dcerpc_pipe *p,
5217 struct torture_context *tctx,
5218 const char *acct_name,
5219 struct policy_handle *domain_handle, char **password)
5221 bool ret = true;
5222 struct dcerpc_binding_handle *b = p->binding_handle;
5224 if (!*password) {
5225 return false;
5228 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5229 ret = false;
5232 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5233 ret = false;
5236 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5237 ret = false;
5240 /* test what happens when setting the old password again */
5241 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5242 ret = false;
5246 char simple_pass[9];
5247 char *v = generate_random_str(tctx, 1);
5249 ZERO_STRUCT(simple_pass);
5250 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5252 /* test what happens when picking a simple password */
5253 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5254 ret = false;
5258 /* set samr_SetDomainInfo level 1 with min_length 5 */
5260 struct samr_QueryDomainInfo r;
5261 union samr_DomainInfo *info = NULL;
5262 struct samr_SetDomainInfo s;
5263 uint16_t len_old, len;
5264 uint32_t pwd_prop_old;
5265 int64_t min_pwd_age_old;
5267 len = 5;
5269 r.in.domain_handle = domain_handle;
5270 r.in.level = 1;
5271 r.out.info = &info;
5273 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5274 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5275 "QueryDomainInfo failed");
5276 if (!NT_STATUS_IS_OK(r.out.result)) {
5277 return false;
5280 s.in.domain_handle = domain_handle;
5281 s.in.level = 1;
5282 s.in.info = info;
5284 /* remember the old min length, so we can reset it */
5285 len_old = s.in.info->info1.min_password_length;
5286 s.in.info->info1.min_password_length = len;
5287 pwd_prop_old = s.in.info->info1.password_properties;
5288 /* turn off password complexity checks for this test */
5289 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5291 min_pwd_age_old = s.in.info->info1.min_password_age;
5292 s.in.info->info1.min_password_age = 0;
5294 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5295 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5296 "SetDomainInfo failed");
5297 if (!NT_STATUS_IS_OK(s.out.result)) {
5298 return false;
5301 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5303 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5304 ret = false;
5307 s.in.info->info1.min_password_length = len_old;
5308 s.in.info->info1.password_properties = pwd_prop_old;
5309 s.in.info->info1.min_password_age = min_pwd_age_old;
5311 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5312 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5313 "SetDomainInfo failed");
5314 if (!NT_STATUS_IS_OK(s.out.result)) {
5315 return false;
5321 struct samr_OpenUser r;
5322 struct samr_QueryUserInfo q;
5323 union samr_UserInfo *info;
5324 struct samr_LookupNames n;
5325 struct policy_handle user_handle;
5326 struct samr_Ids rids, types;
5328 n.in.domain_handle = domain_handle;
5329 n.in.num_names = 1;
5330 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5331 n.in.names[0].string = acct_name;
5332 n.out.rids = &rids;
5333 n.out.types = &types;
5335 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5336 "LookupNames failed");
5337 if (!NT_STATUS_IS_OK(n.out.result)) {
5338 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5339 return false;
5342 r.in.domain_handle = domain_handle;
5343 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5344 r.in.rid = n.out.rids->ids[0];
5345 r.out.user_handle = &user_handle;
5347 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5348 "OpenUser failed");
5349 if (!NT_STATUS_IS_OK(r.out.result)) {
5350 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5351 return false;
5354 q.in.user_handle = &user_handle;
5355 q.in.level = 5;
5356 q.out.info = &info;
5358 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5359 "QueryUserInfo failed");
5360 if (!NT_STATUS_IS_OK(q.out.result)) {
5361 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5362 return false;
5365 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5367 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5368 info->info5.last_password_change, true)) {
5369 ret = false;
5373 /* we change passwords twice - this has the effect of verifying
5374 they were changed correctly for the final call */
5375 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5376 ret = false;
5379 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5380 ret = false;
5383 return ret;
5386 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5387 struct policy_handle *domain_handle,
5388 const char *user_name,
5389 struct policy_handle *user_handle_out,
5390 struct dom_sid *domain_sid,
5391 enum torture_samr_choice which_ops,
5392 struct cli_credentials *machine_credentials,
5393 bool test_user)
5396 TALLOC_CTX *user_ctx;
5398 struct samr_CreateUser r;
5399 struct samr_QueryUserInfo q;
5400 union samr_UserInfo *info;
5401 struct samr_DeleteUser d;
5402 uint32_t rid;
5404 /* This call creates a 'normal' account - check that it really does */
5405 const uint32_t acct_flags = ACB_NORMAL;
5406 struct lsa_String name;
5407 bool ret = true;
5408 struct dcerpc_binding_handle *b = p->binding_handle;
5410 struct policy_handle user_handle;
5411 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5412 init_lsa_String(&name, user_name);
5414 r.in.domain_handle = domain_handle;
5415 r.in.account_name = &name;
5416 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5417 r.out.user_handle = &user_handle;
5418 r.out.rid = &rid;
5420 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5422 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5423 "CreateUser failed");
5425 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5426 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5427 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5428 return true;
5429 } else {
5430 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5431 nt_errstr(r.out.result));
5432 return false;
5436 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5437 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5438 talloc_free(user_ctx);
5439 return false;
5441 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5442 "CreateUser failed");
5445 if (!NT_STATUS_IS_OK(r.out.result)) {
5446 talloc_free(user_ctx);
5447 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5448 return false;
5451 if (!test_user) {
5452 if (user_handle_out) {
5453 *user_handle_out = user_handle;
5455 return ret;
5459 q.in.user_handle = &user_handle;
5460 q.in.level = 16;
5461 q.out.info = &info;
5463 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5464 "QueryUserInfo failed");
5465 if (!NT_STATUS_IS_OK(q.out.result)) {
5466 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5467 q.in.level, nt_errstr(q.out.result));
5468 ret = false;
5469 } else {
5470 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5471 torture_warning(tctx, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5472 info->info16.acct_flags,
5473 acct_flags);
5474 ret = false;
5478 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5479 domain_sid, acct_flags, name.string, which_ops,
5480 machine_credentials)) {
5481 ret = false;
5484 if (user_handle_out) {
5485 *user_handle_out = user_handle;
5486 } else {
5487 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5489 d.in.user_handle = &user_handle;
5490 d.out.user_handle = &user_handle;
5492 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5493 "DeleteUser failed");
5494 if (!NT_STATUS_IS_OK(d.out.result)) {
5495 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5496 ret = false;
5502 talloc_free(user_ctx);
5504 return ret;
5508 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5509 struct policy_handle *domain_handle,
5510 struct dom_sid *domain_sid,
5511 enum torture_samr_choice which_ops,
5512 struct cli_credentials *machine_credentials)
5514 struct samr_CreateUser2 r;
5515 struct samr_QueryUserInfo q;
5516 union samr_UserInfo *info;
5517 struct samr_DeleteUser d;
5518 struct policy_handle user_handle;
5519 uint32_t rid;
5520 struct lsa_String name;
5521 bool ret = true;
5522 int i;
5523 struct dcerpc_binding_handle *b = p->binding_handle;
5525 struct {
5526 uint32_t acct_flags;
5527 const char *account_name;
5528 NTSTATUS nt_status;
5529 } account_types[] = {
5530 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5531 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5532 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5533 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5534 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5535 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5536 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5537 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5538 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5539 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5540 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5541 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5542 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5543 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5544 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5547 for (i = 0; account_types[i].account_name; i++) {
5548 TALLOC_CTX *user_ctx;
5549 uint32_t acct_flags = account_types[i].acct_flags;
5550 uint32_t access_granted;
5551 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5552 init_lsa_String(&name, account_types[i].account_name);
5554 r.in.domain_handle = domain_handle;
5555 r.in.account_name = &name;
5556 r.in.acct_flags = acct_flags;
5557 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5558 r.out.user_handle = &user_handle;
5559 r.out.access_granted = &access_granted;
5560 r.out.rid = &rid;
5562 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5564 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5565 "CreateUser2 failed");
5567 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5568 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5569 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5570 continue;
5571 } else {
5572 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5573 nt_errstr(r.out.result));
5574 ret = false;
5575 continue;
5579 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5580 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5581 talloc_free(user_ctx);
5582 ret = false;
5583 continue;
5585 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5586 "CreateUser2 failed");
5589 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5590 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5591 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5592 ret = false;
5595 if (NT_STATUS_IS_OK(r.out.result)) {
5596 q.in.user_handle = &user_handle;
5597 q.in.level = 5;
5598 q.out.info = &info;
5600 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5601 "QueryUserInfo failed");
5602 if (!NT_STATUS_IS_OK(q.out.result)) {
5603 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5604 q.in.level, nt_errstr(q.out.result));
5605 ret = false;
5606 } else {
5607 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5608 if (acct_flags == ACB_NORMAL) {
5609 expected_flags |= ACB_PW_EXPIRED;
5611 if ((info->info5.acct_flags) != expected_flags) {
5612 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5613 info->info5.acct_flags,
5614 expected_flags);
5615 ret = false;
5617 switch (acct_flags) {
5618 case ACB_SVRTRUST:
5619 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5620 torture_warning(tctx, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5621 DOMAIN_RID_DCS, info->info5.primary_gid);
5622 ret = false;
5624 break;
5625 case ACB_WSTRUST:
5626 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5627 torture_warning(tctx, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5628 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5629 ret = false;
5631 break;
5632 case ACB_NORMAL:
5633 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5634 torture_warning(tctx, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5635 DOMAIN_RID_USERS, info->info5.primary_gid);
5636 ret = false;
5638 break;
5642 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5643 domain_sid, acct_flags, name.string, which_ops,
5644 machine_credentials)) {
5645 ret = false;
5648 if (!ndr_policy_handle_empty(&user_handle)) {
5649 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5651 d.in.user_handle = &user_handle;
5652 d.out.user_handle = &user_handle;
5654 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5655 "DeleteUser failed");
5656 if (!NT_STATUS_IS_OK(d.out.result)) {
5657 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5658 ret = false;
5662 talloc_free(user_ctx);
5665 return ret;
5668 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5669 struct torture_context *tctx,
5670 struct policy_handle *handle)
5672 struct samr_QueryAliasInfo r;
5673 union samr_AliasInfo *info;
5674 uint16_t levels[] = {1, 2, 3};
5675 int i;
5676 bool ret = true;
5678 for (i=0;i<ARRAY_SIZE(levels);i++) {
5679 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5681 r.in.alias_handle = handle;
5682 r.in.level = levels[i];
5683 r.out.info = &info;
5685 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5686 "QueryAliasInfo failed");
5687 if (!NT_STATUS_IS_OK(r.out.result)) {
5688 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5689 levels[i], nt_errstr(r.out.result));
5690 ret = false;
5694 return ret;
5697 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5698 struct torture_context *tctx,
5699 struct policy_handle *handle)
5701 struct samr_QueryGroupInfo r;
5702 union samr_GroupInfo *info;
5703 uint16_t levels[] = {1, 2, 3, 4, 5};
5704 int i;
5705 bool ret = true;
5707 for (i=0;i<ARRAY_SIZE(levels);i++) {
5708 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5710 r.in.group_handle = handle;
5711 r.in.level = levels[i];
5712 r.out.info = &info;
5714 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5715 "QueryGroupInfo failed");
5716 if (!NT_STATUS_IS_OK(r.out.result)) {
5717 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5718 levels[i], nt_errstr(r.out.result));
5719 ret = false;
5723 return ret;
5726 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5727 struct torture_context *tctx,
5728 struct policy_handle *handle)
5730 struct samr_QueryGroupMember r;
5731 struct samr_RidAttrArray *rids = NULL;
5732 bool ret = true;
5734 torture_comment(tctx, "Testing QueryGroupMember\n");
5736 r.in.group_handle = handle;
5737 r.out.rids = &rids;
5739 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5740 "QueryGroupMember failed");
5741 if (!NT_STATUS_IS_OK(r.out.result)) {
5742 torture_warning(tctx, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
5743 ret = false;
5746 return ret;
5750 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5751 struct torture_context *tctx,
5752 struct policy_handle *handle)
5754 struct samr_QueryGroupInfo r;
5755 union samr_GroupInfo *info;
5756 struct samr_SetGroupInfo s;
5757 uint16_t levels[] = {1, 2, 3, 4};
5758 uint16_t set_ok[] = {0, 1, 1, 1};
5759 int i;
5760 bool ret = true;
5762 for (i=0;i<ARRAY_SIZE(levels);i++) {
5763 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5765 r.in.group_handle = handle;
5766 r.in.level = levels[i];
5767 r.out.info = &info;
5769 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5770 "QueryGroupInfo failed");
5771 if (!NT_STATUS_IS_OK(r.out.result)) {
5772 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5773 levels[i], nt_errstr(r.out.result));
5774 ret = false;
5777 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5779 s.in.group_handle = handle;
5780 s.in.level = levels[i];
5781 s.in.info = *r.out.info;
5783 #if 0
5784 /* disabled this, as it changes the name only from the point of view of samr,
5785 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5786 the name is still reserved, so creating the old name fails, but deleting by the old name
5787 also fails */
5788 if (s.in.level == 2) {
5789 init_lsa_String(&s.in.info->string, "NewName");
5791 #endif
5793 if (s.in.level == 4) {
5794 init_lsa_String(&s.in.info->description, "test description");
5797 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5798 "SetGroupInfo failed");
5799 if (set_ok[i]) {
5800 if (!NT_STATUS_IS_OK(s.out.result)) {
5801 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5802 r.in.level, nt_errstr(s.out.result));
5803 ret = false;
5804 continue;
5806 } else {
5807 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5808 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5809 r.in.level, nt_errstr(s.out.result));
5810 ret = false;
5811 continue;
5816 return ret;
5819 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5820 struct torture_context *tctx,
5821 struct policy_handle *handle)
5823 struct samr_QueryUserInfo r;
5824 union samr_UserInfo *info;
5825 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5826 11, 12, 13, 14, 16, 17, 20, 21};
5827 int i;
5828 bool ret = true;
5830 for (i=0;i<ARRAY_SIZE(levels);i++) {
5831 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5833 r.in.user_handle = handle;
5834 r.in.level = levels[i];
5835 r.out.info = &info;
5837 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5838 "QueryUserInfo failed");
5839 if (!NT_STATUS_IS_OK(r.out.result)) {
5840 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5841 levels[i], nt_errstr(r.out.result));
5842 ret = false;
5846 return ret;
5849 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5850 struct torture_context *tctx,
5851 struct policy_handle *handle)
5853 struct samr_QueryUserInfo2 r;
5854 union samr_UserInfo *info;
5855 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5856 11, 12, 13, 14, 16, 17, 20, 21};
5857 int i;
5858 bool ret = true;
5860 for (i=0;i<ARRAY_SIZE(levels);i++) {
5861 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5863 r.in.user_handle = handle;
5864 r.in.level = levels[i];
5865 r.out.info = &info;
5867 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5868 "QueryUserInfo2 failed");
5869 if (!NT_STATUS_IS_OK(r.out.result)) {
5870 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5871 levels[i], nt_errstr(r.out.result));
5872 ret = false;
5876 return ret;
5879 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5880 struct torture_context *tctx,
5881 struct policy_handle *handle, uint32_t rid)
5883 struct samr_OpenUser r;
5884 struct policy_handle user_handle;
5885 bool ret = true;
5887 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5889 r.in.domain_handle = handle;
5890 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5891 r.in.rid = rid;
5892 r.out.user_handle = &user_handle;
5894 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5895 "OpenUser failed");
5896 if (!NT_STATUS_IS_OK(r.out.result)) {
5897 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5898 return false;
5901 if (!test_QuerySecurity(b, tctx, &user_handle)) {
5902 ret = false;
5905 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5906 ret = false;
5909 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5910 ret = false;
5913 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5914 ret = false;
5917 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5918 ret = false;
5921 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5922 ret = false;
5925 return ret;
5928 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5929 struct torture_context *tctx,
5930 struct policy_handle *handle, uint32_t rid)
5932 struct samr_OpenGroup r;
5933 struct policy_handle group_handle;
5934 bool ret = true;
5936 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5938 r.in.domain_handle = handle;
5939 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5940 r.in.rid = rid;
5941 r.out.group_handle = &group_handle;
5943 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5944 "OpenGroup failed");
5945 if (!NT_STATUS_IS_OK(r.out.result)) {
5946 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5947 return false;
5950 if (!torture_setting_bool(tctx, "samba3", false)) {
5951 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5952 ret = false;
5956 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5957 ret = false;
5960 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5961 ret = false;
5964 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5965 ret = false;
5968 return ret;
5971 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5972 struct torture_context *tctx,
5973 struct policy_handle *handle, uint32_t rid)
5975 struct samr_OpenAlias r;
5976 struct policy_handle alias_handle;
5977 bool ret = true;
5979 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5981 r.in.domain_handle = handle;
5982 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5983 r.in.rid = rid;
5984 r.out.alias_handle = &alias_handle;
5986 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5987 "OpenAlias failed");
5988 if (!NT_STATUS_IS_OK(r.out.result)) {
5989 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5990 return false;
5993 if (!torture_setting_bool(tctx, "samba3", false)) {
5994 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
5995 ret = false;
5999 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6000 ret = false;
6003 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6004 ret = false;
6007 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6008 ret = false;
6011 return ret;
6014 static bool check_mask(struct dcerpc_binding_handle *b,
6015 struct torture_context *tctx,
6016 struct policy_handle *handle, uint32_t rid,
6017 uint32_t acct_flag_mask)
6019 struct samr_OpenUser r;
6020 struct samr_QueryUserInfo q;
6021 union samr_UserInfo *info;
6022 struct policy_handle user_handle;
6023 bool ret = true;
6025 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6027 r.in.domain_handle = handle;
6028 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6029 r.in.rid = rid;
6030 r.out.user_handle = &user_handle;
6032 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6033 "OpenUser failed");
6034 if (!NT_STATUS_IS_OK(r.out.result)) {
6035 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6036 return false;
6039 q.in.user_handle = &user_handle;
6040 q.in.level = 16;
6041 q.out.info = &info;
6043 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6044 "QueryUserInfo failed");
6045 if (!NT_STATUS_IS_OK(q.out.result)) {
6046 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
6047 nt_errstr(q.out.result));
6048 ret = false;
6049 } else {
6050 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
6051 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
6052 acct_flag_mask, info->info16.acct_flags, rid);
6053 ret = false;
6057 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6058 ret = false;
6061 return ret;
6064 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
6065 struct torture_context *tctx,
6066 struct policy_handle *handle)
6068 struct samr_EnumDomainUsers r;
6069 uint32_t mask, resume_handle=0;
6070 int i, mask_idx;
6071 bool ret = true;
6072 struct samr_LookupNames n;
6073 struct samr_LookupRids lr ;
6074 struct lsa_Strings names;
6075 struct samr_Ids rids, types;
6076 struct samr_SamArray *sam = NULL;
6077 uint32_t num_entries = 0;
6079 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
6080 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
6081 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
6082 ACB_PWNOEXP, 0};
6084 torture_comment(tctx, "Testing EnumDomainUsers\n");
6086 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
6087 r.in.domain_handle = handle;
6088 r.in.resume_handle = &resume_handle;
6089 r.in.acct_flags = mask = masks[mask_idx];
6090 r.in.max_size = (uint32_t)-1;
6091 r.out.resume_handle = &resume_handle;
6092 r.out.num_entries = &num_entries;
6093 r.out.sam = &sam;
6095 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
6096 "EnumDomainUsers failed");
6097 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6098 !NT_STATUS_IS_OK(r.out.result)) {
6099 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
6100 return false;
6103 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6105 if (sam->count == 0) {
6106 continue;
6109 for (i=0;i<sam->count;i++) {
6110 if (mask) {
6111 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6112 ret = false;
6114 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6115 ret = false;
6120 torture_comment(tctx, "Testing LookupNames\n");
6121 n.in.domain_handle = handle;
6122 n.in.num_names = sam->count;
6123 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6124 n.out.rids = &rids;
6125 n.out.types = &types;
6126 for (i=0;i<sam->count;i++) {
6127 n.in.names[i].string = sam->entries[i].name.string;
6129 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6130 "LookupNames failed");
6131 if (!NT_STATUS_IS_OK(n.out.result)) {
6132 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6133 ret = false;
6137 torture_comment(tctx, "Testing LookupRids\n");
6138 lr.in.domain_handle = handle;
6139 lr.in.num_rids = sam->count;
6140 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6141 lr.out.names = &names;
6142 lr.out.types = &types;
6143 for (i=0;i<sam->count;i++) {
6144 lr.in.rids[i] = sam->entries[i].idx;
6146 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6147 "LookupRids failed");
6148 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6150 return ret;
6154 try blasting the server with a bunch of sync requests
6156 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6157 struct policy_handle *handle)
6159 struct samr_EnumDomainUsers r;
6160 uint32_t resume_handle=0;
6161 int i;
6162 #define ASYNC_COUNT 100
6163 struct tevent_req *req[ASYNC_COUNT];
6165 if (!torture_setting_bool(tctx, "dangerous", false)) {
6166 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6169 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6171 r.in.domain_handle = handle;
6172 r.in.resume_handle = &resume_handle;
6173 r.in.acct_flags = 0;
6174 r.in.max_size = (uint32_t)-1;
6175 r.out.resume_handle = &resume_handle;
6177 for (i=0;i<ASYNC_COUNT;i++) {
6178 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6181 for (i=0;i<ASYNC_COUNT;i++) {
6182 tevent_req_poll(req[i], tctx->ev);
6183 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6184 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6185 i, nt_errstr(r.out.result)));
6188 torture_comment(tctx, "%d async requests OK\n", i);
6190 return true;
6193 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6194 struct torture_context *tctx,
6195 struct policy_handle *handle)
6197 struct samr_EnumDomainGroups r;
6198 uint32_t resume_handle=0;
6199 struct samr_SamArray *sam = NULL;
6200 uint32_t num_entries = 0;
6201 int i;
6202 bool ret = true;
6203 bool universal_group_found = false;
6205 torture_comment(tctx, "Testing EnumDomainGroups\n");
6207 r.in.domain_handle = handle;
6208 r.in.resume_handle = &resume_handle;
6209 r.in.max_size = (uint32_t)-1;
6210 r.out.resume_handle = &resume_handle;
6211 r.out.num_entries = &num_entries;
6212 r.out.sam = &sam;
6214 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6215 "EnumDomainGroups failed");
6216 if (!NT_STATUS_IS_OK(r.out.result)) {
6217 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6218 return false;
6221 if (!sam) {
6222 return false;
6225 for (i=0;i<sam->count;i++) {
6226 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6227 ret = false;
6229 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6230 "Enterprise Admins") == 0)) {
6231 universal_group_found = true;
6235 /* when we are running this on s4 we should get back at least the
6236 * "Enterprise Admins" universal group. If we don't get a group entry
6237 * at all we probably are performing the test on the builtin domain.
6238 * So ignore this case. */
6239 if (torture_setting_bool(tctx, "samba4", false)) {
6240 if ((sam->count > 0) && (!universal_group_found)) {
6241 ret = false;
6245 return ret;
6248 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6249 struct torture_context *tctx,
6250 struct policy_handle *handle)
6252 struct samr_EnumDomainAliases r;
6253 uint32_t resume_handle=0;
6254 struct samr_SamArray *sam = NULL;
6255 uint32_t num_entries = 0;
6256 int i;
6257 bool ret = true;
6259 torture_comment(tctx, "Testing EnumDomainAliases\n");
6261 r.in.domain_handle = handle;
6262 r.in.resume_handle = &resume_handle;
6263 r.in.max_size = (uint32_t)-1;
6264 r.out.sam = &sam;
6265 r.out.num_entries = &num_entries;
6266 r.out.resume_handle = &resume_handle;
6268 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6269 "EnumDomainAliases failed");
6270 if (!NT_STATUS_IS_OK(r.out.result)) {
6271 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6272 return false;
6275 if (!sam) {
6276 return false;
6279 for (i=0;i<sam->count;i++) {
6280 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6281 ret = false;
6285 return ret;
6288 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6289 struct torture_context *tctx,
6290 struct policy_handle *handle)
6292 struct samr_GetDisplayEnumerationIndex r;
6293 bool ret = true;
6294 uint16_t levels[] = {1, 2, 3, 4, 5};
6295 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6296 struct lsa_String name;
6297 uint32_t idx = 0;
6298 int i;
6300 for (i=0;i<ARRAY_SIZE(levels);i++) {
6301 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6303 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6305 r.in.domain_handle = handle;
6306 r.in.level = levels[i];
6307 r.in.name = &name;
6308 r.out.idx = &idx;
6310 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6311 "GetDisplayEnumerationIndex failed");
6313 if (ok_lvl[i] &&
6314 !NT_STATUS_IS_OK(r.out.result) &&
6315 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6316 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6317 levels[i], nt_errstr(r.out.result));
6318 ret = false;
6321 init_lsa_String(&name, "zzzzzzzz");
6323 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6324 "GetDisplayEnumerationIndex failed");
6326 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6327 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6328 levels[i], nt_errstr(r.out.result));
6329 ret = false;
6333 return ret;
6336 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6337 struct torture_context *tctx,
6338 struct policy_handle *handle)
6340 struct samr_GetDisplayEnumerationIndex2 r;
6341 bool ret = true;
6342 uint16_t levels[] = {1, 2, 3, 4, 5};
6343 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6344 struct lsa_String name;
6345 uint32_t idx = 0;
6346 int i;
6348 for (i=0;i<ARRAY_SIZE(levels);i++) {
6349 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6351 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6353 r.in.domain_handle = handle;
6354 r.in.level = levels[i];
6355 r.in.name = &name;
6356 r.out.idx = &idx;
6358 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6359 "GetDisplayEnumerationIndex2 failed");
6360 if (ok_lvl[i] &&
6361 !NT_STATUS_IS_OK(r.out.result) &&
6362 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6363 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6364 levels[i], nt_errstr(r.out.result));
6365 ret = false;
6368 init_lsa_String(&name, "zzzzzzzz");
6370 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6371 "GetDisplayEnumerationIndex2 failed");
6372 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6373 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6374 levels[i], nt_errstr(r.out.result));
6375 ret = false;
6379 return ret;
6382 #define STRING_EQUAL_QUERY(s1, s2, user) \
6383 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6384 /* odd, but valid */ \
6385 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6386 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6387 #s1, user.string, s1.string, s2.string, __location__); \
6388 ret = false; \
6390 #define INT_EQUAL_QUERY(s1, s2, user) \
6391 if (s1 != s2) { \
6392 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6393 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6394 ret = false; \
6397 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6398 struct torture_context *tctx,
6399 struct samr_QueryDisplayInfo *querydisplayinfo,
6400 bool *seen_testuser)
6402 struct samr_OpenUser r;
6403 struct samr_QueryUserInfo q;
6404 union samr_UserInfo *info;
6405 struct policy_handle user_handle;
6406 int i, ret = true;
6407 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6408 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6409 for (i = 0; ; i++) {
6410 switch (querydisplayinfo->in.level) {
6411 case 1:
6412 if (i >= querydisplayinfo->out.info->info1.count) {
6413 return ret;
6415 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6416 break;
6417 case 2:
6418 if (i >= querydisplayinfo->out.info->info2.count) {
6419 return ret;
6421 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6422 break;
6423 case 3:
6424 /* Groups */
6425 case 4:
6426 case 5:
6427 /* Not interested in validating just the account name */
6428 return true;
6431 r.out.user_handle = &user_handle;
6433 switch (querydisplayinfo->in.level) {
6434 case 1:
6435 case 2:
6436 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6437 "OpenUser failed");
6438 if (!NT_STATUS_IS_OK(r.out.result)) {
6439 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6440 return false;
6444 q.in.user_handle = &user_handle;
6445 q.in.level = 21;
6446 q.out.info = &info;
6447 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6448 "QueryUserInfo failed");
6449 if (!NT_STATUS_IS_OK(r.out.result)) {
6450 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6451 return false;
6454 switch (querydisplayinfo->in.level) {
6455 case 1:
6456 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6457 *seen_testuser = true;
6459 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6460 info->info21.full_name, info->info21.account_name);
6461 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6462 info->info21.account_name, info->info21.account_name);
6463 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6464 info->info21.description, info->info21.account_name);
6465 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6466 info->info21.rid, info->info21.account_name);
6467 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6468 info->info21.acct_flags, info->info21.account_name);
6470 break;
6471 case 2:
6472 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6473 info->info21.account_name, info->info21.account_name);
6474 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6475 info->info21.description, info->info21.account_name);
6476 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6477 info->info21.rid, info->info21.account_name);
6478 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6479 info->info21.acct_flags, info->info21.account_name);
6481 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6482 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6483 info->info21.account_name.string);
6486 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6487 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6488 info->info21.account_name.string,
6489 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6490 info->info21.acct_flags);
6491 return false;
6494 break;
6497 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6498 return false;
6501 return ret;
6504 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6505 struct torture_context *tctx,
6506 struct policy_handle *handle)
6508 struct samr_QueryDisplayInfo r;
6509 struct samr_QueryDomainInfo dom_info;
6510 union samr_DomainInfo *info = NULL;
6511 bool ret = true;
6512 uint16_t levels[] = {1, 2, 3, 4, 5};
6513 int i;
6514 bool seen_testuser = false;
6515 uint32_t total_size;
6516 uint32_t returned_size;
6517 union samr_DispInfo disp_info;
6520 for (i=0;i<ARRAY_SIZE(levels);i++) {
6521 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6523 r.in.start_idx = 0;
6524 r.out.result = STATUS_MORE_ENTRIES;
6525 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6526 r.in.domain_handle = handle;
6527 r.in.level = levels[i];
6528 r.in.max_entries = 2;
6529 r.in.buf_size = (uint32_t)-1;
6530 r.out.total_size = &total_size;
6531 r.out.returned_size = &returned_size;
6532 r.out.info = &disp_info;
6534 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6535 "QueryDisplayInfo failed");
6536 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6537 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6538 levels[i], nt_errstr(r.out.result));
6539 ret = false;
6541 switch (r.in.level) {
6542 case 1:
6543 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6544 ret = false;
6546 r.in.start_idx += r.out.info->info1.count;
6547 break;
6548 case 2:
6549 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6550 ret = false;
6552 r.in.start_idx += r.out.info->info2.count;
6553 break;
6554 case 3:
6555 r.in.start_idx += r.out.info->info3.count;
6556 break;
6557 case 4:
6558 r.in.start_idx += r.out.info->info4.count;
6559 break;
6560 case 5:
6561 r.in.start_idx += r.out.info->info5.count;
6562 break;
6565 dom_info.in.domain_handle = handle;
6566 dom_info.in.level = 2;
6567 dom_info.out.info = &info;
6569 /* Check number of users returned is correct */
6570 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6571 "QueryDomainInfo failed");
6572 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6573 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6574 r.in.level, nt_errstr(dom_info.out.result));
6575 ret = false;
6576 break;
6578 switch (r.in.level) {
6579 case 1:
6580 case 4:
6581 if (info->general.num_users < r.in.start_idx) {
6582 /* On AD deployments this numbers don't match
6583 * since QueryDisplayInfo returns universal and
6584 * global groups, QueryDomainInfo only global
6585 * ones. */
6586 if (torture_setting_bool(tctx, "samba3", false)) {
6587 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6588 r.in.start_idx, info->general.num_groups,
6589 info->general.domain_name.string);
6590 ret = false;
6593 if (!seen_testuser) {
6594 struct policy_handle user_handle;
6595 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6596 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6597 info->general.domain_name.string);
6598 ret = false;
6599 test_samr_handle_Close(b, tctx, &user_handle);
6602 break;
6603 case 3:
6604 case 5:
6605 if (info->general.num_groups != r.in.start_idx) {
6606 /* On AD deployments this numbers don't match
6607 * since QueryDisplayInfo returns universal and
6608 * global groups, QueryDomainInfo only global
6609 * ones. */
6610 if (torture_setting_bool(tctx, "samba3", false)) {
6611 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6612 r.in.start_idx, info->general.num_groups,
6613 info->general.domain_name.string);
6614 ret = false;
6618 break;
6623 return ret;
6626 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6627 struct torture_context *tctx,
6628 struct policy_handle *handle)
6630 struct samr_QueryDisplayInfo2 r;
6631 bool ret = true;
6632 uint16_t levels[] = {1, 2, 3, 4, 5};
6633 int i;
6634 uint32_t total_size;
6635 uint32_t returned_size;
6636 union samr_DispInfo info;
6638 for (i=0;i<ARRAY_SIZE(levels);i++) {
6639 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6641 r.in.domain_handle = handle;
6642 r.in.level = levels[i];
6643 r.in.start_idx = 0;
6644 r.in.max_entries = 1000;
6645 r.in.buf_size = (uint32_t)-1;
6646 r.out.total_size = &total_size;
6647 r.out.returned_size = &returned_size;
6648 r.out.info = &info;
6650 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6651 "QueryDisplayInfo2 failed");
6652 if (!NT_STATUS_IS_OK(r.out.result)) {
6653 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6654 levels[i], nt_errstr(r.out.result));
6655 ret = false;
6659 return ret;
6662 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6663 struct torture_context *tctx,
6664 struct policy_handle *handle)
6666 struct samr_QueryDisplayInfo3 r;
6667 bool ret = true;
6668 uint16_t levels[] = {1, 2, 3, 4, 5};
6669 int i;
6670 uint32_t total_size;
6671 uint32_t returned_size;
6672 union samr_DispInfo info;
6674 for (i=0;i<ARRAY_SIZE(levels);i++) {
6675 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6677 r.in.domain_handle = handle;
6678 r.in.level = levels[i];
6679 r.in.start_idx = 0;
6680 r.in.max_entries = 1000;
6681 r.in.buf_size = (uint32_t)-1;
6682 r.out.total_size = &total_size;
6683 r.out.returned_size = &returned_size;
6684 r.out.info = &info;
6686 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6687 "QueryDisplayInfo3 failed");
6688 if (!NT_STATUS_IS_OK(r.out.result)) {
6689 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6690 levels[i], nt_errstr(r.out.result));
6691 ret = false;
6695 return ret;
6699 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6700 struct torture_context *tctx,
6701 struct policy_handle *handle)
6703 struct samr_QueryDisplayInfo r;
6704 bool ret = true;
6705 uint32_t total_size;
6706 uint32_t returned_size;
6707 union samr_DispInfo info;
6709 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6711 r.in.domain_handle = handle;
6712 r.in.level = 1;
6713 r.in.start_idx = 0;
6714 r.in.max_entries = 1;
6715 r.in.buf_size = (uint32_t)-1;
6716 r.out.total_size = &total_size;
6717 r.out.returned_size = &returned_size;
6718 r.out.info = &info;
6720 do {
6721 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6722 "QueryDisplayInfo failed");
6723 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6724 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6725 torture_warning(tctx, "expected idx %d but got %d\n",
6726 r.in.start_idx + 1,
6727 r.out.info->info1.entries[0].idx);
6728 break;
6731 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6732 !NT_STATUS_IS_OK(r.out.result)) {
6733 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6734 r.in.level, nt_errstr(r.out.result));
6735 ret = false;
6736 break;
6738 r.in.start_idx++;
6739 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6740 NT_STATUS_IS_OK(r.out.result)) &&
6741 *r.out.returned_size != 0);
6743 return ret;
6746 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6747 struct torture_context *tctx,
6748 struct policy_handle *handle)
6750 struct samr_QueryDomainInfo r;
6751 union samr_DomainInfo *info = NULL;
6752 struct samr_SetDomainInfo s;
6753 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6754 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6755 int i;
6756 bool ret = true;
6757 struct dcerpc_binding_handle *b = p->binding_handle;
6758 const char *domain_comment = talloc_asprintf(tctx,
6759 "Tortured by Samba4 RPC-SAMR: %s",
6760 timestring(tctx, time(NULL)));
6762 s.in.domain_handle = handle;
6763 s.in.level = 4;
6764 s.in.info = talloc(tctx, union samr_DomainInfo);
6766 s.in.info->oem.oem_information.string = domain_comment;
6767 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6768 "SetDomainInfo failed");
6769 if (!NT_STATUS_IS_OK(s.out.result)) {
6770 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6771 s.in.level, nt_errstr(s.out.result));
6772 return false;
6775 for (i=0;i<ARRAY_SIZE(levels);i++) {
6776 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6778 r.in.domain_handle = handle;
6779 r.in.level = levels[i];
6780 r.out.info = &info;
6782 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6783 "QueryDomainInfo failed");
6784 if (!NT_STATUS_IS_OK(r.out.result)) {
6785 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6786 r.in.level, nt_errstr(r.out.result));
6787 ret = false;
6788 continue;
6791 switch (levels[i]) {
6792 case 2:
6793 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6794 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6795 levels[i], info->general.oem_information.string, domain_comment);
6796 if (!torture_setting_bool(tctx, "samba3", false)) {
6797 ret = false;
6800 if (!info->general.primary.string) {
6801 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6802 levels[i]);
6803 ret = false;
6804 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6805 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6806 if (torture_setting_bool(tctx, "samba3", false)) {
6807 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6808 levels[i], info->general.primary.string, dcerpc_server_name(p));
6812 break;
6813 case 4:
6814 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6815 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6816 levels[i], info->oem.oem_information.string, domain_comment);
6817 if (!torture_setting_bool(tctx, "samba3", false)) {
6818 ret = false;
6821 break;
6822 case 6:
6823 if (!info->info6.primary.string) {
6824 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6825 levels[i]);
6826 ret = false;
6828 break;
6829 case 11:
6830 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6831 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6832 levels[i], info->general2.general.oem_information.string, domain_comment);
6833 if (!torture_setting_bool(tctx, "samba3", false)) {
6834 ret = false;
6837 break;
6840 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6842 s.in.domain_handle = handle;
6843 s.in.level = levels[i];
6844 s.in.info = info;
6846 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6847 "SetDomainInfo failed");
6848 if (set_ok[i]) {
6849 if (!NT_STATUS_IS_OK(s.out.result)) {
6850 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6851 r.in.level, nt_errstr(s.out.result));
6852 ret = false;
6853 continue;
6855 } else {
6856 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6857 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6858 r.in.level, nt_errstr(s.out.result));
6859 ret = false;
6860 continue;
6864 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6865 "QueryDomainInfo failed");
6866 if (!NT_STATUS_IS_OK(r.out.result)) {
6867 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6868 r.in.level, nt_errstr(r.out.result));
6869 ret = false;
6870 continue;
6874 return ret;
6878 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6879 struct torture_context *tctx,
6880 struct policy_handle *handle)
6882 struct samr_QueryDomainInfo2 r;
6883 union samr_DomainInfo *info = NULL;
6884 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6885 int i;
6886 bool ret = true;
6888 for (i=0;i<ARRAY_SIZE(levels);i++) {
6889 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6891 r.in.domain_handle = handle;
6892 r.in.level = levels[i];
6893 r.out.info = &info;
6895 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6896 "QueryDomainInfo2 failed");
6897 if (!NT_STATUS_IS_OK(r.out.result)) {
6898 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6899 r.in.level, nt_errstr(r.out.result));
6900 ret = false;
6901 continue;
6905 return true;
6908 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6909 set of group names. */
6910 static bool test_GroupList(struct dcerpc_binding_handle *b,
6911 struct torture_context *tctx,
6912 struct dom_sid *domain_sid,
6913 struct policy_handle *handle)
6915 struct samr_EnumDomainGroups q1;
6916 struct samr_QueryDisplayInfo q2;
6917 NTSTATUS status;
6918 uint32_t resume_handle=0;
6919 struct samr_SamArray *sam = NULL;
6920 uint32_t num_entries = 0;
6921 int i;
6922 bool ret = true;
6923 uint32_t total_size;
6924 uint32_t returned_size;
6925 union samr_DispInfo info;
6927 int num_names = 0;
6928 const char **names = NULL;
6930 bool builtin_domain = dom_sid_compare(domain_sid,
6931 &global_sid_Builtin) == 0;
6933 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6935 q1.in.domain_handle = handle;
6936 q1.in.resume_handle = &resume_handle;
6937 q1.in.max_size = 5;
6938 q1.out.resume_handle = &resume_handle;
6939 q1.out.num_entries = &num_entries;
6940 q1.out.sam = &sam;
6942 status = STATUS_MORE_ENTRIES;
6943 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6944 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6945 "EnumDomainGroups failed");
6946 status = q1.out.result;
6948 if (!NT_STATUS_IS_OK(status) &&
6949 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6950 break;
6952 for (i=0; i<*q1.out.num_entries; i++) {
6953 add_string_to_array(tctx,
6954 sam->entries[i].name.string,
6955 &names, &num_names);
6959 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6961 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6963 if (builtin_domain) {
6964 torture_assert(tctx, num_names == 0,
6965 "EnumDomainGroups shouldn't return any group in the builtin domain!");
6968 q2.in.domain_handle = handle;
6969 q2.in.level = 5;
6970 q2.in.start_idx = 0;
6971 q2.in.max_entries = 5;
6972 q2.in.buf_size = (uint32_t)-1;
6973 q2.out.total_size = &total_size;
6974 q2.out.returned_size = &returned_size;
6975 q2.out.info = &info;
6977 status = STATUS_MORE_ENTRIES;
6978 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6979 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
6980 "QueryDisplayInfo failed");
6981 status = q2.out.result;
6982 if (!NT_STATUS_IS_OK(status) &&
6983 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6984 break;
6986 for (i=0; i<q2.out.info->info5.count; i++) {
6987 int j;
6988 const char *name = q2.out.info->info5.entries[i].account_name.string;
6989 bool found = false;
6990 for (j=0; j<num_names; j++) {
6991 if (names[j] == NULL)
6992 continue;
6993 if (strequal(names[j], name)) {
6994 names[j] = NULL;
6995 found = true;
6996 break;
7000 if ((!found) && (!builtin_domain)) {
7001 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7002 name);
7003 ret = false;
7006 q2.in.start_idx += q2.out.info->info5.count;
7009 if (!NT_STATUS_IS_OK(status)) {
7010 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
7011 nt_errstr(status));
7012 ret = false;
7015 if (builtin_domain) {
7016 torture_assert(tctx, q2.in.start_idx != 0,
7017 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
7020 for (i=0; i<num_names; i++) {
7021 if (names[i] != NULL) {
7022 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
7023 names[i]);
7024 ret = false;
7028 return ret;
7031 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
7032 struct torture_context *tctx,
7033 struct policy_handle *group_handle)
7035 struct samr_DeleteDomainGroup d;
7037 torture_comment(tctx, "Testing DeleteDomainGroup\n");
7039 d.in.group_handle = group_handle;
7040 d.out.group_handle = group_handle;
7042 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
7043 "DeleteDomainGroup failed");
7044 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
7046 return true;
7049 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
7050 struct torture_context *tctx,
7051 struct policy_handle *domain_handle)
7053 struct samr_TestPrivateFunctionsDomain r;
7054 bool ret = true;
7056 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
7058 r.in.domain_handle = domain_handle;
7060 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
7061 "TestPrivateFunctionsDomain failed");
7062 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
7064 return ret;
7067 static bool test_RidToSid(struct dcerpc_binding_handle *b,
7068 struct torture_context *tctx,
7069 struct dom_sid *domain_sid,
7070 struct policy_handle *domain_handle)
7072 struct samr_RidToSid r;
7073 bool ret = true;
7074 struct dom_sid *calc_sid, *out_sid;
7075 int rids[] = { 0, 42, 512, 10200 };
7076 int i;
7078 for (i=0;i<ARRAY_SIZE(rids);i++) {
7079 torture_comment(tctx, "Testing RidToSid\n");
7081 calc_sid = dom_sid_dup(tctx, domain_sid);
7082 r.in.domain_handle = domain_handle;
7083 r.in.rid = rids[i];
7084 r.out.sid = &out_sid;
7086 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
7087 "RidToSid failed");
7088 if (!NT_STATUS_IS_OK(r.out.result)) {
7089 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
7090 ret = false;
7091 } else {
7092 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
7094 if (!dom_sid_equal(calc_sid, out_sid)) {
7095 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
7096 dom_sid_string(tctx, out_sid),
7097 dom_sid_string(tctx, calc_sid));
7098 ret = false;
7103 return ret;
7106 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7107 struct torture_context *tctx,
7108 struct policy_handle *domain_handle)
7110 struct samr_GetBootKeyInformation r;
7111 bool ret = true;
7112 uint32_t unknown = 0;
7113 NTSTATUS status;
7115 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7117 r.in.domain_handle = domain_handle;
7118 r.out.unknown = &unknown;
7120 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7121 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7122 status = r.out.result;
7124 if (!NT_STATUS_IS_OK(status)) {
7125 /* w2k3 seems to fail this sometimes and pass it sometimes */
7126 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7129 return ret;
7132 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7133 struct torture_context *tctx,
7134 struct policy_handle *domain_handle,
7135 struct policy_handle *group_handle)
7137 NTSTATUS status;
7138 struct samr_AddGroupMember r;
7139 struct samr_DeleteGroupMember d;
7140 struct samr_QueryGroupMember q;
7141 struct samr_RidAttrArray *rids = NULL;
7142 struct samr_SetMemberAttributesOfGroup s;
7143 uint32_t rid;
7144 bool found_member = false;
7145 int i;
7147 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7148 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7150 r.in.group_handle = group_handle;
7151 r.in.rid = rid;
7152 r.in.flags = 0; /* ??? */
7154 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7156 d.in.group_handle = group_handle;
7157 d.in.rid = rid;
7159 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7160 "DeleteGroupMember failed");
7161 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7163 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7164 "AddGroupMember failed");
7165 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7167 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7168 "AddGroupMember failed");
7169 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7171 if (torture_setting_bool(tctx, "samba4", false) ||
7172 torture_setting_bool(tctx, "samba3", false)) {
7173 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7174 } else {
7175 /* this one is quite strange. I am using random inputs in the
7176 hope of triggering an error that might give us a clue */
7178 s.in.group_handle = group_handle;
7179 s.in.unknown1 = random();
7180 s.in.unknown2 = random();
7182 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7183 "SetMemberAttributesOfGroup failed");
7184 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7187 q.in.group_handle = group_handle;
7188 q.out.rids = &rids;
7190 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7191 "QueryGroupMember failed");
7192 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7193 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7195 for (i=0; i < rids->count; i++) {
7196 if (rids->rids[i] == rid) {
7197 found_member = true;
7201 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7203 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7204 "DeleteGroupMember failed");
7205 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7207 rids = NULL;
7208 found_member = false;
7210 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7211 "QueryGroupMember failed");
7212 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7213 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7215 for (i=0; i < rids->count; i++) {
7216 if (rids->rids[i] == rid) {
7217 found_member = true;
7221 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7223 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7224 "AddGroupMember failed");
7225 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7227 return true;
7231 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7232 struct torture_context *tctx,
7233 struct policy_handle *domain_handle,
7234 const char *group_name,
7235 struct policy_handle *group_handle,
7236 struct dom_sid *domain_sid,
7237 bool test_group)
7239 struct samr_CreateDomainGroup r;
7240 uint32_t rid;
7241 struct lsa_String name;
7242 bool ret = true;
7244 init_lsa_String(&name, group_name);
7246 r.in.domain_handle = domain_handle;
7247 r.in.name = &name;
7248 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7249 r.out.group_handle = group_handle;
7250 r.out.rid = &rid;
7252 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7254 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7255 "CreateDomainGroup failed");
7257 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7258 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7259 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7260 return true;
7261 } else {
7262 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7263 nt_errstr(r.out.result));
7264 return false;
7268 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7269 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7270 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7271 nt_errstr(r.out.result));
7272 return false;
7274 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7275 "CreateDomainGroup failed");
7277 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7278 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7280 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7281 nt_errstr(r.out.result));
7282 return false;
7284 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7285 "CreateDomainGroup failed");
7287 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7289 if (!test_group) {
7290 return ret;
7293 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7294 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7295 ret = false;
7298 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7299 ret = false;
7302 return ret;
7307 its not totally clear what this does. It seems to accept any sid you like.
7309 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7310 struct torture_context *tctx,
7311 struct policy_handle *domain_handle)
7313 struct samr_RemoveMemberFromForeignDomain r;
7315 r.in.domain_handle = domain_handle;
7316 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7318 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7319 "RemoveMemberFromForeignDomain failed");
7320 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7322 return true;
7325 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7326 struct torture_context *tctx,
7327 struct policy_handle *domain_handle,
7328 uint32_t *total_num_entries_p)
7330 NTSTATUS status;
7331 struct samr_EnumDomainUsers r;
7332 uint32_t resume_handle = 0;
7333 uint32_t num_entries = 0;
7334 uint32_t total_num_entries = 0;
7335 struct samr_SamArray *sam;
7337 r.in.domain_handle = domain_handle;
7338 r.in.acct_flags = 0;
7339 r.in.max_size = (uint32_t)-1;
7340 r.in.resume_handle = &resume_handle;
7342 r.out.sam = &sam;
7343 r.out.num_entries = &num_entries;
7344 r.out.resume_handle = &resume_handle;
7346 torture_comment(tctx, "Testing EnumDomainUsers\n");
7348 do {
7349 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7350 "EnumDomainUsers failed");
7351 if (NT_STATUS_IS_ERR(r.out.result)) {
7352 torture_assert_ntstatus_ok(tctx, r.out.result,
7353 "failed to enumerate users");
7355 status = r.out.result;
7357 total_num_entries += num_entries;
7358 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7360 if (total_num_entries_p) {
7361 *total_num_entries_p = total_num_entries;
7364 return true;
7367 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7368 struct torture_context *tctx,
7369 struct policy_handle *domain_handle,
7370 uint32_t *total_num_entries_p)
7372 NTSTATUS status;
7373 struct samr_EnumDomainGroups r;
7374 uint32_t resume_handle = 0;
7375 uint32_t num_entries = 0;
7376 uint32_t total_num_entries = 0;
7377 struct samr_SamArray *sam;
7379 r.in.domain_handle = domain_handle;
7380 r.in.max_size = (uint32_t)-1;
7381 r.in.resume_handle = &resume_handle;
7383 r.out.sam = &sam;
7384 r.out.num_entries = &num_entries;
7385 r.out.resume_handle = &resume_handle;
7387 torture_comment(tctx, "Testing EnumDomainGroups\n");
7389 do {
7390 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7391 "EnumDomainGroups failed");
7392 if (NT_STATUS_IS_ERR(r.out.result)) {
7393 torture_assert_ntstatus_ok(tctx, r.out.result,
7394 "failed to enumerate groups");
7396 status = r.out.result;
7398 total_num_entries += num_entries;
7399 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7401 if (total_num_entries_p) {
7402 *total_num_entries_p = total_num_entries;
7405 return true;
7408 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7409 struct torture_context *tctx,
7410 struct policy_handle *domain_handle,
7411 uint32_t *total_num_entries_p)
7413 NTSTATUS status;
7414 struct samr_EnumDomainAliases r;
7415 uint32_t resume_handle = 0;
7416 uint32_t num_entries = 0;
7417 uint32_t total_num_entries = 0;
7418 struct samr_SamArray *sam;
7420 r.in.domain_handle = domain_handle;
7421 r.in.max_size = (uint32_t)-1;
7422 r.in.resume_handle = &resume_handle;
7424 r.out.sam = &sam;
7425 r.out.num_entries = &num_entries;
7426 r.out.resume_handle = &resume_handle;
7428 torture_comment(tctx, "Testing EnumDomainAliases\n");
7430 do {
7431 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7432 "EnumDomainAliases failed");
7433 if (NT_STATUS_IS_ERR(r.out.result)) {
7434 torture_assert_ntstatus_ok(tctx, r.out.result,
7435 "failed to enumerate aliases");
7437 status = r.out.result;
7439 total_num_entries += num_entries;
7440 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7442 if (total_num_entries_p) {
7443 *total_num_entries_p = total_num_entries;
7446 return true;
7449 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7450 struct torture_context *tctx,
7451 struct policy_handle *handle,
7452 uint16_t level,
7453 uint32_t *total_num_entries_p)
7455 NTSTATUS status;
7456 struct samr_QueryDisplayInfo r;
7457 uint32_t total_num_entries = 0;
7459 r.in.domain_handle = handle;
7460 r.in.level = level;
7461 r.in.start_idx = 0;
7462 r.in.max_entries = (uint32_t)-1;
7463 r.in.buf_size = (uint32_t)-1;
7465 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7467 do {
7468 uint32_t total_size;
7469 uint32_t returned_size;
7470 union samr_DispInfo info;
7472 r.out.total_size = &total_size;
7473 r.out.returned_size = &returned_size;
7474 r.out.info = &info;
7476 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7477 "failed to query displayinfo");
7478 if (NT_STATUS_IS_ERR(r.out.result)) {
7479 torture_assert_ntstatus_ok(tctx, r.out.result,
7480 "failed to query displayinfo");
7482 status = r.out.result;
7484 if (*r.out.returned_size == 0) {
7485 break;
7488 switch (r.in.level) {
7489 case 1:
7490 total_num_entries += info.info1.count;
7491 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7492 break;
7493 case 2:
7494 total_num_entries += info.info2.count;
7495 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7496 break;
7497 case 3:
7498 total_num_entries += info.info3.count;
7499 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7500 break;
7501 case 4:
7502 total_num_entries += info.info4.count;
7503 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7504 break;
7505 case 5:
7506 total_num_entries += info.info5.count;
7507 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7508 break;
7509 default:
7510 return false;
7513 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7515 if (total_num_entries_p) {
7516 *total_num_entries_p = total_num_entries;
7519 return true;
7522 static bool test_ManyObjects(struct dcerpc_pipe *p,
7523 struct torture_context *tctx,
7524 struct policy_handle *domain_handle,
7525 struct dom_sid *domain_sid,
7526 struct torture_samr_context *ctx)
7528 uint32_t num_total = ctx->num_objects_large_dc;
7529 uint32_t num_enum = 0;
7530 uint32_t num_disp = 0;
7531 uint32_t num_created = 0;
7532 uint32_t num_anounced = 0;
7533 uint32_t i;
7534 struct dcerpc_binding_handle *b = p->binding_handle;
7536 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7538 /* query */
7541 struct samr_QueryDomainInfo2 r;
7542 union samr_DomainInfo *info;
7543 r.in.domain_handle = domain_handle;
7544 r.in.level = 2;
7545 r.out.info = &info;
7547 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7548 "QueryDomainInfo2 failed");
7549 torture_assert_ntstatus_ok(tctx, r.out.result,
7550 "failed to query domain info");
7552 switch (ctx->choice) {
7553 case TORTURE_SAMR_MANY_ACCOUNTS:
7554 num_anounced = info->general.num_users;
7555 break;
7556 case TORTURE_SAMR_MANY_GROUPS:
7557 num_anounced = info->general.num_groups;
7558 break;
7559 case TORTURE_SAMR_MANY_ALIASES:
7560 num_anounced = info->general.num_aliases;
7561 break;
7562 default:
7563 return false;
7567 /* create */
7569 for (i=0; i < num_total; i++) {
7571 const char *name = NULL;
7573 switch (ctx->choice) {
7574 case TORTURE_SAMR_MANY_ACCOUNTS:
7575 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7576 torture_assert(tctx,
7577 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7578 "failed to create user");
7579 break;
7580 case TORTURE_SAMR_MANY_GROUPS:
7581 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7582 torture_assert(tctx,
7583 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7584 "failed to create group");
7585 break;
7586 case TORTURE_SAMR_MANY_ALIASES:
7587 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7588 torture_assert(tctx,
7589 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7590 "failed to create alias");
7591 break;
7592 default:
7593 return false;
7595 if (!ndr_policy_handle_empty(&handles[i])) {
7596 num_created++;
7600 /* enum */
7602 switch (ctx->choice) {
7603 case TORTURE_SAMR_MANY_ACCOUNTS:
7604 torture_assert(tctx,
7605 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7606 "failed to enum users");
7607 break;
7608 case TORTURE_SAMR_MANY_GROUPS:
7609 torture_assert(tctx,
7610 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7611 "failed to enum groups");
7612 break;
7613 case TORTURE_SAMR_MANY_ALIASES:
7614 torture_assert(tctx,
7615 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7616 "failed to enum aliases");
7617 break;
7618 default:
7619 return false;
7622 /* dispinfo */
7624 switch (ctx->choice) {
7625 case TORTURE_SAMR_MANY_ACCOUNTS:
7626 torture_assert(tctx,
7627 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
7628 "failed to query display info");
7629 break;
7630 case TORTURE_SAMR_MANY_GROUPS:
7631 torture_assert(tctx,
7632 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
7633 "failed to query display info");
7634 break;
7635 case TORTURE_SAMR_MANY_ALIASES:
7636 /* no aliases in dispinfo */
7637 break;
7638 default:
7639 return false;
7642 /* close or delete */
7644 for (i=0; i < num_total; i++) {
7646 if (ndr_policy_handle_empty(&handles[i])) {
7647 continue;
7650 if (torture_setting_bool(tctx, "samba3", false)) {
7651 torture_assert(tctx,
7652 test_samr_handle_Close(b, tctx, &handles[i]),
7653 "failed to close handle");
7654 } else {
7655 switch (ctx->choice) {
7656 case TORTURE_SAMR_MANY_ACCOUNTS:
7657 torture_assert(tctx,
7658 test_DeleteUser(b, tctx, &handles[i]),
7659 "failed to delete user");
7660 break;
7661 case TORTURE_SAMR_MANY_GROUPS:
7662 torture_assert(tctx,
7663 test_DeleteDomainGroup(b, tctx, &handles[i]),
7664 "failed to delete group");
7665 break;
7666 case TORTURE_SAMR_MANY_ALIASES:
7667 torture_assert(tctx,
7668 test_DeleteAlias(b, tctx, &handles[i]),
7669 "failed to delete alias");
7670 break;
7671 default:
7672 return false;
7677 talloc_free(handles);
7679 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7680 torture_comment(tctx,
7681 "unexpected number of results (%u) returned in enum call, expected %u\n",
7682 num_enum, num_anounced + num_created);
7684 torture_comment(tctx,
7685 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7686 num_disp, num_anounced + num_created);
7689 return true;
7692 static bool test_Connect(struct dcerpc_binding_handle *b,
7693 struct torture_context *tctx,
7694 struct policy_handle *handle);
7696 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7697 struct torture_samr_context *ctx, struct dom_sid *sid)
7699 struct samr_OpenDomain r;
7700 struct policy_handle domain_handle;
7701 struct policy_handle alias_handle;
7702 struct policy_handle user_handle;
7703 struct policy_handle group_handle;
7704 bool ret = true;
7705 struct dcerpc_binding_handle *b = p->binding_handle;
7707 ZERO_STRUCT(alias_handle);
7708 ZERO_STRUCT(user_handle);
7709 ZERO_STRUCT(group_handle);
7710 ZERO_STRUCT(domain_handle);
7712 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7714 r.in.connect_handle = &ctx->handle;
7715 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7716 r.in.sid = sid;
7717 r.out.domain_handle = &domain_handle;
7719 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7720 "OpenDomain failed");
7721 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7723 /* run the domain tests with the main handle closed - this tests
7724 the servers reference counting */
7725 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7727 switch (ctx->choice) {
7728 case TORTURE_SAMR_PASSWORDS:
7729 case TORTURE_SAMR_USER_PRIVILEGES:
7730 if (!torture_setting_bool(tctx, "samba3", false)) {
7731 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7733 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7734 if (!ret) {
7735 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7737 break;
7738 case TORTURE_SAMR_USER_ATTRIBUTES:
7739 if (!torture_setting_bool(tctx, "samba3", false)) {
7740 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7742 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7743 /* This test needs 'complex' users to validate */
7744 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7745 if (!ret) {
7746 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7748 break;
7749 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7750 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7751 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7752 if (!torture_setting_bool(tctx, "samba3", false)) {
7753 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7755 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7756 if (!ret) {
7757 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7759 break;
7760 case TORTURE_SAMR_MANY_ACCOUNTS:
7761 case TORTURE_SAMR_MANY_GROUPS:
7762 case TORTURE_SAMR_MANY_ALIASES:
7763 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7764 if (!ret) {
7765 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7767 break;
7768 case TORTURE_SAMR_OTHER:
7769 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7770 if (!ret) {
7771 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7773 if (!torture_setting_bool(tctx, "samba3", false)) {
7774 ret &= test_QuerySecurity(b, tctx, &domain_handle);
7776 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7777 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7778 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7779 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7780 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7781 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7782 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7783 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7784 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7785 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7786 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7787 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7788 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7790 if (torture_setting_bool(tctx, "samba4", false)) {
7791 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7792 } else {
7793 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7794 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7796 ret &= test_GroupList(b, tctx, sid, &domain_handle);
7797 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7798 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7799 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7800 if (!ret) {
7801 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7803 break;
7806 if (!ndr_policy_handle_empty(&user_handle) &&
7807 !test_DeleteUser(b, tctx, &user_handle)) {
7808 ret = false;
7811 if (!ndr_policy_handle_empty(&alias_handle) &&
7812 !test_DeleteAlias(b, tctx, &alias_handle)) {
7813 ret = false;
7816 if (!ndr_policy_handle_empty(&group_handle) &&
7817 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7818 ret = false;
7821 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7823 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7824 /* reconnect the main handle */
7826 if (!ret) {
7827 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7830 return ret;
7833 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7834 struct torture_samr_context *ctx, const char *domain)
7836 struct samr_LookupDomain r;
7837 struct dom_sid2 *sid = NULL;
7838 struct lsa_String n1;
7839 struct lsa_String n2;
7840 bool ret = true;
7841 struct dcerpc_binding_handle *b = p->binding_handle;
7843 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7845 /* check for correct error codes */
7846 r.in.connect_handle = &ctx->handle;
7847 r.in.domain_name = &n2;
7848 r.out.sid = &sid;
7849 n2.string = NULL;
7851 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7852 "LookupDomain failed");
7853 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7855 init_lsa_String(&n2, "xxNODOMAINxx");
7857 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7858 "LookupDomain failed");
7859 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7861 r.in.connect_handle = &ctx->handle;
7863 init_lsa_String(&n1, domain);
7864 r.in.domain_name = &n1;
7866 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7867 "LookupDomain failed");
7868 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7870 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7871 ret = false;
7874 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7875 ret = false;
7878 return ret;
7882 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7883 struct torture_samr_context *ctx)
7885 struct samr_EnumDomains r;
7886 uint32_t resume_handle = 0;
7887 uint32_t num_entries = 0;
7888 struct samr_SamArray *sam = NULL;
7889 int i;
7890 bool ret = true;
7891 struct dcerpc_binding_handle *b = p->binding_handle;
7893 r.in.connect_handle = &ctx->handle;
7894 r.in.resume_handle = &resume_handle;
7895 r.in.buf_size = (uint32_t)-1;
7896 r.out.resume_handle = &resume_handle;
7897 r.out.num_entries = &num_entries;
7898 r.out.sam = &sam;
7900 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7901 "EnumDomains failed");
7902 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7904 if (!*r.out.sam) {
7905 return false;
7908 for (i=0;i<sam->count;i++) {
7909 if (!test_LookupDomain(p, tctx, ctx,
7910 sam->entries[i].name.string)) {
7911 ret = false;
7915 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7916 "EnumDomains failed");
7917 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7919 return ret;
7923 static bool test_Connect(struct dcerpc_binding_handle *b,
7924 struct torture_context *tctx,
7925 struct policy_handle *handle)
7927 struct samr_Connect r;
7928 struct samr_Connect2 r2;
7929 struct samr_Connect3 r3;
7930 struct samr_Connect4 r4;
7931 struct samr_Connect5 r5;
7932 union samr_ConnectInfo info;
7933 struct policy_handle h;
7934 uint32_t level_out = 0;
7935 bool ret = true, got_handle = false;
7937 torture_comment(tctx, "Testing samr_Connect\n");
7939 r.in.system_name = NULL;
7940 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7941 r.out.connect_handle = &h;
7943 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7944 "Connect failed");
7945 if (!NT_STATUS_IS_OK(r.out.result)) {
7946 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7947 ret = false;
7948 } else {
7949 got_handle = true;
7950 *handle = h;
7953 torture_comment(tctx, "Testing samr_Connect2\n");
7955 r2.in.system_name = NULL;
7956 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7957 r2.out.connect_handle = &h;
7959 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7960 "Connect2 failed");
7961 if (!NT_STATUS_IS_OK(r2.out.result)) {
7962 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7963 ret = false;
7964 } else {
7965 if (got_handle) {
7966 test_samr_handle_Close(b, tctx, handle);
7968 got_handle = true;
7969 *handle = h;
7972 torture_comment(tctx, "Testing samr_Connect3\n");
7974 r3.in.system_name = NULL;
7975 r3.in.unknown = 0;
7976 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7977 r3.out.connect_handle = &h;
7979 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
7980 "Connect3 failed");
7981 if (!NT_STATUS_IS_OK(r3.out.result)) {
7982 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
7983 ret = false;
7984 } else {
7985 if (got_handle) {
7986 test_samr_handle_Close(b, tctx, handle);
7988 got_handle = true;
7989 *handle = h;
7992 torture_comment(tctx, "Testing samr_Connect4\n");
7994 r4.in.system_name = "";
7995 r4.in.client_version = 0;
7996 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7997 r4.out.connect_handle = &h;
7999 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8000 "Connect4 failed");
8001 if (!NT_STATUS_IS_OK(r4.out.result)) {
8002 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8003 ret = false;
8004 } else {
8005 if (got_handle) {
8006 test_samr_handle_Close(b, tctx, handle);
8008 got_handle = true;
8009 *handle = h;
8012 torture_comment(tctx, "Testing samr_Connect5\n");
8014 info.info1.client_version = 0;
8015 info.info1.unknown2 = 0;
8017 r5.in.system_name = "";
8018 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8019 r5.in.level_in = 1;
8020 r5.out.level_out = &level_out;
8021 r5.in.info_in = &info;
8022 r5.out.info_out = &info;
8023 r5.out.connect_handle = &h;
8025 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
8026 "Connect5 failed");
8027 if (!NT_STATUS_IS_OK(r5.out.result)) {
8028 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
8029 ret = false;
8030 } else {
8031 if (got_handle) {
8032 test_samr_handle_Close(b, tctx, handle);
8034 got_handle = true;
8035 *handle = h;
8038 return ret;
8042 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
8043 struct torture_context *tctx)
8045 struct samr_ValidatePassword r;
8046 union samr_ValidatePasswordReq req;
8047 union samr_ValidatePasswordRep *repp = NULL;
8048 NTSTATUS status;
8049 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
8050 int i;
8051 struct dcerpc_binding_handle *b = p->binding_handle;
8053 torture_comment(tctx, "Testing samr_ValidatePassword\n");
8055 ZERO_STRUCT(r);
8056 r.in.level = NetValidatePasswordReset;
8057 r.in.req = &req;
8058 r.out.rep = &repp;
8060 ZERO_STRUCT(req);
8061 req.req3.account.string = "non-existent-account-aklsdji";
8063 for (i=0; passwords[i]; i++) {
8064 req.req3.password.string = passwords[i];
8066 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
8067 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
8068 torture_skip(tctx, "ValidatePassword not supported by server\n");
8070 torture_assert_ntstatus_ok(tctx, status,
8071 "samr_ValidatePassword failed");
8072 torture_assert_ntstatus_ok(tctx, r.out.result,
8073 "samr_ValidatePassword failed");
8074 torture_comment(tctx, "Server %s password '%s' with code %i\n",
8075 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
8076 req.req3.password.string, repp->ctr3.status);
8079 return true;
8082 bool torture_rpc_samr(struct torture_context *torture)
8084 NTSTATUS status;
8085 struct dcerpc_pipe *p;
8086 bool ret = true;
8087 struct torture_samr_context *ctx;
8088 struct dcerpc_binding_handle *b;
8090 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8091 if (!NT_STATUS_IS_OK(status)) {
8092 return false;
8094 b = p->binding_handle;
8096 ctx = talloc_zero(torture, struct torture_samr_context);
8098 ctx->choice = TORTURE_SAMR_OTHER;
8100 ret &= test_Connect(b, torture, &ctx->handle);
8102 if (!torture_setting_bool(torture, "samba3", false)) {
8103 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8106 ret &= test_EnumDomains(p, torture, ctx);
8108 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8110 ret &= test_Shutdown(b, torture, &ctx->handle);
8112 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8114 return ret;
8118 bool torture_rpc_samr_users(struct torture_context *torture)
8120 NTSTATUS status;
8121 struct dcerpc_pipe *p;
8122 bool ret = true;
8123 struct torture_samr_context *ctx;
8124 struct dcerpc_binding_handle *b;
8126 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8127 if (!NT_STATUS_IS_OK(status)) {
8128 return false;
8130 b = p->binding_handle;
8132 ctx = talloc_zero(torture, struct torture_samr_context);
8134 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8136 ret &= test_Connect(b, torture, &ctx->handle);
8138 if (!torture_setting_bool(torture, "samba3", false)) {
8139 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8142 ret &= test_EnumDomains(p, torture, ctx);
8144 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8146 ret &= test_Shutdown(b, torture, &ctx->handle);
8148 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8150 return ret;
8154 bool torture_rpc_samr_passwords(struct torture_context *torture)
8156 NTSTATUS status;
8157 struct dcerpc_pipe *p;
8158 bool ret = true;
8159 struct torture_samr_context *ctx;
8160 struct dcerpc_binding_handle *b;
8162 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8163 if (!NT_STATUS_IS_OK(status)) {
8164 return false;
8166 b = p->binding_handle;
8168 ctx = talloc_zero(torture, struct torture_samr_context);
8170 ctx->choice = TORTURE_SAMR_PASSWORDS;
8172 ret &= test_Connect(b, torture, &ctx->handle);
8174 ret &= test_EnumDomains(p, torture, ctx);
8176 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8178 ret &= test_samr_ValidatePassword(p, torture);
8180 return ret;
8183 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8184 struct dcerpc_pipe *p2,
8185 struct cli_credentials *machine_credentials)
8187 NTSTATUS status;
8188 struct dcerpc_pipe *p;
8189 bool ret = true;
8190 struct torture_samr_context *ctx;
8191 struct dcerpc_binding_handle *b;
8193 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8194 if (!NT_STATUS_IS_OK(status)) {
8195 return false;
8197 b = p->binding_handle;
8199 ctx = talloc_zero(torture, struct torture_samr_context);
8201 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8202 ctx->machine_credentials = machine_credentials;
8204 ret &= test_Connect(b, torture, &ctx->handle);
8206 ret &= test_EnumDomains(p, torture, ctx);
8208 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8210 return ret;
8213 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8215 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8216 struct torture_rpc_tcase *tcase;
8218 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8219 &ndr_table_samr,
8220 TEST_ACCOUNT_NAME_PWD);
8222 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8223 torture_rpc_samr_pwdlastset);
8225 return suite;
8228 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8229 struct dcerpc_pipe *p2,
8230 struct cli_credentials *machine_credentials)
8232 NTSTATUS status;
8233 struct dcerpc_pipe *p;
8234 bool ret = true;
8235 struct torture_samr_context *ctx;
8236 struct dcerpc_binding_handle *b;
8238 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8239 if (!NT_STATUS_IS_OK(status)) {
8240 return false;
8242 b = p->binding_handle;
8244 ctx = talloc_zero(torture, struct torture_samr_context);
8246 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8247 ctx->machine_credentials = machine_credentials;
8249 ret &= test_Connect(b, torture, &ctx->handle);
8251 ret &= test_EnumDomains(p, torture, ctx);
8253 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8255 return ret;
8258 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8260 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8261 struct torture_rpc_tcase *tcase;
8263 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8264 &ndr_table_samr,
8265 TEST_ACCOUNT_NAME_PWD);
8267 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8268 torture_rpc_samr_users_privileges_delete_user);
8270 return suite;
8273 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8274 struct dcerpc_pipe *p2,
8275 void *data)
8277 NTSTATUS status;
8278 struct dcerpc_pipe *p;
8279 bool ret = true;
8280 struct torture_samr_context *ctx =
8281 talloc_get_type_abort(data, struct torture_samr_context);
8282 struct dcerpc_binding_handle *b;
8284 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8285 if (!NT_STATUS_IS_OK(status)) {
8286 return false;
8288 b = p->binding_handle;
8290 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8291 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8292 ctx->num_objects_large_dc);
8294 ret &= test_Connect(b, torture, &ctx->handle);
8296 ret &= test_EnumDomains(p, torture, ctx);
8298 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8300 return ret;
8303 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8304 struct dcerpc_pipe *p2,
8305 void *data)
8307 NTSTATUS status;
8308 struct dcerpc_pipe *p;
8309 bool ret = true;
8310 struct torture_samr_context *ctx =
8311 talloc_get_type_abort(data, struct torture_samr_context);
8312 struct dcerpc_binding_handle *b;
8314 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8315 if (!NT_STATUS_IS_OK(status)) {
8316 return false;
8318 b = p->binding_handle;
8320 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8321 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8322 ctx->num_objects_large_dc);
8324 ret &= test_Connect(b, torture, &ctx->handle);
8326 ret &= test_EnumDomains(p, torture, ctx);
8328 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8330 return ret;
8333 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8334 struct dcerpc_pipe *p2,
8335 void *data)
8337 NTSTATUS status;
8338 struct dcerpc_pipe *p;
8339 bool ret = true;
8340 struct torture_samr_context *ctx =
8341 talloc_get_type_abort(data, struct torture_samr_context);
8342 struct dcerpc_binding_handle *b;
8344 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8345 if (!NT_STATUS_IS_OK(status)) {
8346 return false;
8348 b = p->binding_handle;
8350 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8351 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8352 ctx->num_objects_large_dc);
8354 ret &= test_Connect(b, torture, &ctx->handle);
8356 ret &= test_EnumDomains(p, torture, ctx);
8358 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8360 return ret;
8363 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8365 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8366 struct torture_rpc_tcase *tcase;
8367 struct torture_samr_context *ctx;
8369 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8371 ctx = talloc_zero(suite, struct torture_samr_context);
8372 ctx->num_objects_large_dc = 150;
8374 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8375 torture_rpc_samr_many_aliases, ctx);
8376 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8377 torture_rpc_samr_many_groups, ctx);
8378 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8379 torture_rpc_samr_many_accounts, ctx);
8381 return suite;
8384 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8385 struct dcerpc_pipe *p2,
8386 struct cli_credentials *machine_credentials)
8388 NTSTATUS status;
8389 struct dcerpc_pipe *p;
8390 bool ret = true;
8391 struct torture_samr_context *ctx;
8392 struct dcerpc_binding_handle *b;
8394 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8395 if (!NT_STATUS_IS_OK(status)) {
8396 return false;
8398 b = p->binding_handle;
8400 ctx = talloc_zero(torture, struct torture_samr_context);
8402 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8403 ctx->machine_credentials = machine_credentials;
8405 ret &= test_Connect(b, torture, &ctx->handle);
8407 ret &= test_EnumDomains(p, torture, ctx);
8409 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8411 return ret;
8414 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8416 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8417 struct torture_rpc_tcase *tcase;
8419 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8420 &ndr_table_samr,
8421 TEST_ACCOUNT_NAME_PWD);
8423 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8424 torture_rpc_samr_badpwdcount);
8426 return suite;
8429 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8430 struct dcerpc_pipe *p2,
8431 struct cli_credentials *machine_credentials)
8433 NTSTATUS status;
8434 struct dcerpc_pipe *p;
8435 bool ret = true;
8436 struct torture_samr_context *ctx;
8437 struct dcerpc_binding_handle *b;
8439 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8440 if (!NT_STATUS_IS_OK(status)) {
8441 return false;
8443 b = p->binding_handle;
8445 ctx = talloc_zero(torture, struct torture_samr_context);
8447 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8448 ctx->machine_credentials = machine_credentials;
8450 ret &= test_Connect(b, torture, &ctx->handle);
8452 ret &= test_EnumDomains(p, torture, ctx);
8454 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8456 return ret;
8459 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8461 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8462 struct torture_rpc_tcase *tcase;
8464 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8465 &ndr_table_samr,
8466 TEST_ACCOUNT_NAME_PWD);
8468 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8469 torture_rpc_samr_lockout);
8471 return suite;