s4-torture: validate owf password hash and negotiate AES in forest trust test.
[Samba/gebeck_regimport.git] / source4 / torture / rpc / samr.c
blob7f50ce95d5f7a3ae90a2d97e6ffac102ad8f2aeb
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 if (!NT_STATUS_IS_OK(s.out.result)) {
669 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
670 s.in.level, nt_errstr(s.out.result));
671 ret = false;
672 } else {
673 *password = newpass;
676 return ret;
680 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
681 struct policy_handle *handle, uint32_t fields_present,
682 char **password)
684 NTSTATUS status;
685 struct samr_SetUserInfo s;
686 union samr_UserInfo u;
687 bool ret = true;
688 DATA_BLOB session_key;
689 struct dcerpc_binding_handle *b = p->binding_handle;
690 char *newpass;
691 struct samr_GetUserPwInfo pwp;
692 struct samr_PwInfo info;
693 int policy_min_pw_len = 0;
694 pwp.in.user_handle = handle;
695 pwp.out.info = &info;
697 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
698 "GetUserPwInfo failed");
699 if (NT_STATUS_IS_OK(pwp.out.result)) {
700 policy_min_pw_len = pwp.out.info->min_password_length;
702 newpass = samr_rand_pass(tctx, policy_min_pw_len);
704 s.in.user_handle = handle;
705 s.in.info = &u;
706 s.in.level = 23;
708 ZERO_STRUCT(u);
710 u.info23.info.fields_present = fields_present;
712 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
714 status = dcerpc_fetch_session_key(p, &session_key);
715 if (!NT_STATUS_IS_OK(status)) {
716 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
717 s.in.level, nt_errstr(status));
718 return false;
721 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
723 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
725 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
726 "SetUserInfo failed");
727 if (!NT_STATUS_IS_OK(s.out.result)) {
728 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
729 s.in.level, nt_errstr(s.out.result));
730 ret = false;
731 } else {
732 *password = newpass;
735 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
737 status = dcerpc_fetch_session_key(p, &session_key);
738 if (!NT_STATUS_IS_OK(status)) {
739 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
740 s.in.level, nt_errstr(status));
741 return false;
744 /* This should break the key nicely */
745 session_key.length--;
746 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
748 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
750 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
751 "SetUserInfo failed");
752 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
753 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
754 s.in.level, nt_errstr(s.out.result));
755 ret = false;
758 return ret;
762 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
763 struct policy_handle *handle, bool makeshort,
764 char **password)
766 NTSTATUS status;
767 struct samr_SetUserInfo s;
768 union samr_UserInfo u;
769 bool ret = true;
770 DATA_BLOB session_key;
771 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
772 uint8_t confounder[16];
773 char *newpass;
774 struct dcerpc_binding_handle *b = p->binding_handle;
775 struct MD5Context ctx;
776 struct samr_GetUserPwInfo pwp;
777 struct samr_PwInfo info;
778 int policy_min_pw_len = 0;
779 pwp.in.user_handle = handle;
780 pwp.out.info = &info;
782 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
783 "GetUserPwInfo failed");
784 if (NT_STATUS_IS_OK(pwp.out.result)) {
785 policy_min_pw_len = pwp.out.info->min_password_length;
787 if (makeshort && policy_min_pw_len) {
788 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
789 } else {
790 newpass = samr_rand_pass(tctx, policy_min_pw_len);
793 s.in.user_handle = handle;
794 s.in.info = &u;
795 s.in.level = 26;
797 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
798 u.info26.password_expired = 0;
800 status = dcerpc_fetch_session_key(p, &session_key);
801 if (!NT_STATUS_IS_OK(status)) {
802 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
803 s.in.level, nt_errstr(status));
804 return false;
807 generate_random_buffer((uint8_t *)confounder, 16);
809 MD5Init(&ctx);
810 MD5Update(&ctx, confounder, 16);
811 MD5Update(&ctx, session_key.data, session_key.length);
812 MD5Final(confounded_session_key.data, &ctx);
814 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
815 memcpy(&u.info26.password.data[516], confounder, 16);
817 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
819 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
820 "SetUserInfo failed");
821 if (!NT_STATUS_IS_OK(s.out.result)) {
822 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
823 s.in.level, nt_errstr(s.out.result));
824 ret = false;
825 } else {
826 *password = newpass;
829 /* This should break the key nicely */
830 confounded_session_key.data[0]++;
832 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
833 memcpy(&u.info26.password.data[516], confounder, 16);
835 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
837 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
838 "SetUserInfo failed");
839 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
840 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
841 s.in.level, nt_errstr(s.out.result));
842 ret = false;
843 } else {
844 *password = newpass;
847 return ret;
850 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
851 struct policy_handle *handle, uint32_t fields_present,
852 char **password)
854 NTSTATUS status;
855 struct samr_SetUserInfo s;
856 union samr_UserInfo u;
857 bool ret = true;
858 DATA_BLOB session_key;
859 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
860 struct MD5Context ctx;
861 uint8_t confounder[16];
862 char *newpass;
863 struct dcerpc_binding_handle *b = p->binding_handle;
864 struct samr_GetUserPwInfo pwp;
865 struct samr_PwInfo info;
866 int policy_min_pw_len = 0;
867 pwp.in.user_handle = handle;
868 pwp.out.info = &info;
870 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
871 "GetUserPwInfo failed");
872 if (NT_STATUS_IS_OK(pwp.out.result)) {
873 policy_min_pw_len = pwp.out.info->min_password_length;
875 newpass = samr_rand_pass(tctx, policy_min_pw_len);
877 s.in.user_handle = handle;
878 s.in.info = &u;
879 s.in.level = 25;
881 ZERO_STRUCT(u);
883 u.info25.info.fields_present = fields_present;
885 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
887 status = dcerpc_fetch_session_key(p, &session_key);
888 if (!NT_STATUS_IS_OK(status)) {
889 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
890 s.in.level, nt_errstr(status));
891 return false;
894 generate_random_buffer((uint8_t *)confounder, 16);
896 MD5Init(&ctx);
897 MD5Update(&ctx, confounder, 16);
898 MD5Update(&ctx, session_key.data, session_key.length);
899 MD5Final(confounded_session_key.data, &ctx);
901 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
902 memcpy(&u.info25.password.data[516], confounder, 16);
904 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
906 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
907 "SetUserInfo failed");
908 if (!NT_STATUS_IS_OK(s.out.result)) {
909 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
910 s.in.level, nt_errstr(s.out.result));
911 ret = false;
912 } else {
913 *password = newpass;
916 /* This should break the key nicely */
917 confounded_session_key.data[0]++;
919 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
920 memcpy(&u.info25.password.data[516], confounder, 16);
922 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
924 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
925 "SetUserInfo failed");
926 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
927 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
928 s.in.level, nt_errstr(s.out.result));
929 ret = false;
932 return ret;
935 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
936 struct policy_handle *handle, char **password)
938 NTSTATUS status;
939 struct samr_SetUserInfo s;
940 union samr_UserInfo u;
941 bool ret = true;
942 DATA_BLOB session_key;
943 char *newpass;
944 struct dcerpc_binding_handle *b = p->binding_handle;
945 struct samr_GetUserPwInfo pwp;
946 struct samr_PwInfo info;
947 int policy_min_pw_len = 0;
948 uint8_t lm_hash[16], nt_hash[16];
950 pwp.in.user_handle = handle;
951 pwp.out.info = &info;
953 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
954 "GetUserPwInfo failed");
955 if (NT_STATUS_IS_OK(pwp.out.result)) {
956 policy_min_pw_len = pwp.out.info->min_password_length;
958 newpass = samr_rand_pass(tctx, policy_min_pw_len);
960 s.in.user_handle = handle;
961 s.in.info = &u;
962 s.in.level = 18;
964 ZERO_STRUCT(u);
966 u.info18.nt_pwd_active = true;
967 u.info18.lm_pwd_active = true;
969 E_md4hash(newpass, nt_hash);
970 E_deshash(newpass, lm_hash);
972 status = dcerpc_fetch_session_key(p, &session_key);
973 if (!NT_STATUS_IS_OK(status)) {
974 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
975 s.in.level, nt_errstr(status));
976 return false;
980 DATA_BLOB in,out;
981 in = data_blob_const(nt_hash, 16);
982 out = data_blob_talloc_zero(tctx, 16);
983 sess_crypt_blob(&out, &in, &session_key, true);
984 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
987 DATA_BLOB in,out;
988 in = data_blob_const(lm_hash, 16);
989 out = data_blob_talloc_zero(tctx, 16);
990 sess_crypt_blob(&out, &in, &session_key, true);
991 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
994 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
996 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
997 "SetUserInfo failed");
998 if (!NT_STATUS_IS_OK(s.out.result)) {
999 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1000 s.in.level, nt_errstr(s.out.result));
1001 ret = false;
1002 } else {
1003 *password = newpass;
1006 return ret;
1009 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1010 struct policy_handle *handle, uint32_t fields_present,
1011 char **password)
1013 NTSTATUS status;
1014 struct samr_SetUserInfo s;
1015 union samr_UserInfo u;
1016 bool ret = true;
1017 DATA_BLOB session_key;
1018 char *newpass;
1019 struct dcerpc_binding_handle *b = p->binding_handle;
1020 struct samr_GetUserPwInfo pwp;
1021 struct samr_PwInfo info;
1022 int policy_min_pw_len = 0;
1023 uint8_t lm_hash[16], nt_hash[16];
1025 pwp.in.user_handle = handle;
1026 pwp.out.info = &info;
1028 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1029 "GetUserPwInfo failed");
1030 if (NT_STATUS_IS_OK(pwp.out.result)) {
1031 policy_min_pw_len = pwp.out.info->min_password_length;
1033 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1035 s.in.user_handle = handle;
1036 s.in.info = &u;
1037 s.in.level = 21;
1039 E_md4hash(newpass, nt_hash);
1040 E_deshash(newpass, lm_hash);
1042 ZERO_STRUCT(u);
1044 u.info21.fields_present = fields_present;
1046 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1047 u.info21.lm_owf_password.length = 16;
1048 u.info21.lm_owf_password.size = 16;
1049 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1050 u.info21.lm_password_set = true;
1053 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1054 u.info21.nt_owf_password.length = 16;
1055 u.info21.nt_owf_password.size = 16;
1056 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1057 u.info21.nt_password_set = true;
1060 status = dcerpc_fetch_session_key(p, &session_key);
1061 if (!NT_STATUS_IS_OK(status)) {
1062 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1063 s.in.level, nt_errstr(status));
1064 return false;
1067 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1068 DATA_BLOB in,out;
1069 in = data_blob_const(u.info21.lm_owf_password.array,
1070 u.info21.lm_owf_password.length);
1071 out = data_blob_talloc_zero(tctx, 16);
1072 sess_crypt_blob(&out, &in, &session_key, true);
1073 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1076 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1077 DATA_BLOB in,out;
1078 in = data_blob_const(u.info21.nt_owf_password.array,
1079 u.info21.nt_owf_password.length);
1080 out = data_blob_talloc_zero(tctx, 16);
1081 sess_crypt_blob(&out, &in, &session_key, true);
1082 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1085 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1087 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1088 "SetUserInfo failed");
1089 if (!NT_STATUS_IS_OK(s.out.result)) {
1090 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1091 s.in.level, nt_errstr(s.out.result));
1092 ret = false;
1093 } else {
1094 *password = newpass;
1097 /* try invalid length */
1098 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1100 u.info21.nt_owf_password.length++;
1102 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1103 "SetUserInfo failed");
1104 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1105 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1106 s.in.level, nt_errstr(s.out.result));
1107 ret = false;
1111 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1113 u.info21.lm_owf_password.length++;
1115 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1116 "SetUserInfo failed");
1117 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1118 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1119 s.in.level, nt_errstr(s.out.result));
1120 ret = false;
1124 return ret;
1127 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1128 struct torture_context *tctx,
1129 struct policy_handle *handle,
1130 uint16_t level,
1131 uint32_t fields_present,
1132 char **password, uint8_t password_expired,
1133 bool use_setinfo2,
1134 bool *matched_expected_error)
1136 NTSTATUS status;
1137 NTSTATUS expected_error = NT_STATUS_OK;
1138 struct samr_SetUserInfo s;
1139 struct samr_SetUserInfo2 s2;
1140 union samr_UserInfo u;
1141 bool ret = true;
1142 DATA_BLOB session_key;
1143 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1144 struct MD5Context ctx;
1145 uint8_t confounder[16];
1146 char *newpass;
1147 struct dcerpc_binding_handle *b = p->binding_handle;
1148 struct samr_GetUserPwInfo pwp;
1149 struct samr_PwInfo info;
1150 int policy_min_pw_len = 0;
1151 const char *comment = NULL;
1152 uint8_t lm_hash[16], nt_hash[16];
1154 pwp.in.user_handle = handle;
1155 pwp.out.info = &info;
1157 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1158 "GetUserPwInfo failed");
1159 if (NT_STATUS_IS_OK(pwp.out.result)) {
1160 policy_min_pw_len = pwp.out.info->min_password_length;
1162 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1164 if (use_setinfo2) {
1165 s2.in.user_handle = handle;
1166 s2.in.info = &u;
1167 s2.in.level = level;
1168 } else {
1169 s.in.user_handle = handle;
1170 s.in.info = &u;
1171 s.in.level = level;
1174 if (fields_present & SAMR_FIELD_COMMENT) {
1175 comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
1178 ZERO_STRUCT(u);
1180 switch (level) {
1181 case 18:
1182 E_md4hash(newpass, nt_hash);
1183 E_deshash(newpass, lm_hash);
1185 u.info18.nt_pwd_active = true;
1186 u.info18.lm_pwd_active = true;
1187 u.info18.password_expired = password_expired;
1189 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1190 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1192 break;
1193 case 21:
1194 E_md4hash(newpass, nt_hash);
1195 E_deshash(newpass, lm_hash);
1197 u.info21.fields_present = fields_present;
1198 u.info21.password_expired = password_expired;
1199 u.info21.comment.string = comment;
1201 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1202 u.info21.lm_owf_password.length = 16;
1203 u.info21.lm_owf_password.size = 16;
1204 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1205 u.info21.lm_password_set = true;
1208 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1209 u.info21.nt_owf_password.length = 16;
1210 u.info21.nt_owf_password.size = 16;
1211 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1212 u.info21.nt_password_set = true;
1215 break;
1216 case 23:
1217 u.info23.info.fields_present = fields_present;
1218 u.info23.info.password_expired = password_expired;
1219 u.info23.info.comment.string = comment;
1221 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1223 break;
1224 case 24:
1225 u.info24.password_expired = password_expired;
1227 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1229 break;
1230 case 25:
1231 u.info25.info.fields_present = fields_present;
1232 u.info25.info.password_expired = password_expired;
1233 u.info25.info.comment.string = comment;
1235 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1237 break;
1238 case 26:
1239 u.info26.password_expired = password_expired;
1241 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1243 break;
1246 status = dcerpc_fetch_session_key(p, &session_key);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1249 s.in.level, nt_errstr(status));
1250 return false;
1253 generate_random_buffer((uint8_t *)confounder, 16);
1255 MD5Init(&ctx);
1256 MD5Update(&ctx, confounder, 16);
1257 MD5Update(&ctx, session_key.data, session_key.length);
1258 MD5Final(confounded_session_key.data, &ctx);
1260 switch (level) {
1261 case 18:
1263 DATA_BLOB in,out;
1264 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1265 out = data_blob_talloc_zero(tctx, 16);
1266 sess_crypt_blob(&out, &in, &session_key, true);
1267 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1270 DATA_BLOB in,out;
1271 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1272 out = data_blob_talloc_zero(tctx, 16);
1273 sess_crypt_blob(&out, &in, &session_key, true);
1274 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1277 break;
1278 case 21:
1279 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1280 DATA_BLOB in,out;
1281 in = data_blob_const(u.info21.lm_owf_password.array,
1282 u.info21.lm_owf_password.length);
1283 out = data_blob_talloc_zero(tctx, 16);
1284 sess_crypt_blob(&out, &in, &session_key, true);
1285 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1287 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1288 DATA_BLOB in,out;
1289 in = data_blob_const(u.info21.nt_owf_password.array,
1290 u.info21.nt_owf_password.length);
1291 out = data_blob_talloc_zero(tctx, 16);
1292 sess_crypt_blob(&out, &in, &session_key, true);
1293 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1295 break;
1296 case 23:
1297 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1298 break;
1299 case 24:
1300 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1301 break;
1302 case 25:
1303 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1304 memcpy(&u.info25.password.data[516], confounder, 16);
1305 break;
1306 case 26:
1307 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1308 memcpy(&u.info26.password.data[516], confounder, 16);
1309 break;
1312 if (use_setinfo2) {
1313 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1314 "SetUserInfo2 failed");
1315 status = s2.out.result;
1316 } else {
1317 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1318 "SetUserInfo failed");
1319 status = s.out.result;
1322 if (!NT_STATUS_IS_OK(status)) {
1323 if (fields_present == 0) {
1324 expected_error = NT_STATUS_INVALID_PARAMETER;
1326 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1327 expected_error = NT_STATUS_ACCESS_DENIED;
1331 if (!NT_STATUS_IS_OK(expected_error)) {
1332 if (use_setinfo2) {
1333 torture_assert_ntstatus_equal(tctx,
1334 s2.out.result,
1335 expected_error, "SetUserInfo2 failed");
1336 } else {
1337 torture_assert_ntstatus_equal(tctx,
1338 s.out.result,
1339 expected_error, "SetUserInfo failed");
1341 *matched_expected_error = true;
1342 return true;
1345 if (!NT_STATUS_IS_OK(status)) {
1346 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1347 use_setinfo2 ? "2":"", level, nt_errstr(status));
1348 ret = false;
1349 } else {
1350 *password = newpass;
1353 return ret;
1356 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1357 struct torture_context *tctx,
1358 struct policy_handle *handle)
1360 struct samr_SetAliasInfo r;
1361 struct samr_QueryAliasInfo q;
1362 union samr_AliasInfo *info;
1363 uint16_t levels[] = {2, 3};
1364 int i;
1365 bool ret = true;
1367 /* Ignoring switch level 1, as that includes the number of members for the alias
1368 * and setting this to a wrong value might have negative consequences
1371 for (i=0;i<ARRAY_SIZE(levels);i++) {
1372 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1374 r.in.alias_handle = handle;
1375 r.in.level = levels[i];
1376 r.in.info = talloc(tctx, union samr_AliasInfo);
1377 switch (r.in.level) {
1378 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1379 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1380 "Test Description, should test I18N as well"); break;
1381 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1384 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1385 "SetAliasInfo failed");
1386 if (!NT_STATUS_IS_OK(r.out.result)) {
1387 torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1388 levels[i], nt_errstr(r.out.result));
1389 ret = false;
1392 q.in.alias_handle = handle;
1393 q.in.level = levels[i];
1394 q.out.info = &info;
1396 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1397 "QueryAliasInfo failed");
1398 if (!NT_STATUS_IS_OK(q.out.result)) {
1399 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1400 levels[i], nt_errstr(q.out.result));
1401 ret = false;
1405 return ret;
1408 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1409 struct torture_context *tctx,
1410 struct policy_handle *user_handle)
1412 struct samr_GetGroupsForUser r;
1413 struct samr_RidWithAttributeArray *rids = NULL;
1415 torture_comment(tctx, "Testing GetGroupsForUser\n");
1417 r.in.user_handle = user_handle;
1418 r.out.rids = &rids;
1420 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1421 "GetGroupsForUser failed");
1422 torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1424 return true;
1428 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1429 struct lsa_String *domain_name)
1431 struct samr_GetDomPwInfo r;
1432 struct samr_PwInfo info;
1433 struct dcerpc_binding_handle *b = p->binding_handle;
1435 r.in.domain_name = domain_name;
1436 r.out.info = &info;
1438 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1440 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1441 "GetDomPwInfo failed");
1442 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1444 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1445 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1447 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1448 "GetDomPwInfo failed");
1449 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1451 r.in.domain_name->string = "\\\\__NONAME__";
1452 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1454 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1455 "GetDomPwInfo failed");
1456 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1458 r.in.domain_name->string = "\\\\Builtin";
1459 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1461 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1462 "GetDomPwInfo failed");
1463 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1465 return true;
1468 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1469 struct torture_context *tctx,
1470 struct policy_handle *handle)
1472 struct samr_GetUserPwInfo r;
1473 struct samr_PwInfo info;
1475 torture_comment(tctx, "Testing GetUserPwInfo\n");
1477 r.in.user_handle = handle;
1478 r.out.info = &info;
1480 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1481 "GetUserPwInfo failed");
1482 torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1484 return true;
1487 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1488 struct torture_context *tctx,
1489 struct policy_handle *domain_handle, const char *name,
1490 uint32_t *rid)
1492 NTSTATUS status;
1493 struct samr_LookupNames n;
1494 struct lsa_String sname[2];
1495 struct samr_Ids rids, types;
1497 init_lsa_String(&sname[0], name);
1499 n.in.domain_handle = domain_handle;
1500 n.in.num_names = 1;
1501 n.in.names = sname;
1502 n.out.rids = &rids;
1503 n.out.types = &types;
1504 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1505 if (!NT_STATUS_IS_OK(status)) {
1506 return status;
1508 if (NT_STATUS_IS_OK(n.out.result)) {
1509 *rid = n.out.rids->ids[0];
1510 } else {
1511 return n.out.result;
1514 init_lsa_String(&sname[1], "xxNONAMExx");
1515 n.in.num_names = 2;
1516 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1517 if (!NT_STATUS_IS_OK(status)) {
1518 return status;
1520 if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1521 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1522 if (NT_STATUS_IS_OK(n.out.result)) {
1523 return NT_STATUS_UNSUCCESSFUL;
1525 return n.out.result;
1528 n.in.num_names = 0;
1529 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1530 if (!NT_STATUS_IS_OK(status)) {
1531 return status;
1533 if (!NT_STATUS_IS_OK(n.out.result)) {
1534 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1535 return n.out.result;
1538 init_lsa_String(&sname[0], "xxNONAMExx");
1539 n.in.num_names = 1;
1540 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 return status;
1544 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1545 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1546 if (NT_STATUS_IS_OK(n.out.result)) {
1547 return NT_STATUS_UNSUCCESSFUL;
1549 return n.out.result;
1552 init_lsa_String(&sname[0], "xxNONAMExx");
1553 init_lsa_String(&sname[1], "xxNONAME2xx");
1554 n.in.num_names = 2;
1555 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1556 if (!NT_STATUS_IS_OK(status)) {
1557 return status;
1559 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1560 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1561 if (NT_STATUS_IS_OK(n.out.result)) {
1562 return NT_STATUS_UNSUCCESSFUL;
1564 return n.out.result;
1567 return NT_STATUS_OK;
1570 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1571 struct torture_context *tctx,
1572 struct policy_handle *domain_handle,
1573 const char *name, struct policy_handle *user_handle)
1575 NTSTATUS status;
1576 struct samr_OpenUser r;
1577 uint32_t rid;
1579 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1580 if (!NT_STATUS_IS_OK(status)) {
1581 return status;
1584 r.in.domain_handle = domain_handle;
1585 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1586 r.in.rid = rid;
1587 r.out.user_handle = user_handle;
1588 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1589 if (!NT_STATUS_IS_OK(status)) {
1590 return status;
1592 if (!NT_STATUS_IS_OK(r.out.result)) {
1593 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1596 return r.out.result;
1599 #if 0
1600 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1601 struct torture_context *tctx,
1602 struct policy_handle *handle)
1604 NTSTATUS status;
1605 struct samr_ChangePasswordUser r;
1606 bool ret = true;
1607 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1608 struct policy_handle user_handle;
1609 char *oldpass = "test";
1610 char *newpass = "test2";
1611 uint8_t old_nt_hash[16], new_nt_hash[16];
1612 uint8_t old_lm_hash[16], new_lm_hash[16];
1614 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1615 if (!NT_STATUS_IS_OK(status)) {
1616 return false;
1619 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1621 torture_comment(tctx, "old password: %s\n", oldpass);
1622 torture_comment(tctx, "new password: %s\n", newpass);
1624 E_md4hash(oldpass, old_nt_hash);
1625 E_md4hash(newpass, new_nt_hash);
1626 E_deshash(oldpass, old_lm_hash);
1627 E_deshash(newpass, new_lm_hash);
1629 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1630 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1631 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1632 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1633 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1634 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1636 r.in.handle = &user_handle;
1637 r.in.lm_present = 1;
1638 r.in.old_lm_crypted = &hash1;
1639 r.in.new_lm_crypted = &hash2;
1640 r.in.nt_present = 1;
1641 r.in.old_nt_crypted = &hash3;
1642 r.in.new_nt_crypted = &hash4;
1643 r.in.cross1_present = 1;
1644 r.in.nt_cross = &hash5;
1645 r.in.cross2_present = 1;
1646 r.in.lm_cross = &hash6;
1648 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1649 "ChangePasswordUser failed");
1650 if (!NT_STATUS_IS_OK(r.out.result)) {
1651 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1652 ret = false;
1655 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1656 ret = false;
1659 return ret;
1661 #endif
1663 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1664 struct torture_context *tctx,
1665 const char *acct_name,
1666 struct policy_handle *handle, char **password)
1668 NTSTATUS status;
1669 struct samr_ChangePasswordUser r;
1670 bool ret = true;
1671 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1672 struct policy_handle user_handle;
1673 char *oldpass;
1674 uint8_t old_nt_hash[16], new_nt_hash[16];
1675 uint8_t old_lm_hash[16], new_lm_hash[16];
1676 bool changed = true;
1678 char *newpass;
1679 struct samr_GetUserPwInfo pwp;
1680 struct samr_PwInfo info;
1681 int policy_min_pw_len = 0;
1683 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1684 if (!NT_STATUS_IS_OK(status)) {
1685 return false;
1687 pwp.in.user_handle = &user_handle;
1688 pwp.out.info = &info;
1690 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1691 "GetUserPwInfo failed");
1692 if (NT_STATUS_IS_OK(pwp.out.result)) {
1693 policy_min_pw_len = pwp.out.info->min_password_length;
1695 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1697 torture_comment(tctx, "Testing ChangePasswordUser\n");
1699 torture_assert(tctx, *password != NULL,
1700 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1702 oldpass = *password;
1704 E_md4hash(oldpass, old_nt_hash);
1705 E_md4hash(newpass, new_nt_hash);
1706 E_deshash(oldpass, old_lm_hash);
1707 E_deshash(newpass, new_lm_hash);
1709 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1710 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1711 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1712 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1713 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1714 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1716 r.in.user_handle = &user_handle;
1717 r.in.lm_present = 1;
1718 /* Break the LM hash */
1719 hash1.hash[0]++;
1720 r.in.old_lm_crypted = &hash1;
1721 r.in.new_lm_crypted = &hash2;
1722 r.in.nt_present = 1;
1723 r.in.old_nt_crypted = &hash3;
1724 r.in.new_nt_crypted = &hash4;
1725 r.in.cross1_present = 1;
1726 r.in.nt_cross = &hash5;
1727 r.in.cross2_present = 1;
1728 r.in.lm_cross = &hash6;
1730 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1731 "ChangePasswordUser failed");
1732 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1733 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1735 /* Unbreak the LM hash */
1736 hash1.hash[0]--;
1738 r.in.user_handle = &user_handle;
1739 r.in.lm_present = 1;
1740 r.in.old_lm_crypted = &hash1;
1741 r.in.new_lm_crypted = &hash2;
1742 /* Break the NT hash */
1743 hash3.hash[0]--;
1744 r.in.nt_present = 1;
1745 r.in.old_nt_crypted = &hash3;
1746 r.in.new_nt_crypted = &hash4;
1747 r.in.cross1_present = 1;
1748 r.in.nt_cross = &hash5;
1749 r.in.cross2_present = 1;
1750 r.in.lm_cross = &hash6;
1752 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1753 "ChangePasswordUser failed");
1754 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1755 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1757 /* Unbreak the NT hash */
1758 hash3.hash[0]--;
1760 r.in.user_handle = &user_handle;
1761 r.in.lm_present = 1;
1762 r.in.old_lm_crypted = &hash1;
1763 r.in.new_lm_crypted = &hash2;
1764 r.in.nt_present = 1;
1765 r.in.old_nt_crypted = &hash3;
1766 r.in.new_nt_crypted = &hash4;
1767 r.in.cross1_present = 1;
1768 r.in.nt_cross = &hash5;
1769 r.in.cross2_present = 1;
1770 /* Break the LM cross */
1771 hash6.hash[0]++;
1772 r.in.lm_cross = &hash6;
1774 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1775 "ChangePasswordUser failed");
1776 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1777 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));
1778 ret = false;
1781 /* Unbreak the LM cross */
1782 hash6.hash[0]--;
1784 r.in.user_handle = &user_handle;
1785 r.in.lm_present = 1;
1786 r.in.old_lm_crypted = &hash1;
1787 r.in.new_lm_crypted = &hash2;
1788 r.in.nt_present = 1;
1789 r.in.old_nt_crypted = &hash3;
1790 r.in.new_nt_crypted = &hash4;
1791 r.in.cross1_present = 1;
1792 /* Break the NT cross */
1793 hash5.hash[0]++;
1794 r.in.nt_cross = &hash5;
1795 r.in.cross2_present = 1;
1796 r.in.lm_cross = &hash6;
1798 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1799 "ChangePasswordUser failed");
1800 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1801 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));
1802 ret = false;
1805 /* Unbreak the NT cross */
1806 hash5.hash[0]--;
1809 /* Reset the hashes to not broken values */
1810 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1811 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1812 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1813 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1814 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1815 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1817 r.in.user_handle = &user_handle;
1818 r.in.lm_present = 1;
1819 r.in.old_lm_crypted = &hash1;
1820 r.in.new_lm_crypted = &hash2;
1821 r.in.nt_present = 1;
1822 r.in.old_nt_crypted = &hash3;
1823 r.in.new_nt_crypted = &hash4;
1824 r.in.cross1_present = 1;
1825 r.in.nt_cross = &hash5;
1826 r.in.cross2_present = 0;
1827 r.in.lm_cross = NULL;
1829 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1830 "ChangePasswordUser failed");
1831 if (NT_STATUS_IS_OK(r.out.result)) {
1832 changed = true;
1833 *password = newpass;
1834 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1835 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1836 ret = false;
1839 oldpass = newpass;
1840 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1842 E_md4hash(oldpass, old_nt_hash);
1843 E_md4hash(newpass, new_nt_hash);
1844 E_deshash(oldpass, old_lm_hash);
1845 E_deshash(newpass, new_lm_hash);
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 = 0;
1864 r.in.nt_cross = NULL;
1865 r.in.cross2_present = 1;
1866 r.in.lm_cross = &hash6;
1868 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1869 "ChangePasswordUser failed");
1870 if (NT_STATUS_IS_OK(r.out.result)) {
1871 changed = true;
1872 *password = newpass;
1873 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1874 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1875 ret = false;
1878 oldpass = newpass;
1879 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1881 E_md4hash(oldpass, old_nt_hash);
1882 E_md4hash(newpass, new_nt_hash);
1883 E_deshash(oldpass, old_lm_hash);
1884 E_deshash(newpass, new_lm_hash);
1887 /* Reset the hashes to not broken values */
1888 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1889 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1890 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1891 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1892 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1893 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1895 r.in.user_handle = &user_handle;
1896 r.in.lm_present = 1;
1897 r.in.old_lm_crypted = &hash1;
1898 r.in.new_lm_crypted = &hash2;
1899 r.in.nt_present = 1;
1900 r.in.old_nt_crypted = &hash3;
1901 r.in.new_nt_crypted = &hash4;
1902 r.in.cross1_present = 1;
1903 r.in.nt_cross = &hash5;
1904 r.in.cross2_present = 1;
1905 r.in.lm_cross = &hash6;
1907 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1908 "ChangePasswordUser failed");
1909 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1910 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1911 } else if (!NT_STATUS_IS_OK(r.out.result)) {
1912 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1913 ret = false;
1914 } else {
1915 changed = true;
1916 *password = newpass;
1919 r.in.user_handle = &user_handle;
1920 r.in.lm_present = 1;
1921 r.in.old_lm_crypted = &hash1;
1922 r.in.new_lm_crypted = &hash2;
1923 r.in.nt_present = 1;
1924 r.in.old_nt_crypted = &hash3;
1925 r.in.new_nt_crypted = &hash4;
1926 r.in.cross1_present = 1;
1927 r.in.nt_cross = &hash5;
1928 r.in.cross2_present = 1;
1929 r.in.lm_cross = &hash6;
1931 if (changed) {
1932 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1933 "ChangePasswordUser failed");
1934 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1935 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1936 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1937 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
1938 ret = false;
1943 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
1944 ret = false;
1947 return ret;
1951 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
1952 struct torture_context *tctx,
1953 const char *acct_name,
1954 struct policy_handle *handle, char **password)
1956 struct samr_OemChangePasswordUser2 r;
1957 bool ret = true;
1958 struct samr_Password lm_verifier;
1959 struct samr_CryptPassword lm_pass;
1960 struct lsa_AsciiString server, account, account_bad;
1961 char *oldpass;
1962 char *newpass;
1963 struct dcerpc_binding_handle *b = p->binding_handle;
1964 uint8_t old_lm_hash[16], new_lm_hash[16];
1966 struct samr_GetDomPwInfo dom_pw_info;
1967 struct samr_PwInfo info;
1968 int policy_min_pw_len = 0;
1970 struct lsa_String domain_name;
1972 domain_name.string = "";
1973 dom_pw_info.in.domain_name = &domain_name;
1974 dom_pw_info.out.info = &info;
1976 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1978 torture_assert(tctx, *password != NULL,
1979 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1981 oldpass = *password;
1983 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
1984 "GetDomPwInfo failed");
1985 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
1986 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1989 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1991 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1992 account.string = acct_name;
1994 E_deshash(oldpass, old_lm_hash);
1995 E_deshash(newpass, new_lm_hash);
1997 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1998 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1999 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2001 r.in.server = &server;
2002 r.in.account = &account;
2003 r.in.password = &lm_pass;
2004 r.in.hash = &lm_verifier;
2006 /* Break the verification */
2007 lm_verifier.hash[0]++;
2009 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2010 "OemChangePasswordUser2 failed");
2012 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2013 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2014 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2015 nt_errstr(r.out.result));
2016 ret = false;
2019 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2020 /* Break the old password */
2021 old_lm_hash[0]++;
2022 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2023 /* unbreak it for the next operation */
2024 old_lm_hash[0]--;
2025 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2027 r.in.server = &server;
2028 r.in.account = &account;
2029 r.in.password = &lm_pass;
2030 r.in.hash = &lm_verifier;
2032 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2033 "OemChangePasswordUser2 failed");
2035 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2036 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2037 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2038 nt_errstr(r.out.result));
2039 ret = false;
2042 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2043 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2045 r.in.server = &server;
2046 r.in.account = &account;
2047 r.in.password = &lm_pass;
2048 r.in.hash = NULL;
2050 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2051 "OemChangePasswordUser2 failed");
2053 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2054 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2055 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2056 nt_errstr(r.out.result));
2057 ret = false;
2060 /* This shouldn't be a valid name */
2061 account_bad.string = TEST_ACCOUNT_NAME "XX";
2062 r.in.account = &account_bad;
2064 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2065 "OemChangePasswordUser2 failed");
2067 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2068 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2069 nt_errstr(r.out.result));
2070 ret = false;
2073 /* This shouldn't be a valid name */
2074 account_bad.string = TEST_ACCOUNT_NAME "XX";
2075 r.in.account = &account_bad;
2076 r.in.password = &lm_pass;
2077 r.in.hash = &lm_verifier;
2079 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2080 "OemChangePasswordUser2 failed");
2082 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2083 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2084 nt_errstr(r.out.result));
2085 ret = false;
2088 /* This shouldn't be a valid name */
2089 account_bad.string = TEST_ACCOUNT_NAME "XX";
2090 r.in.account = &account_bad;
2091 r.in.password = NULL;
2092 r.in.hash = &lm_verifier;
2094 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2095 "OemChangePasswordUser2 failed");
2097 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2098 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2099 nt_errstr(r.out.result));
2100 ret = false;
2103 E_deshash(oldpass, old_lm_hash);
2104 E_deshash(newpass, new_lm_hash);
2106 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2107 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2108 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2110 r.in.server = &server;
2111 r.in.account = &account;
2112 r.in.password = &lm_pass;
2113 r.in.hash = &lm_verifier;
2115 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2116 "OemChangePasswordUser2 failed");
2118 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2119 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2120 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2121 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2122 ret = false;
2123 } else {
2124 *password = newpass;
2127 return ret;
2131 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2132 const char *acct_name,
2133 char **password,
2134 char *newpass, bool allow_password_restriction)
2136 struct samr_ChangePasswordUser2 r;
2137 bool ret = true;
2138 struct lsa_String server, account;
2139 struct samr_CryptPassword nt_pass, lm_pass;
2140 struct samr_Password nt_verifier, lm_verifier;
2141 char *oldpass;
2142 struct dcerpc_binding_handle *b = p->binding_handle;
2143 uint8_t old_nt_hash[16], new_nt_hash[16];
2144 uint8_t old_lm_hash[16], new_lm_hash[16];
2146 struct samr_GetDomPwInfo dom_pw_info;
2147 struct samr_PwInfo info;
2149 struct lsa_String domain_name;
2151 domain_name.string = "";
2152 dom_pw_info.in.domain_name = &domain_name;
2153 dom_pw_info.out.info = &info;
2155 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2157 torture_assert(tctx, *password != NULL,
2158 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2159 oldpass = *password;
2161 if (!newpass) {
2162 int policy_min_pw_len = 0;
2163 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2164 "GetDomPwInfo failed");
2165 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2166 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2169 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2172 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2173 init_lsa_String(&account, acct_name);
2175 E_md4hash(oldpass, old_nt_hash);
2176 E_md4hash(newpass, new_nt_hash);
2178 E_deshash(oldpass, old_lm_hash);
2179 E_deshash(newpass, new_lm_hash);
2181 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2182 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2183 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2185 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2186 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2187 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2189 r.in.server = &server;
2190 r.in.account = &account;
2191 r.in.nt_password = &nt_pass;
2192 r.in.nt_verifier = &nt_verifier;
2193 r.in.lm_change = 1;
2194 r.in.lm_password = &lm_pass;
2195 r.in.lm_verifier = &lm_verifier;
2197 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2198 "ChangePasswordUser2 failed");
2200 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2201 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2202 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2203 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2204 ret = false;
2205 } else {
2206 *password = newpass;
2209 return ret;
2213 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2214 const char *account_string,
2215 int policy_min_pw_len,
2216 char **password,
2217 const char *newpass,
2218 NTTIME last_password_change,
2219 bool handle_reject_reason)
2221 struct samr_ChangePasswordUser3 r;
2222 bool ret = true;
2223 struct lsa_String server, account, account_bad;
2224 struct samr_CryptPassword nt_pass, lm_pass;
2225 struct samr_Password nt_verifier, lm_verifier;
2226 char *oldpass;
2227 struct dcerpc_binding_handle *b = p->binding_handle;
2228 uint8_t old_nt_hash[16], new_nt_hash[16];
2229 uint8_t old_lm_hash[16], new_lm_hash[16];
2230 NTTIME t;
2231 struct samr_DomInfo1 *dominfo = NULL;
2232 struct userPwdChangeFailureInformation *reject = NULL;
2234 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2236 if (newpass == NULL) {
2237 do {
2238 if (policy_min_pw_len == 0) {
2239 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2240 } else {
2241 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2243 } while (check_password_quality(newpass) == false);
2244 } else {
2245 torture_comment(tctx, "Using password '%s'\n", newpass);
2248 torture_assert(tctx, *password != NULL,
2249 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2251 oldpass = *password;
2252 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2253 init_lsa_String(&account, account_string);
2255 E_md4hash(oldpass, old_nt_hash);
2256 E_md4hash(newpass, new_nt_hash);
2258 E_deshash(oldpass, old_lm_hash);
2259 E_deshash(newpass, new_lm_hash);
2261 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2262 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2263 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2265 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2266 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2267 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2269 /* Break the verification */
2270 nt_verifier.hash[0]++;
2272 r.in.server = &server;
2273 r.in.account = &account;
2274 r.in.nt_password = &nt_pass;
2275 r.in.nt_verifier = &nt_verifier;
2276 r.in.lm_change = 1;
2277 r.in.lm_password = &lm_pass;
2278 r.in.lm_verifier = &lm_verifier;
2279 r.in.password3 = NULL;
2280 r.out.dominfo = &dominfo;
2281 r.out.reject = &reject;
2283 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2284 "ChangePasswordUser3 failed");
2285 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2286 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2287 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2288 nt_errstr(r.out.result));
2289 ret = false;
2292 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2293 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2294 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2296 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2297 /* Break the NT hash */
2298 old_nt_hash[0]++;
2299 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2300 /* Unbreak it again */
2301 old_nt_hash[0]--;
2302 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2304 r.in.server = &server;
2305 r.in.account = &account;
2306 r.in.nt_password = &nt_pass;
2307 r.in.nt_verifier = &nt_verifier;
2308 r.in.lm_change = 1;
2309 r.in.lm_password = &lm_pass;
2310 r.in.lm_verifier = &lm_verifier;
2311 r.in.password3 = NULL;
2312 r.out.dominfo = &dominfo;
2313 r.out.reject = &reject;
2315 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2316 "ChangePasswordUser3 failed");
2317 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2318 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2319 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2320 nt_errstr(r.out.result));
2321 ret = false;
2324 /* This shouldn't be a valid name */
2325 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2327 r.in.account = &account_bad;
2328 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2329 "ChangePasswordUser3 failed");
2330 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2331 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2332 nt_errstr(r.out.result));
2333 ret = false;
2336 E_md4hash(oldpass, old_nt_hash);
2337 E_md4hash(newpass, new_nt_hash);
2339 E_deshash(oldpass, old_lm_hash);
2340 E_deshash(newpass, new_lm_hash);
2342 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2343 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2344 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2346 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2347 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2348 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2350 r.in.server = &server;
2351 r.in.account = &account;
2352 r.in.nt_password = &nt_pass;
2353 r.in.nt_verifier = &nt_verifier;
2354 r.in.lm_change = 1;
2355 r.in.lm_password = &lm_pass;
2356 r.in.lm_verifier = &lm_verifier;
2357 r.in.password3 = NULL;
2358 r.out.dominfo = &dominfo;
2359 r.out.reject = &reject;
2361 unix_to_nt_time(&t, time(NULL));
2363 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2364 "ChangePasswordUser3 failed");
2366 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2367 && dominfo
2368 && reject
2369 && handle_reject_reason
2370 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2371 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2373 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2374 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2375 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2376 return false;
2380 /* We tested the order of precendence which is as follows:
2382 * pwd min_age
2383 * pwd length
2384 * pwd complexity
2385 * pwd history
2387 Guenther */
2389 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2390 (last_password_change + dominfo->min_password_age > t)) {
2392 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2393 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2394 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2395 return false;
2398 } else if ((dominfo->min_password_length > 0) &&
2399 (strlen(newpass) < dominfo->min_password_length)) {
2401 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2402 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2403 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2404 return false;
2407 } else if ((dominfo->password_history_length > 0) &&
2408 strequal(oldpass, newpass)) {
2410 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2411 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2412 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2413 return false;
2415 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2417 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2418 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2419 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2420 return false;
2425 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2426 /* retry with adjusted size */
2427 return test_ChangePasswordUser3(p, tctx, account_string,
2428 dominfo->min_password_length,
2429 password, NULL, 0, false);
2433 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2434 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2435 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2436 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2437 return false;
2439 /* Perhaps the server has a 'min password age' set? */
2441 } else {
2442 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2444 *password = talloc_strdup(tctx, newpass);
2447 return ret;
2450 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2451 const char *account_string,
2452 struct policy_handle *handle,
2453 char **password)
2455 NTSTATUS status;
2456 struct samr_ChangePasswordUser3 r;
2457 struct samr_SetUserInfo s;
2458 union samr_UserInfo u;
2459 DATA_BLOB session_key;
2460 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2461 uint8_t confounder[16];
2462 struct MD5Context ctx;
2464 bool ret = true;
2465 struct lsa_String server, account;
2466 struct samr_CryptPassword nt_pass;
2467 struct samr_Password nt_verifier;
2468 DATA_BLOB new_random_pass;
2469 char *newpass;
2470 char *oldpass;
2471 struct dcerpc_binding_handle *b = p->binding_handle;
2472 uint8_t old_nt_hash[16], new_nt_hash[16];
2473 NTTIME t;
2474 struct samr_DomInfo1 *dominfo = NULL;
2475 struct userPwdChangeFailureInformation *reject = NULL;
2477 new_random_pass = samr_very_rand_pass(tctx, 128);
2479 torture_assert(tctx, *password != NULL,
2480 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2482 oldpass = *password;
2483 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2484 init_lsa_String(&account, account_string);
2486 s.in.user_handle = handle;
2487 s.in.info = &u;
2488 s.in.level = 25;
2490 ZERO_STRUCT(u);
2492 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2494 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2496 status = dcerpc_fetch_session_key(p, &session_key);
2497 if (!NT_STATUS_IS_OK(status)) {
2498 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2499 s.in.level, nt_errstr(status));
2500 return false;
2503 generate_random_buffer((uint8_t *)confounder, 16);
2505 MD5Init(&ctx);
2506 MD5Update(&ctx, confounder, 16);
2507 MD5Update(&ctx, session_key.data, session_key.length);
2508 MD5Final(confounded_session_key.data, &ctx);
2510 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2511 memcpy(&u.info25.password.data[516], confounder, 16);
2513 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2515 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2516 "SetUserInfo failed");
2517 if (!NT_STATUS_IS_OK(s.out.result)) {
2518 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2519 s.in.level, nt_errstr(s.out.result));
2520 ret = false;
2523 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2525 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2527 new_random_pass = samr_very_rand_pass(tctx, 128);
2529 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2531 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2532 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2533 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2535 r.in.server = &server;
2536 r.in.account = &account;
2537 r.in.nt_password = &nt_pass;
2538 r.in.nt_verifier = &nt_verifier;
2539 r.in.lm_change = 0;
2540 r.in.lm_password = NULL;
2541 r.in.lm_verifier = NULL;
2542 r.in.password3 = NULL;
2543 r.out.dominfo = &dominfo;
2544 r.out.reject = &reject;
2546 unix_to_nt_time(&t, time(NULL));
2548 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2549 "ChangePasswordUser3 failed");
2551 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2552 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2553 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2554 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2555 return false;
2557 /* Perhaps the server has a 'min password age' set? */
2559 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2560 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2561 ret = false;
2564 newpass = samr_rand_pass(tctx, 128);
2566 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2568 E_md4hash(newpass, new_nt_hash);
2570 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2571 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2572 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2574 r.in.server = &server;
2575 r.in.account = &account;
2576 r.in.nt_password = &nt_pass;
2577 r.in.nt_verifier = &nt_verifier;
2578 r.in.lm_change = 0;
2579 r.in.lm_password = NULL;
2580 r.in.lm_verifier = NULL;
2581 r.in.password3 = NULL;
2582 r.out.dominfo = &dominfo;
2583 r.out.reject = &reject;
2585 unix_to_nt_time(&t, time(NULL));
2587 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2588 "ChangePasswordUser3 failed");
2590 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2591 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2592 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2593 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2594 return false;
2596 /* Perhaps the server has a 'min password age' set? */
2598 } else {
2599 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2600 *password = talloc_strdup(tctx, newpass);
2603 return ret;
2607 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2608 struct torture_context *tctx,
2609 struct policy_handle *alias_handle)
2611 struct samr_GetMembersInAlias r;
2612 struct lsa_SidArray sids;
2614 torture_comment(tctx, "Testing GetMembersInAlias\n");
2616 r.in.alias_handle = alias_handle;
2617 r.out.sids = &sids;
2619 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2620 "GetMembersInAlias failed");
2621 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2623 return true;
2626 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2627 struct torture_context *tctx,
2628 struct policy_handle *alias_handle,
2629 const struct dom_sid *domain_sid)
2631 struct samr_AddAliasMember r;
2632 struct samr_DeleteAliasMember d;
2633 struct dom_sid *sid;
2635 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2637 torture_comment(tctx, "Testing AddAliasMember\n");
2638 r.in.alias_handle = alias_handle;
2639 r.in.sid = sid;
2641 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2642 "AddAliasMember failed");
2643 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2645 d.in.alias_handle = alias_handle;
2646 d.in.sid = sid;
2648 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2649 "DeleteAliasMember failed");
2650 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2652 return true;
2655 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2656 struct torture_context *tctx,
2657 struct policy_handle *alias_handle)
2659 struct samr_AddMultipleMembersToAlias a;
2660 struct samr_RemoveMultipleMembersFromAlias r;
2661 struct lsa_SidArray sids;
2663 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2664 a.in.alias_handle = alias_handle;
2665 a.in.sids = &sids;
2667 sids.num_sids = 3;
2668 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2670 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2671 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2672 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2674 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2675 "AddMultipleMembersToAlias failed");
2676 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2679 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2680 r.in.alias_handle = alias_handle;
2681 r.in.sids = &sids;
2683 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2684 "RemoveMultipleMembersFromAlias failed");
2685 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2687 /* strange! removing twice doesn't give any error */
2688 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2689 "RemoveMultipleMembersFromAlias failed");
2690 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2692 /* but removing an alias that isn't there does */
2693 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2695 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2696 "RemoveMultipleMembersFromAlias failed");
2697 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2699 return true;
2702 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2703 struct torture_context *tctx,
2704 struct policy_handle *domain_handle)
2706 struct samr_GetAliasMembership r;
2707 struct lsa_SidArray sids;
2708 struct samr_Ids rids;
2710 torture_comment(tctx, "Testing GetAliasMembership\n");
2712 r.in.domain_handle = domain_handle;
2713 r.in.sids = &sids;
2714 r.out.rids = &rids;
2716 sids.num_sids = 0;
2717 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2719 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2720 "GetAliasMembership failed");
2721 torture_assert_ntstatus_ok(tctx, r.out.result,
2722 "samr_GetAliasMembership failed");
2724 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2725 "protocol misbehaviour");
2727 sids.num_sids = 1;
2728 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2729 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2731 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2732 "samr_GetAliasMembership failed");
2733 torture_assert_ntstatus_ok(tctx, r.out.result,
2734 "samr_GetAliasMembership failed");
2736 #if 0
2737 /* only true for w2k8 it seems
2738 * win7, xp, w2k3 will return a 0 length array pointer */
2740 if (rids.ids && (rids.count == 0)) {
2741 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2743 #endif
2744 if (!rids.ids && rids.count) {
2745 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2748 return true;
2751 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2752 struct torture_context *tctx,
2753 struct policy_handle *user_handle)
2755 struct samr_TestPrivateFunctionsUser r;
2757 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2759 r.in.user_handle = user_handle;
2761 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2762 "TestPrivateFunctionsUser failed");
2763 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2765 return true;
2768 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2769 struct torture_context *tctx,
2770 struct policy_handle *handle,
2771 bool use_info2,
2772 NTTIME *pwdlastset)
2774 NTSTATUS status;
2775 uint16_t levels[] = { /* 3, */ 5, 21 };
2776 int i;
2777 NTTIME pwdlastset3 = 0;
2778 NTTIME pwdlastset5 = 0;
2779 NTTIME pwdlastset21 = 0;
2781 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2782 use_info2 ? "2":"");
2784 for (i=0; i<ARRAY_SIZE(levels); i++) {
2786 struct samr_QueryUserInfo r;
2787 struct samr_QueryUserInfo2 r2;
2788 union samr_UserInfo *info;
2790 if (use_info2) {
2791 r2.in.user_handle = handle;
2792 r2.in.level = levels[i];
2793 r2.out.info = &info;
2794 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2795 "QueryUserInfo2 failed");
2796 status = r2.out.result;
2798 } else {
2799 r.in.user_handle = handle;
2800 r.in.level = levels[i];
2801 r.out.info = &info;
2802 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2803 "QueryUserInfo failed");
2804 status = r.out.result;
2807 if (!NT_STATUS_IS_OK(status) &&
2808 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2809 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2810 use_info2 ? "2":"", levels[i], nt_errstr(status));
2811 return false;
2814 switch (levels[i]) {
2815 case 3:
2816 pwdlastset3 = info->info3.last_password_change;
2817 break;
2818 case 5:
2819 pwdlastset5 = info->info5.last_password_change;
2820 break;
2821 case 21:
2822 pwdlastset21 = info->info21.last_password_change;
2823 break;
2824 default:
2825 return false;
2828 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2829 "pwdlastset mixup"); */
2830 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2831 "pwdlastset mixup");
2833 *pwdlastset = pwdlastset21;
2835 torture_comment(tctx, "(pwdlastset: %llu)\n",
2836 (unsigned long long) *pwdlastset);
2838 return true;
2841 static bool test_SamLogon(struct torture_context *tctx,
2842 struct dcerpc_pipe *p,
2843 struct cli_credentials *test_credentials,
2844 NTSTATUS expected_result,
2845 bool interactive)
2847 NTSTATUS status;
2848 struct netr_LogonSamLogonEx r;
2849 union netr_LogonLevel logon;
2850 union netr_Validation validation;
2851 uint8_t authoritative;
2852 struct netr_IdentityInfo identity;
2853 struct netr_NetworkInfo ninfo;
2854 struct netr_PasswordInfo pinfo;
2855 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2856 int flags = CLI_CRED_NTLM_AUTH;
2857 uint32_t samlogon_flags = 0;
2858 struct netlogon_creds_CredentialState *creds;
2859 struct netr_Authenticator a;
2860 struct dcerpc_binding_handle *b = p->binding_handle;
2862 torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2864 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
2865 flags |= CLI_CRED_LANMAN_AUTH;
2868 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
2869 flags |= CLI_CRED_NTLMv2_AUTH;
2872 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2873 &identity.account_name.string,
2874 &identity.domain_name.string);
2876 identity.parameter_control =
2877 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2878 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2879 identity.logon_id_low = 0;
2880 identity.logon_id_high = 0;
2881 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2883 if (interactive) {
2884 netlogon_creds_client_authenticator(creds, &a);
2886 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
2887 ZERO_STRUCT(pinfo.lmpassword.hash);
2889 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
2891 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
2892 netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
2893 netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
2894 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
2895 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
2896 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
2897 } else {
2898 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
2899 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
2902 pinfo.identity_info = identity;
2903 logon.password = &pinfo;
2905 r.in.logon_level = NetlogonInteractiveInformation;
2906 } else {
2907 generate_random_buffer(ninfo.challenge,
2908 sizeof(ninfo.challenge));
2909 chal = data_blob_const(ninfo.challenge,
2910 sizeof(ninfo.challenge));
2912 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2913 cli_credentials_get_domain(test_credentials));
2915 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2916 &flags,
2917 chal,
2918 names_blob,
2919 &lm_resp, &nt_resp,
2920 NULL, NULL);
2921 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2923 ninfo.lm.data = lm_resp.data;
2924 ninfo.lm.length = lm_resp.length;
2926 ninfo.nt.data = nt_resp.data;
2927 ninfo.nt.length = nt_resp.length;
2929 ninfo.identity_info = identity;
2930 logon.network = &ninfo;
2932 r.in.logon_level = NetlogonNetworkInformation;
2935 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2936 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2937 r.in.logon = &logon;
2938 r.in.flags = &samlogon_flags;
2939 r.out.flags = &samlogon_flags;
2940 r.out.validation = &validation;
2941 r.out.authoritative = &authoritative;
2943 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
2945 r.in.validation_level = 6;
2947 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
2948 "netr_LogonSamLogonEx failed");
2949 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
2950 r.in.validation_level = 3;
2951 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
2952 "netr_LogonSamLogonEx failed");
2954 if (!NT_STATUS_IS_OK(r.out.result)) {
2955 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
2956 return true;
2957 } else {
2958 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
2961 return true;
2964 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2965 struct dcerpc_pipe *p,
2966 struct cli_credentials *machine_creds,
2967 const char *acct_name,
2968 const char *password,
2969 NTSTATUS expected_samlogon_result,
2970 bool interactive)
2972 bool ret = true;
2973 struct cli_credentials *test_credentials;
2975 test_credentials = cli_credentials_init(tctx);
2977 cli_credentials_set_workstation(test_credentials,
2978 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2979 cli_credentials_set_domain(test_credentials,
2980 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2981 cli_credentials_set_username(test_credentials,
2982 acct_name, CRED_SPECIFIED);
2983 cli_credentials_set_password(test_credentials,
2984 password, CRED_SPECIFIED);
2986 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
2987 interactive ? "interactive" : "network", acct_name, password);
2989 if (!test_SamLogon(tctx, p, test_credentials,
2990 expected_samlogon_result, interactive)) {
2991 torture_warning(tctx, "new password did not work\n");
2992 ret = false;
2995 return ret;
2998 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2999 struct dcerpc_pipe *np,
3000 struct torture_context *tctx,
3001 struct policy_handle *handle,
3002 uint16_t level,
3003 uint32_t fields_present,
3004 uint8_t password_expired,
3005 bool *matched_expected_error,
3006 bool use_setinfo2,
3007 const char *acct_name,
3008 char **password,
3009 struct cli_credentials *machine_creds,
3010 bool use_queryinfo2,
3011 NTTIME *pwdlastset,
3012 NTSTATUS expected_samlogon_result)
3014 const char *fields = NULL;
3015 bool ret = true;
3016 struct dcerpc_binding_handle *b = p->binding_handle;
3018 switch (level) {
3019 case 21:
3020 case 23:
3021 case 25:
3022 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3023 fields_present);
3024 break;
3025 default:
3026 break;
3029 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3030 "(password_expired: %d) %s\n",
3031 use_setinfo2 ? "2":"", level, password_expired,
3032 fields ? fields : "");
3034 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3035 fields_present,
3036 password,
3037 password_expired,
3038 use_setinfo2,
3039 matched_expected_error)) {
3040 ret = false;
3043 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3044 use_queryinfo2,
3045 pwdlastset)) {
3046 ret = false;
3049 if (*matched_expected_error == true) {
3050 return ret;
3053 if (!test_SamLogon_with_creds(tctx, np,
3054 machine_creds,
3055 acct_name,
3056 *password,
3057 expected_samlogon_result,
3058 false)) {
3059 ret = false;
3062 return ret;
3065 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3066 struct cli_credentials *credentials,
3067 struct dcerpc_pipe **p)
3069 struct dcerpc_binding *b;
3071 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3072 "failed to get rpc binding");
3074 /* We have to use schannel, otherwise the SamLogonEx fails
3075 * with INTERNAL_ERROR */
3077 b->flags &= ~DCERPC_AUTH_OPTIONS;
3078 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO;
3080 torture_assert_ntstatus_ok(tctx,
3081 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3082 credentials, tctx->ev, tctx->lp_ctx),
3083 "failed to bind to netlogon");
3085 return true;
3088 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3089 struct torture_context *tctx,
3090 uint32_t acct_flags,
3091 const char *acct_name,
3092 struct policy_handle *handle,
3093 char **password,
3094 struct cli_credentials *machine_credentials)
3096 int s = 0, q = 0, f = 0, l = 0, z = 0;
3097 bool ret = true;
3098 int delay = 50000;
3099 bool set_levels[] = { false, true };
3100 bool query_levels[] = { false, true };
3101 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3102 uint32_t nonzeros[] = { 1, 24 };
3103 uint32_t fields_present[] = {
3105 SAMR_FIELD_EXPIRED_FLAG,
3106 SAMR_FIELD_LAST_PWD_CHANGE,
3107 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3108 SAMR_FIELD_COMMENT,
3109 SAMR_FIELD_NT_PASSWORD_PRESENT,
3110 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3111 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3112 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3113 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3114 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3115 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3117 struct dcerpc_pipe *np = NULL;
3119 if (torture_setting_bool(tctx, "samba3", false) ||
3120 torture_setting_bool(tctx, "samba4", false)) {
3121 delay = 999999;
3122 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3123 delay);
3126 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3128 /* set to 1 to enable testing for all possible opcode
3129 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3130 combinations */
3131 #if 0
3132 #define TEST_ALL_LEVELS 1
3133 #define TEST_SET_LEVELS 1
3134 #define TEST_QUERY_LEVELS 1
3135 #endif
3136 #ifdef TEST_ALL_LEVELS
3137 for (l=0; l<ARRAY_SIZE(levels); l++) {
3138 #else
3139 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3140 #endif
3141 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3142 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3143 #ifdef TEST_SET_LEVELS
3144 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3145 #endif
3146 #ifdef TEST_QUERY_LEVELS
3147 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3148 #endif
3149 NTTIME pwdlastset_old = 0;
3150 NTTIME pwdlastset_new = 0;
3151 bool matched_expected_error = false;
3152 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3154 torture_comment(tctx, "------------------------------\n"
3155 "Testing pwdLastSet attribute for flags: 0x%08x "
3156 "(s: %d (l: %d), q: %d)\n",
3157 acct_flags, s, levels[l], q);
3159 switch (levels[l]) {
3160 case 21:
3161 case 23:
3162 case 25:
3163 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3164 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3165 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3167 break;
3171 /* set #1 */
3173 /* set a password and force password change (pwdlastset 0) by
3174 * setting the password expired flag to a non-0 value */
3176 if (!test_SetPassword_level(p, np, tctx, handle,
3177 levels[l],
3178 fields_present[f],
3179 nonzeros[z],
3180 &matched_expected_error,
3181 set_levels[s],
3182 acct_name,
3183 password,
3184 machine_credentials,
3185 query_levels[q],
3186 &pwdlastset_new,
3187 expected_samlogon_result)) {
3188 ret = false;
3191 if (matched_expected_error == true) {
3192 /* skipping on expected failure */
3193 continue;
3196 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3197 * set without the SAMR_FIELD_EXPIRED_FLAG */
3199 switch (levels[l]) {
3200 case 21:
3201 case 23:
3202 case 25:
3203 if ((pwdlastset_new != 0) &&
3204 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3205 torture_comment(tctx, "not considering a non-0 "
3206 "pwdLastSet as a an error as the "
3207 "SAMR_FIELD_EXPIRED_FLAG has not "
3208 "been set\n");
3209 break;
3211 break;
3212 default:
3213 if (pwdlastset_new != 0) {
3214 torture_warning(tctx, "pwdLastSet test failed: "
3215 "expected pwdLastSet 0 but got %llu\n",
3216 (unsigned long long) pwdlastset_old);
3217 ret = false;
3219 break;
3222 switch (levels[l]) {
3223 case 21:
3224 case 23:
3225 case 25:
3226 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3227 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3228 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3229 (pwdlastset_old >= pwdlastset_new)) {
3230 torture_warning(tctx, "pwdlastset not increasing\n");
3231 ret = false;
3233 break;
3236 pwdlastset_old = pwdlastset_new;
3238 usleep(delay);
3240 /* set #2 */
3242 /* set a password, pwdlastset needs to get updated (increased
3243 * value), password_expired value used here is 0 */
3245 if (!test_SetPassword_level(p, np, tctx, handle,
3246 levels[l],
3247 fields_present[f],
3249 &matched_expected_error,
3250 set_levels[s],
3251 acct_name,
3252 password,
3253 machine_credentials,
3254 query_levels[q],
3255 &pwdlastset_new,
3256 expected_samlogon_result)) {
3257 ret = false;
3260 /* when a password has been changed, pwdlastset must not be 0 afterwards
3261 * and must be larger then the old value */
3263 switch (levels[l]) {
3264 case 21:
3265 case 23:
3266 case 25:
3267 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3268 * password has been changed, old and new pwdlastset
3269 * need to be the same value */
3271 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3272 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3273 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3275 torture_assert_int_equal(tctx, pwdlastset_old,
3276 pwdlastset_new, "pwdlastset must be equal");
3277 break;
3279 break;
3280 default:
3281 if (pwdlastset_old >= pwdlastset_new) {
3282 torture_warning(tctx, "pwdLastSet test failed: "
3283 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3284 (unsigned long long) pwdlastset_old,
3285 (unsigned long long) pwdlastset_new);
3286 ret = false;
3288 if (pwdlastset_new == 0) {
3289 torture_warning(tctx, "pwdLastSet test failed: "
3290 "expected non-0 pwdlastset, got: %llu\n",
3291 (unsigned long long) pwdlastset_new);
3292 ret = false;
3294 break;
3297 switch (levels[l]) {
3298 case 21:
3299 case 23:
3300 case 25:
3301 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3302 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3303 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3304 (pwdlastset_old >= pwdlastset_new)) {
3305 torture_warning(tctx, "pwdlastset not increasing\n");
3306 ret = false;
3308 break;
3311 pwdlastset_old = pwdlastset_new;
3313 usleep(delay);
3315 /* set #2b */
3317 /* set a password, pwdlastset needs to get updated (increased
3318 * value), password_expired value used here is 0 */
3320 if (!test_SetPassword_level(p, np, tctx, handle,
3321 levels[l],
3322 fields_present[f],
3324 &matched_expected_error,
3325 set_levels[s],
3326 acct_name,
3327 password,
3328 machine_credentials,
3329 query_levels[q],
3330 &pwdlastset_new,
3331 expected_samlogon_result)) {
3332 ret = false;
3335 /* when a password has been changed, pwdlastset must not be 0 afterwards
3336 * and must be larger then the old value */
3338 switch (levels[l]) {
3339 case 21:
3340 case 23:
3341 case 25:
3343 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3344 * password has been changed, old and new pwdlastset
3345 * need to be the same value */
3347 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3348 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3349 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3351 torture_assert_int_equal(tctx, pwdlastset_old,
3352 pwdlastset_new, "pwdlastset must be equal");
3353 break;
3355 break;
3356 default:
3357 if (pwdlastset_old >= pwdlastset_new) {
3358 torture_warning(tctx, "pwdLastSet test failed: "
3359 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3360 (unsigned long long) pwdlastset_old,
3361 (unsigned long long) pwdlastset_new);
3362 ret = false;
3364 if (pwdlastset_new == 0) {
3365 torture_warning(tctx, "pwdLastSet test failed: "
3366 "expected non-0 pwdlastset, got: %llu\n",
3367 (unsigned long long) pwdlastset_new);
3368 ret = false;
3370 break;
3373 switch (levels[l]) {
3374 case 21:
3375 case 23:
3376 case 25:
3377 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3378 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3379 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3380 (pwdlastset_old >= pwdlastset_new)) {
3381 torture_warning(tctx, "pwdlastset not increasing\n");
3382 ret = false;
3384 break;
3387 pwdlastset_old = pwdlastset_new;
3389 usleep(delay);
3391 /* set #3 */
3393 /* set a password and force password change (pwdlastset 0) by
3394 * setting the password expired flag to a non-0 value */
3396 if (!test_SetPassword_level(p, np, tctx, handle,
3397 levels[l],
3398 fields_present[f],
3399 nonzeros[z],
3400 &matched_expected_error,
3401 set_levels[s],
3402 acct_name,
3403 password,
3404 machine_credentials,
3405 query_levels[q],
3406 &pwdlastset_new,
3407 expected_samlogon_result)) {
3408 ret = false;
3411 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3412 * set without the SAMR_FIELD_EXPIRED_FLAG */
3414 switch (levels[l]) {
3415 case 21:
3416 case 23:
3417 case 25:
3418 if ((pwdlastset_new != 0) &&
3419 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3420 torture_comment(tctx, "not considering a non-0 "
3421 "pwdLastSet as a an error as the "
3422 "SAMR_FIELD_EXPIRED_FLAG has not "
3423 "been set\n");
3424 break;
3427 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3428 * password has been changed, old and new pwdlastset
3429 * need to be the same value */
3431 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3432 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3433 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3435 torture_assert_int_equal(tctx, pwdlastset_old,
3436 pwdlastset_new, "pwdlastset must be equal");
3437 break;
3439 break;
3440 default:
3441 if (pwdlastset_new != 0) {
3442 torture_warning(tctx, "pwdLastSet test failed: "
3443 "expected pwdLastSet 0, got %llu\n",
3444 (unsigned long long) pwdlastset_old);
3445 ret = false;
3447 break;
3450 switch (levels[l]) {
3451 case 21:
3452 case 23:
3453 case 25:
3454 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3455 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3456 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3457 (pwdlastset_old >= pwdlastset_new)) {
3458 torture_warning(tctx, "pwdlastset not increasing\n");
3459 ret = false;
3461 break;
3464 /* if the level we are testing does not have a fields_present
3465 * field, skip all fields present tests by setting f to to
3466 * arraysize */
3467 switch (levels[l]) {
3468 case 18:
3469 case 24:
3470 case 26:
3471 f = ARRAY_SIZE(fields_present);
3472 break;
3475 #ifdef TEST_QUERY_LEVELS
3477 #endif
3478 #ifdef TEST_SET_LEVELS
3480 #endif
3481 } /* fields present */
3482 } /* nonzeros */
3483 } /* levels */
3485 #undef TEST_SET_LEVELS
3486 #undef TEST_QUERY_LEVELS
3488 talloc_free(np);
3490 return ret;
3493 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3494 struct torture_context *tctx,
3495 struct policy_handle *handle,
3496 uint32_t *badpwdcount)
3498 union samr_UserInfo *info;
3499 struct samr_QueryUserInfo r;
3501 r.in.user_handle = handle;
3502 r.in.level = 3;
3503 r.out.info = &info;
3505 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3507 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3508 "failed to query userinfo");
3509 torture_assert_ntstatus_ok(tctx, r.out.result,
3510 "failed to query userinfo");
3512 *badpwdcount = info->info3.bad_password_count;
3514 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3516 return true;
3519 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3520 struct torture_context *tctx,
3521 struct policy_handle *user_handle,
3522 uint32_t acct_flags)
3524 struct samr_SetUserInfo r;
3525 union samr_UserInfo user_info;
3527 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3529 user_info.info16.acct_flags = acct_flags;
3531 r.in.user_handle = user_handle;
3532 r.in.level = 16;
3533 r.in.info = &user_info;
3535 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3536 "failed to set account flags");
3537 torture_assert_ntstatus_ok(tctx, r.out.result,
3538 "failed to set account flags");
3540 return true;
3543 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3544 struct torture_context *tctx,
3545 struct policy_handle *user_handle,
3546 uint32_t acct_flags,
3547 char **password)
3549 struct dcerpc_binding_handle *b = p->binding_handle;
3551 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3552 "failed to set password");
3554 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3556 torture_assert(tctx,
3557 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3558 acct_flags & ~ACB_DISABLED),
3559 "failed to enable user");
3561 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3562 "failed to set password");
3564 return true;
3567 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3568 struct torture_context *tctx,
3569 struct policy_handle *domain_handle,
3570 enum samr_DomainInfoClass level,
3571 union samr_DomainInfo *info)
3573 struct samr_SetDomainInfo r;
3575 r.in.domain_handle = domain_handle;
3576 r.in.level = level;
3577 r.in.info = info;
3579 torture_assert_ntstatus_ok(tctx,
3580 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3581 "failed to set domain info");
3582 torture_assert_ntstatus_ok(tctx, r.out.result,
3583 "failed to set domain info");
3585 return true;
3588 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3589 struct torture_context *tctx,
3590 struct policy_handle *domain_handle,
3591 enum samr_DomainInfoClass level,
3592 union samr_DomainInfo *info,
3593 NTSTATUS expected)
3595 struct samr_SetDomainInfo r;
3597 r.in.domain_handle = domain_handle;
3598 r.in.level = level;
3599 r.in.info = info;
3601 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3602 "SetDomainInfo failed");
3603 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3605 return true;
3608 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3609 struct torture_context *tctx,
3610 struct policy_handle *domain_handle,
3611 enum samr_DomainInfoClass level,
3612 union samr_DomainInfo **q_info)
3614 struct samr_QueryDomainInfo2 r;
3616 r.in.domain_handle = domain_handle;
3617 r.in.level = level;
3618 r.out.info = q_info;
3620 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3621 "failed to query domain info");
3622 torture_assert_ntstatus_ok(tctx, r.out.result,
3623 "failed to query domain info");
3625 return true;
3628 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3629 struct dcerpc_pipe *np,
3630 struct torture_context *tctx,
3631 uint32_t acct_flags,
3632 const char *acct_name,
3633 struct policy_handle *domain_handle,
3634 struct policy_handle *user_handle,
3635 char **password,
3636 struct cli_credentials *machine_credentials,
3637 const char *comment,
3638 bool disable,
3639 bool interactive,
3640 NTSTATUS expected_success_status,
3641 struct samr_DomInfo1 *info1,
3642 struct samr_DomInfo12 *info12)
3644 union samr_DomainInfo info;
3645 char **passwords;
3646 int i;
3647 uint32_t badpwdcount, tmp;
3648 uint32_t password_history_length = 12;
3649 uint32_t lockout_threshold = 15;
3650 struct dcerpc_binding_handle *b = p->binding_handle;
3652 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3654 torture_assert(tctx, password_history_length < lockout_threshold,
3655 "password history length needs to be smaller than account lockout threshold for this test");
3658 /* set policies */
3660 info.info1 = *info1;
3661 info.info1.password_history_length = password_history_length;
3663 torture_assert(tctx,
3664 test_SetDomainInfo(b, tctx, domain_handle,
3665 DomainPasswordInformation, &info),
3666 "failed to set password history length");
3668 info.info12 = *info12;
3669 info.info12.lockout_threshold = lockout_threshold;
3671 torture_assert(tctx,
3672 test_SetDomainInfo(b, tctx, domain_handle,
3673 DomainLockoutInformation, &info),
3674 "failed to set lockout threshold");
3676 /* reset bad pwd count */
3678 torture_assert(tctx,
3679 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3682 /* enable or disable account */
3683 if (disable) {
3684 torture_assert(tctx,
3685 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3686 acct_flags | ACB_DISABLED),
3687 "failed to disable user");
3688 } else {
3689 torture_assert(tctx,
3690 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3691 acct_flags & ~ACB_DISABLED),
3692 "failed to enable user");
3696 /* setup password history */
3698 passwords = talloc_array(tctx, char *, password_history_length);
3700 for (i=0; i < password_history_length; i++) {
3702 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3703 "failed to set password");
3704 passwords[i] = talloc_strdup(tctx, *password);
3706 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3707 acct_name, passwords[i],
3708 expected_success_status, interactive)) {
3709 torture_fail(tctx, "failed to auth with latest password");
3712 torture_assert(tctx,
3713 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3715 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3719 /* test with wrong password */
3721 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3722 acct_name, "random_crap",
3723 NT_STATUS_WRONG_PASSWORD, interactive)) {
3724 torture_fail(tctx, "succeeded to authenticate with wrong password");
3727 torture_assert(tctx,
3728 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3730 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3733 /* test with latest good password */
3735 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3736 passwords[password_history_length-1],
3737 expected_success_status, interactive)) {
3738 torture_fail(tctx, "succeeded to authenticate with wrong password");
3741 torture_assert(tctx,
3742 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3744 if (disable) {
3745 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3746 } else {
3747 /* only enabled accounts get the bad pwd count reset upon
3748 * successful logon */
3749 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3752 tmp = badpwdcount;
3755 /* test password history */
3757 for (i=0; i < password_history_length; i++) {
3759 torture_comment(tctx, "Testing bad password count behavior with "
3760 "password #%d of #%d\n", i, password_history_length);
3762 /* - network samlogon will succeed auth and not
3763 * increase badpwdcount for 2 last entries
3764 * - interactive samlogon only for the last one */
3766 if (i == password_history_length - 1 ||
3767 (i == password_history_length - 2 && !interactive)) {
3769 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3770 acct_name, passwords[i],
3771 expected_success_status, interactive)) {
3772 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3775 torture_assert(tctx,
3776 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3778 if (disable) {
3779 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3780 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3781 } else {
3782 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3783 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3786 tmp = badpwdcount;
3788 continue;
3791 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3792 acct_name, passwords[i],
3793 NT_STATUS_WRONG_PASSWORD, interactive)) {
3794 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3797 torture_assert(tctx,
3798 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3800 /* - network samlogon will fail auth but not increase
3801 * badpwdcount for 3rd last entry
3802 * - interactive samlogon for 3rd and 2nd last entry */
3804 if (i == password_history_length - 3 ||
3805 (i == password_history_length - 2 && interactive)) {
3806 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3807 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3808 } else {
3809 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3810 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3813 tmp = badpwdcount;
3816 return true;
3819 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3820 struct torture_context *tctx,
3821 uint32_t acct_flags,
3822 const char *acct_name,
3823 struct policy_handle *domain_handle,
3824 struct policy_handle *user_handle,
3825 char **password,
3826 struct cli_credentials *machine_credentials)
3828 union samr_DomainInfo *q_info, s_info;
3829 struct samr_DomInfo1 info1, _info1;
3830 struct samr_DomInfo12 info12, _info12;
3831 bool ret = true;
3832 struct dcerpc_binding_handle *b = p->binding_handle;
3833 struct dcerpc_pipe *np;
3834 int i;
3836 struct {
3837 const char *comment;
3838 bool disabled;
3839 bool interactive;
3840 NTSTATUS expected_success_status;
3841 } creds[] = {
3843 .comment = "network logon (disabled account)",
3844 .disabled = true,
3845 .interactive = false,
3846 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3849 .comment = "network logon (enabled account)",
3850 .disabled = false,
3851 .interactive = false,
3852 .expected_success_status= NT_STATUS_OK
3855 .comment = "interactive logon (disabled account)",
3856 .disabled = true,
3857 .interactive = true,
3858 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3861 .comment = "interactive logon (enabled account)",
3862 .disabled = false,
3863 .interactive = true,
3864 .expected_success_status= NT_STATUS_OK
3868 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3870 /* backup old policies */
3872 torture_assert(tctx,
3873 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3874 DomainPasswordInformation, &q_info),
3875 "failed to query domain info level 1");
3877 info1 = q_info->info1;
3878 _info1 = info1;
3880 torture_assert(tctx,
3881 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3882 DomainLockoutInformation, &q_info),
3883 "failed to query domain info level 12");
3885 info12 = q_info->info12;
3886 _info12 = info12;
3888 /* run tests */
3890 for (i=0; i < ARRAY_SIZE(creds); i++) {
3892 /* skip trust tests for now */
3893 if (acct_flags & ACB_WSTRUST ||
3894 acct_flags & ACB_SVRTRUST ||
3895 acct_flags & ACB_DOMTRUST) {
3896 continue;
3899 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
3900 domain_handle, user_handle, password,
3901 machine_credentials,
3902 creds[i].comment,
3903 creds[i].disabled,
3904 creds[i].interactive,
3905 creds[i].expected_success_status,
3906 &_info1, &_info12);
3907 if (!ret) {
3908 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
3909 } else {
3910 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
3914 /* restore policies */
3916 s_info.info1 = info1;
3918 torture_assert(tctx,
3919 test_SetDomainInfo(b, tctx, domain_handle,
3920 DomainPasswordInformation, &s_info),
3921 "failed to set password information");
3923 s_info.info12 = info12;
3925 torture_assert(tctx,
3926 test_SetDomainInfo(b, tctx, domain_handle,
3927 DomainLockoutInformation, &s_info),
3928 "failed to set lockout information");
3930 return ret;
3933 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3934 struct torture_context *tctx,
3935 struct policy_handle *handle,
3936 uint32_t *acct_flags)
3938 union samr_UserInfo *info;
3939 struct samr_QueryUserInfo r;
3941 r.in.user_handle = handle;
3942 r.in.level = 16;
3943 r.out.info = &info;
3945 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3947 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3948 "failed to query userinfo");
3949 torture_assert_ntstatus_ok(tctx, r.out.result,
3950 "failed to query userinfo");
3952 *acct_flags = info->info16.acct_flags;
3954 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
3956 return true;
3959 static bool test_Password_lockout(struct dcerpc_pipe *p,
3960 struct dcerpc_pipe *np,
3961 struct torture_context *tctx,
3962 uint32_t acct_flags,
3963 const char *acct_name,
3964 struct policy_handle *domain_handle,
3965 struct policy_handle *user_handle,
3966 char **password,
3967 struct cli_credentials *machine_credentials,
3968 const char *comment,
3969 bool disable,
3970 bool interactive,
3971 NTSTATUS expected_success_status,
3972 struct samr_DomInfo1 *info1,
3973 struct samr_DomInfo12 *info12)
3975 union samr_DomainInfo info;
3976 uint32_t badpwdcount;
3977 uint32_t password_history_length = 1;
3978 uint64_t lockout_threshold = 1;
3979 uint32_t lockout_seconds = 5;
3980 uint64_t delta_time_factor = 10 * 1000 * 1000;
3981 struct dcerpc_binding_handle *b = p->binding_handle;
3983 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
3985 /* set policies */
3987 info.info1 = *info1;
3989 torture_comment(tctx, "setting password history length.\n");
3990 info.info1.password_history_length = password_history_length;
3992 torture_assert(tctx,
3993 test_SetDomainInfo(b, tctx, domain_handle,
3994 DomainPasswordInformation, &info),
3995 "failed to set password history length");
3997 info.info12 = *info12;
3998 info.info12.lockout_threshold = lockout_threshold;
4000 /* set lockout duration < lockout window: should fail */
4001 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4002 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4004 torture_assert(tctx,
4005 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4006 DomainLockoutInformation, &info,
4007 NT_STATUS_INVALID_PARAMETER),
4008 "setting lockout duration < lockout window gave unexpected result");
4010 info.info12.lockout_duration = 0;
4011 info.info12.lockout_window = 0;
4013 torture_assert(tctx,
4014 test_SetDomainInfo(b, tctx, domain_handle,
4015 DomainLockoutInformation, &info),
4016 "failed to set lockout window and duration to 0");
4019 /* set lockout duration of 5 seconds */
4020 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4021 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4023 torture_assert(tctx,
4024 test_SetDomainInfo(b, tctx, domain_handle,
4025 DomainLockoutInformation, &info),
4026 "failed to set lockout window and duration to 5 seconds");
4028 /* reset bad pwd count */
4030 torture_assert(tctx,
4031 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4034 /* enable or disable account */
4036 if (disable) {
4037 torture_assert(tctx,
4038 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4039 acct_flags | ACB_DISABLED),
4040 "failed to disable user");
4041 } else {
4042 torture_assert(tctx,
4043 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4044 acct_flags & ~ACB_DISABLED),
4045 "failed to enable user");
4049 /* test logon with right password */
4051 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4052 acct_name, *password,
4053 expected_success_status, interactive)) {
4054 torture_fail(tctx, "failed to auth with latest password");
4057 torture_assert(tctx,
4058 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4059 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4062 /* test with wrong password ==> lockout */
4064 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4065 acct_name, "random_crap",
4066 NT_STATUS_WRONG_PASSWORD, interactive)) {
4067 torture_fail(tctx, "succeeded to authenticate with wrong password");
4070 torture_assert(tctx,
4071 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4072 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4074 torture_assert(tctx,
4075 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4076 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4077 "expected account to be locked");
4080 /* test with good password */
4082 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4083 *password,
4084 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4086 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4089 /* bad pwd count should not get updated */
4090 torture_assert(tctx,
4091 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4092 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4094 /* curiously, windows does _not_ set the autlock flag */
4095 torture_assert(tctx,
4096 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4097 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4098 "expected account to be locked");
4101 /* with bad password */
4103 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4104 acct_name, "random_crap2",
4105 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4107 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4110 /* bad pwd count should not get updated */
4111 torture_assert(tctx,
4112 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4113 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4115 /* curiously, windows does _not_ set the autlock flag */
4116 torture_assert(tctx,
4117 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4118 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4119 "expected account to be locked");
4122 /* let lockout duration expire ==> unlock */
4124 torture_comment(tctx, "let lockout duration expire...\n");
4125 sleep(lockout_seconds + 1);
4127 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4128 *password,
4129 expected_success_status, interactive))
4131 torture_fail(tctx, "failed to authenticate after lockout expired");
4134 torture_assert(tctx,
4135 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4136 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4137 "expected account not to be locked");
4139 return true;
4142 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4143 struct torture_context *tctx,
4144 uint32_t acct_flags,
4145 const char *acct_name,
4146 struct policy_handle *domain_handle,
4147 struct policy_handle *user_handle,
4148 char **password,
4149 struct cli_credentials *machine_credentials)
4151 union samr_DomainInfo *q_info, s_info;
4152 struct samr_DomInfo1 info1, _info1;
4153 struct samr_DomInfo12 info12, _info12;
4154 bool ret = true;
4155 struct dcerpc_binding_handle *b = p->binding_handle;
4156 struct dcerpc_pipe *np;
4157 int i;
4159 struct {
4160 const char *comment;
4161 bool disabled;
4162 bool interactive;
4163 NTSTATUS expected_success_status;
4164 } creds[] = {
4166 .comment = "network logon (disabled account)",
4167 .disabled = true,
4168 .interactive = false,
4169 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4172 .comment = "network logon (enabled account)",
4173 .disabled = false,
4174 .interactive = false,
4175 .expected_success_status= NT_STATUS_OK
4178 .comment = "interactive logon (disabled account)",
4179 .disabled = true,
4180 .interactive = true,
4181 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4184 .comment = "interactive logon (enabled account)",
4185 .disabled = false,
4186 .interactive = true,
4187 .expected_success_status= NT_STATUS_OK
4191 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4193 /* backup old policies */
4195 torture_assert(tctx,
4196 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4197 DomainPasswordInformation, &q_info),
4198 "failed to query domain info level 1");
4200 info1 = q_info->info1;
4201 _info1 = info1;
4203 torture_assert(tctx,
4204 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4205 DomainLockoutInformation, &q_info),
4206 "failed to query domain info level 12");
4208 info12 = q_info->info12;
4209 _info12 = info12;
4211 /* run tests */
4213 for (i=0; i < ARRAY_SIZE(creds); i++) {
4215 /* skip trust tests for now */
4216 if (acct_flags & ACB_WSTRUST ||
4217 acct_flags & ACB_SVRTRUST ||
4218 acct_flags & ACB_DOMTRUST) {
4219 continue;
4222 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4223 domain_handle, user_handle, password,
4224 machine_credentials,
4225 creds[i].comment,
4226 creds[i].disabled,
4227 creds[i].interactive,
4228 creds[i].expected_success_status,
4229 &_info1, &_info12);
4230 if (!ret) {
4231 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4232 } else {
4233 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4237 /* restore policies */
4239 s_info.info1 = info1;
4241 torture_assert(tctx,
4242 test_SetDomainInfo(b, tctx, domain_handle,
4243 DomainPasswordInformation, &s_info),
4244 "failed to set password information");
4246 s_info.info12 = info12;
4248 torture_assert(tctx,
4249 test_SetDomainInfo(b, tctx, domain_handle,
4250 DomainLockoutInformation, &s_info),
4251 "failed to set lockout information");
4253 return ret;
4256 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4257 struct dcerpc_pipe *lp,
4258 struct torture_context *tctx,
4259 struct policy_handle *domain_handle,
4260 struct policy_handle *lsa_handle,
4261 struct policy_handle *user_handle,
4262 const struct dom_sid *domain_sid,
4263 uint32_t rid,
4264 struct cli_credentials *machine_credentials)
4266 bool ret = true;
4267 struct dcerpc_binding_handle *b = p->binding_handle;
4268 struct dcerpc_binding_handle *lb = lp->binding_handle;
4270 struct policy_handle lsa_acct_handle;
4271 struct dom_sid *user_sid;
4273 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4276 struct lsa_EnumAccountRights r;
4277 struct lsa_RightSet rights;
4279 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4281 r.in.handle = lsa_handle;
4282 r.in.sid = user_sid;
4283 r.out.rights = &rights;
4285 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4286 "lsa_EnumAccountRights failed");
4287 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4288 "Expected enum rights for account to fail");
4292 struct lsa_RightSet rights;
4293 struct lsa_StringLarge names[2];
4294 struct lsa_AddAccountRights r;
4296 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4298 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4299 init_lsa_StringLarge(&names[1], NULL);
4301 rights.count = 1;
4302 rights.names = names;
4304 r.in.handle = lsa_handle;
4305 r.in.sid = user_sid;
4306 r.in.rights = &rights;
4308 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4309 "lsa_AddAccountRights failed");
4310 torture_assert_ntstatus_ok(tctx, r.out.result,
4311 "Failed to add privileges");
4315 struct lsa_EnumAccounts r;
4316 uint32_t resume_handle = 0;
4317 struct lsa_SidArray lsa_sid_array;
4318 int i;
4319 bool found_sid = false;
4321 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4323 r.in.handle = lsa_handle;
4324 r.in.num_entries = 0x1000;
4325 r.in.resume_handle = &resume_handle;
4326 r.out.sids = &lsa_sid_array;
4327 r.out.resume_handle = &resume_handle;
4329 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4330 "lsa_EnumAccounts failed");
4331 torture_assert_ntstatus_ok(tctx, r.out.result,
4332 "Failed to enum accounts");
4334 for (i=0; i < lsa_sid_array.num_sids; i++) {
4335 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4336 found_sid = true;
4340 torture_assert(tctx, found_sid,
4341 "failed to list privileged account");
4345 struct lsa_EnumAccountRights r;
4346 struct lsa_RightSet user_rights;
4348 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4350 r.in.handle = lsa_handle;
4351 r.in.sid = user_sid;
4352 r.out.rights = &user_rights;
4354 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4355 "lsa_EnumAccountRights failed");
4356 torture_assert_ntstatus_ok(tctx, r.out.result,
4357 "Failed to enum rights for account");
4359 if (user_rights.count < 1) {
4360 torture_warning(tctx, "failed to find newly added rights");
4361 return false;
4366 struct lsa_OpenAccount r;
4368 torture_comment(tctx, "Testing LSA OpenAccount\n");
4370 r.in.handle = lsa_handle;
4371 r.in.sid = user_sid;
4372 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4373 r.out.acct_handle = &lsa_acct_handle;
4375 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4376 "lsa_OpenAccount failed");
4377 torture_assert_ntstatus_ok(tctx, r.out.result,
4378 "Failed to open lsa account");
4382 struct lsa_GetSystemAccessAccount r;
4383 uint32_t access_mask;
4385 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4387 r.in.handle = &lsa_acct_handle;
4388 r.out.access_mask = &access_mask;
4390 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4391 "lsa_GetSystemAccessAccount failed");
4392 torture_assert_ntstatus_ok(tctx, r.out.result,
4393 "Failed to get lsa system access account");
4397 struct lsa_Close r;
4399 torture_comment(tctx, "Testing LSA Close\n");
4401 r.in.handle = &lsa_acct_handle;
4402 r.out.handle = &lsa_acct_handle;
4404 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4405 "lsa_Close failed");
4406 torture_assert_ntstatus_ok(tctx, r.out.result,
4407 "Failed to close lsa");
4411 struct samr_DeleteUser r;
4413 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4415 r.in.user_handle = user_handle;
4416 r.out.user_handle = user_handle;
4418 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4419 "DeleteUser failed");
4420 torture_assert_ntstatus_ok(tctx, r.out.result,
4421 "DeleteUser failed");
4425 struct lsa_EnumAccounts r;
4426 uint32_t resume_handle = 0;
4427 struct lsa_SidArray lsa_sid_array;
4428 int i;
4429 bool found_sid = false;
4431 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4433 r.in.handle = lsa_handle;
4434 r.in.num_entries = 0x1000;
4435 r.in.resume_handle = &resume_handle;
4436 r.out.sids = &lsa_sid_array;
4437 r.out.resume_handle = &resume_handle;
4439 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4440 "lsa_EnumAccounts failed");
4441 torture_assert_ntstatus_ok(tctx, r.out.result,
4442 "Failed to enum accounts");
4444 for (i=0; i < lsa_sid_array.num_sids; i++) {
4445 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4446 found_sid = true;
4450 torture_assert(tctx, found_sid,
4451 "failed to list privileged account");
4455 struct lsa_EnumAccountRights r;
4456 struct lsa_RightSet user_rights;
4458 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4460 r.in.handle = lsa_handle;
4461 r.in.sid = user_sid;
4462 r.out.rights = &user_rights;
4464 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4465 "lsa_EnumAccountRights failed");
4466 torture_assert_ntstatus_ok(tctx, r.out.result,
4467 "Failed to enum rights for account");
4469 if (user_rights.count < 1) {
4470 torture_warning(tctx, "failed to find newly added rights");
4471 return false;
4476 struct lsa_OpenAccount r;
4478 torture_comment(tctx, "Testing LSA OpenAccount\n");
4480 r.in.handle = lsa_handle;
4481 r.in.sid = user_sid;
4482 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4483 r.out.acct_handle = &lsa_acct_handle;
4485 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4486 "lsa_OpenAccount failed");
4487 torture_assert_ntstatus_ok(tctx, r.out.result,
4488 "Failed to open lsa account");
4492 struct lsa_GetSystemAccessAccount r;
4493 uint32_t access_mask;
4495 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4497 r.in.handle = &lsa_acct_handle;
4498 r.out.access_mask = &access_mask;
4500 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4501 "lsa_GetSystemAccessAccount failed");
4502 torture_assert_ntstatus_ok(tctx, r.out.result,
4503 "Failed to get lsa system access account");
4507 struct lsa_DeleteObject r;
4509 torture_comment(tctx, "Testing LSA DeleteObject\n");
4511 r.in.handle = &lsa_acct_handle;
4512 r.out.handle = &lsa_acct_handle;
4514 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4515 "lsa_DeleteObject failed");
4516 torture_assert_ntstatus_ok(tctx, r.out.result,
4517 "Failed to delete object");
4521 struct lsa_EnumAccounts r;
4522 uint32_t resume_handle = 0;
4523 struct lsa_SidArray lsa_sid_array;
4524 int i;
4525 bool found_sid = false;
4527 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4529 r.in.handle = lsa_handle;
4530 r.in.num_entries = 0x1000;
4531 r.in.resume_handle = &resume_handle;
4532 r.out.sids = &lsa_sid_array;
4533 r.out.resume_handle = &resume_handle;
4535 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4536 "lsa_EnumAccounts failed");
4537 torture_assert_ntstatus_ok(tctx, r.out.result,
4538 "Failed to enum accounts");
4540 for (i=0; i < lsa_sid_array.num_sids; i++) {
4541 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4542 found_sid = true;
4546 torture_assert(tctx, !found_sid,
4547 "should not have listed privileged account");
4551 struct lsa_EnumAccountRights r;
4552 struct lsa_RightSet user_rights;
4554 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4556 r.in.handle = lsa_handle;
4557 r.in.sid = user_sid;
4558 r.out.rights = &user_rights;
4560 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4561 "lsa_EnumAccountRights failed");
4562 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4563 "Failed to enum rights for account");
4566 return ret;
4569 static bool test_user_ops(struct dcerpc_pipe *p,
4570 struct torture_context *tctx,
4571 struct policy_handle *user_handle,
4572 struct policy_handle *domain_handle,
4573 const struct dom_sid *domain_sid,
4574 uint32_t base_acct_flags,
4575 const char *base_acct_name, enum torture_samr_choice which_ops,
4576 struct cli_credentials *machine_credentials)
4578 char *password = NULL;
4579 struct samr_QueryUserInfo q;
4580 union samr_UserInfo *info;
4581 NTSTATUS status;
4582 struct dcerpc_binding_handle *b = p->binding_handle;
4584 bool ret = true;
4585 int i;
4586 uint32_t rid;
4587 const uint32_t password_fields[] = {
4588 SAMR_FIELD_NT_PASSWORD_PRESENT,
4589 SAMR_FIELD_LM_PASSWORD_PRESENT,
4590 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4594 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4595 if (!NT_STATUS_IS_OK(status)) {
4596 ret = false;
4599 switch (which_ops) {
4600 case TORTURE_SAMR_USER_ATTRIBUTES:
4601 if (!test_QuerySecurity(b, tctx, user_handle)) {
4602 ret = false;
4605 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4606 ret = false;
4609 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4610 ret = false;
4613 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4614 base_acct_name)) {
4615 ret = false;
4618 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4619 ret = false;
4622 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4623 ret = false;
4626 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4627 ret = false;
4629 break;
4630 case TORTURE_SAMR_PASSWORDS:
4631 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4632 char simple_pass[9];
4633 char *v = generate_random_str(tctx, 1);
4635 ZERO_STRUCT(simple_pass);
4636 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4638 torture_comment(tctx, "Testing machine account password policy rules\n");
4640 /* Workstation trust accounts don't seem to need to honour password quality policy */
4641 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4642 ret = false;
4645 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4646 ret = false;
4649 /* reset again, to allow another 'user' password change */
4650 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4651 ret = false;
4654 /* Try a 'short' password */
4655 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4656 ret = false;
4659 /* Try a compleatly random password */
4660 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4661 ret = false;
4665 for (i = 0; password_fields[i]; i++) {
4666 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4667 ret = false;
4670 /* check it was set right */
4671 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4672 ret = false;
4676 for (i = 0; password_fields[i]; i++) {
4677 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4678 ret = false;
4681 /* check it was set right */
4682 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4683 ret = false;
4687 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4688 ret = false;
4691 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4692 ret = false;
4695 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4696 ret = false;
4699 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4700 ret = false;
4703 for (i = 0; password_fields[i]; i++) {
4705 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4706 /* we need to skip as that would break
4707 * the ChangePasswordUser3 verify */
4708 continue;
4711 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4712 ret = false;
4715 /* check it was set right */
4716 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4717 ret = false;
4721 q.in.user_handle = user_handle;
4722 q.in.level = 5;
4723 q.out.info = &info;
4725 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4726 "QueryUserInfo failed");
4727 if (!NT_STATUS_IS_OK(q.out.result)) {
4728 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4729 q.in.level, nt_errstr(q.out.result));
4730 ret = false;
4731 } else {
4732 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4733 if ((info->info5.acct_flags) != expected_flags) {
4734 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4735 info->info5.acct_flags,
4736 expected_flags);
4737 /* FIXME: GD */
4738 if (!torture_setting_bool(tctx, "samba3", false)) {
4739 ret = false;
4742 if (info->info5.rid != rid) {
4743 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4744 info->info5.rid, rid);
4749 break;
4751 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4753 /* test last password change timestamp behaviour */
4754 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4755 base_acct_name,
4756 user_handle, &password,
4757 machine_credentials)) {
4758 ret = false;
4761 if (ret == true) {
4762 torture_comment(tctx, "pwdLastSet test succeeded\n");
4763 } else {
4764 torture_warning(tctx, "pwdLastSet test failed\n");
4767 break;
4769 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4771 /* test bad pwd count change behaviour */
4772 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4773 base_acct_name,
4774 domain_handle,
4775 user_handle, &password,
4776 machine_credentials)) {
4777 ret = false;
4780 if (ret == true) {
4781 torture_comment(tctx, "badPwdCount test succeeded\n");
4782 } else {
4783 torture_warning(tctx, "badPwdCount test failed\n");
4786 break;
4788 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4790 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4791 base_acct_name,
4792 domain_handle,
4793 user_handle, &password,
4794 machine_credentials))
4796 ret = false;
4799 if (ret == true) {
4800 torture_comment(tctx, "lockout test succeeded\n");
4801 } else {
4802 torture_warning(tctx, "lockout test failed\n");
4805 break;
4808 case TORTURE_SAMR_USER_PRIVILEGES: {
4810 struct dcerpc_pipe *lp;
4811 struct policy_handle *lsa_handle;
4812 struct dcerpc_binding_handle *lb;
4814 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4815 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4816 lb = lp->binding_handle;
4818 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4819 ret = false;
4822 if (!test_DeleteUser_with_privs(p, lp, tctx,
4823 domain_handle, lsa_handle, user_handle,
4824 domain_sid, rid,
4825 machine_credentials)) {
4826 ret = false;
4829 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4830 ret = false;
4833 if (!ret) {
4834 torture_warning(tctx, "privileged user delete test failed\n");
4837 break;
4839 case TORTURE_SAMR_OTHER:
4840 case TORTURE_SAMR_MANY_ACCOUNTS:
4841 case TORTURE_SAMR_MANY_GROUPS:
4842 case TORTURE_SAMR_MANY_ALIASES:
4843 /* We just need the account to exist */
4844 break;
4846 return ret;
4849 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4850 struct torture_context *tctx,
4851 struct policy_handle *alias_handle,
4852 const struct dom_sid *domain_sid)
4854 bool ret = true;
4856 if (!torture_setting_bool(tctx, "samba3", false)) {
4857 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4858 ret = false;
4862 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4863 ret = false;
4866 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4867 ret = false;
4870 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
4871 ret = false;
4874 if (torture_setting_bool(tctx, "samba3", false) ||
4875 torture_setting_bool(tctx, "samba4", false)) {
4876 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4877 return ret;
4880 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
4881 ret = false;
4884 return ret;
4888 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
4889 struct torture_context *tctx,
4890 struct policy_handle *user_handle)
4892 struct samr_DeleteUser d;
4893 torture_comment(tctx, "Testing DeleteUser\n");
4895 d.in.user_handle = user_handle;
4896 d.out.user_handle = user_handle;
4898 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
4899 "DeleteUser failed");
4900 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
4902 return true;
4905 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
4906 struct torture_context *tctx,
4907 struct policy_handle *handle, const char *name)
4909 NTSTATUS status;
4910 struct samr_DeleteUser d;
4911 struct policy_handle user_handle;
4912 uint32_t rid;
4914 status = test_LookupName(b, tctx, handle, name, &rid);
4915 if (!NT_STATUS_IS_OK(status)) {
4916 goto failed;
4919 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
4920 if (!NT_STATUS_IS_OK(status)) {
4921 goto failed;
4924 d.in.user_handle = &user_handle;
4925 d.out.user_handle = &user_handle;
4926 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
4927 "DeleteUser failed");
4928 if (!NT_STATUS_IS_OK(d.out.result)) {
4929 status = d.out.result;
4930 goto failed;
4933 return true;
4935 failed:
4936 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
4937 return false;
4941 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
4942 struct torture_context *tctx,
4943 struct policy_handle *handle, const char *name)
4945 NTSTATUS status;
4946 struct samr_OpenGroup r;
4947 struct samr_DeleteDomainGroup d;
4948 struct policy_handle group_handle;
4949 uint32_t rid;
4951 status = test_LookupName(b, tctx, handle, name, &rid);
4952 if (!NT_STATUS_IS_OK(status)) {
4953 goto failed;
4956 r.in.domain_handle = handle;
4957 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4958 r.in.rid = rid;
4959 r.out.group_handle = &group_handle;
4960 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
4961 "OpenGroup failed");
4962 if (!NT_STATUS_IS_OK(r.out.result)) {
4963 status = r.out.result;
4964 goto failed;
4967 d.in.group_handle = &group_handle;
4968 d.out.group_handle = &group_handle;
4969 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
4970 "DeleteDomainGroup failed");
4971 if (!NT_STATUS_IS_OK(d.out.result)) {
4972 status = d.out.result;
4973 goto failed;
4976 return true;
4978 failed:
4979 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
4980 return false;
4984 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
4985 struct torture_context *tctx,
4986 struct policy_handle *domain_handle,
4987 const char *name)
4989 NTSTATUS status;
4990 struct samr_OpenAlias r;
4991 struct samr_DeleteDomAlias d;
4992 struct policy_handle alias_handle;
4993 uint32_t rid;
4995 torture_comment(tctx, "Testing DeleteAlias_byname\n");
4997 status = test_LookupName(b, tctx, domain_handle, name, &rid);
4998 if (!NT_STATUS_IS_OK(status)) {
4999 goto failed;
5002 r.in.domain_handle = domain_handle;
5003 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5004 r.in.rid = rid;
5005 r.out.alias_handle = &alias_handle;
5006 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5007 "OpenAlias failed");
5008 if (!NT_STATUS_IS_OK(r.out.result)) {
5009 status = r.out.result;
5010 goto failed;
5013 d.in.alias_handle = &alias_handle;
5014 d.out.alias_handle = &alias_handle;
5015 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5016 "DeleteDomAlias failed");
5017 if (!NT_STATUS_IS_OK(d.out.result)) {
5018 status = d.out.result;
5019 goto failed;
5022 return true;
5024 failed:
5025 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5026 return false;
5029 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5030 struct torture_context *tctx,
5031 struct policy_handle *alias_handle)
5033 struct samr_DeleteDomAlias d;
5034 bool ret = true;
5036 torture_comment(tctx, "Testing DeleteAlias\n");
5038 d.in.alias_handle = alias_handle;
5039 d.out.alias_handle = alias_handle;
5041 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5042 "DeleteDomAlias failed");
5043 if (!NT_STATUS_IS_OK(d.out.result)) {
5044 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5045 ret = false;
5048 return ret;
5051 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5052 struct torture_context *tctx,
5053 struct policy_handle *domain_handle,
5054 const char *alias_name,
5055 struct policy_handle *alias_handle,
5056 const struct dom_sid *domain_sid,
5057 bool test_alias)
5059 struct samr_CreateDomAlias r;
5060 struct lsa_String name;
5061 uint32_t rid;
5062 bool ret = true;
5064 init_lsa_String(&name, alias_name);
5065 r.in.domain_handle = domain_handle;
5066 r.in.alias_name = &name;
5067 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5068 r.out.alias_handle = alias_handle;
5069 r.out.rid = &rid;
5071 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5073 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5074 "CreateDomAlias failed");
5076 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5077 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5078 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5079 return true;
5080 } else {
5081 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5082 nt_errstr(r.out.result));
5083 return false;
5087 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5088 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5089 return false;
5091 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5092 "CreateDomAlias failed");
5095 if (!NT_STATUS_IS_OK(r.out.result)) {
5096 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5097 return false;
5100 if (!test_alias) {
5101 return ret;
5104 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5105 ret = false;
5108 return ret;
5111 static bool test_ChangePassword(struct dcerpc_pipe *p,
5112 struct torture_context *tctx,
5113 const char *acct_name,
5114 struct policy_handle *domain_handle, char **password)
5116 bool ret = true;
5117 struct dcerpc_binding_handle *b = p->binding_handle;
5119 if (!*password) {
5120 return false;
5123 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5124 ret = false;
5127 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5128 ret = false;
5131 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5132 ret = false;
5135 /* test what happens when setting the old password again */
5136 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5137 ret = false;
5141 char simple_pass[9];
5142 char *v = generate_random_str(tctx, 1);
5144 ZERO_STRUCT(simple_pass);
5145 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5147 /* test what happens when picking a simple password */
5148 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5149 ret = false;
5153 /* set samr_SetDomainInfo level 1 with min_length 5 */
5155 struct samr_QueryDomainInfo r;
5156 union samr_DomainInfo *info = NULL;
5157 struct samr_SetDomainInfo s;
5158 uint16_t len_old, len;
5159 uint32_t pwd_prop_old;
5160 int64_t min_pwd_age_old;
5162 len = 5;
5164 r.in.domain_handle = domain_handle;
5165 r.in.level = 1;
5166 r.out.info = &info;
5168 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5169 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5170 "QueryDomainInfo failed");
5171 if (!NT_STATUS_IS_OK(r.out.result)) {
5172 return false;
5175 s.in.domain_handle = domain_handle;
5176 s.in.level = 1;
5177 s.in.info = info;
5179 /* remember the old min length, so we can reset it */
5180 len_old = s.in.info->info1.min_password_length;
5181 s.in.info->info1.min_password_length = len;
5182 pwd_prop_old = s.in.info->info1.password_properties;
5183 /* turn off password complexity checks for this test */
5184 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5186 min_pwd_age_old = s.in.info->info1.min_password_age;
5187 s.in.info->info1.min_password_age = 0;
5189 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5190 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5191 "SetDomainInfo failed");
5192 if (!NT_STATUS_IS_OK(s.out.result)) {
5193 return false;
5196 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5198 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5199 ret = false;
5202 s.in.info->info1.min_password_length = len_old;
5203 s.in.info->info1.password_properties = pwd_prop_old;
5204 s.in.info->info1.min_password_age = min_pwd_age_old;
5206 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5207 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5208 "SetDomainInfo failed");
5209 if (!NT_STATUS_IS_OK(s.out.result)) {
5210 return false;
5216 struct samr_OpenUser r;
5217 struct samr_QueryUserInfo q;
5218 union samr_UserInfo *info;
5219 struct samr_LookupNames n;
5220 struct policy_handle user_handle;
5221 struct samr_Ids rids, types;
5223 n.in.domain_handle = domain_handle;
5224 n.in.num_names = 1;
5225 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5226 n.in.names[0].string = acct_name;
5227 n.out.rids = &rids;
5228 n.out.types = &types;
5230 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5231 "LookupNames failed");
5232 if (!NT_STATUS_IS_OK(n.out.result)) {
5233 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5234 return false;
5237 r.in.domain_handle = domain_handle;
5238 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5239 r.in.rid = n.out.rids->ids[0];
5240 r.out.user_handle = &user_handle;
5242 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5243 "OpenUser failed");
5244 if (!NT_STATUS_IS_OK(r.out.result)) {
5245 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5246 return false;
5249 q.in.user_handle = &user_handle;
5250 q.in.level = 5;
5251 q.out.info = &info;
5253 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5254 "QueryUserInfo failed");
5255 if (!NT_STATUS_IS_OK(q.out.result)) {
5256 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5257 return false;
5260 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5262 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5263 info->info5.last_password_change, true)) {
5264 ret = false;
5268 /* we change passwords twice - this has the effect of verifying
5269 they were changed correctly for the final call */
5270 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5271 ret = false;
5274 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5275 ret = false;
5278 return ret;
5281 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5282 struct policy_handle *domain_handle,
5283 const char *user_name,
5284 struct policy_handle *user_handle_out,
5285 struct dom_sid *domain_sid,
5286 enum torture_samr_choice which_ops,
5287 struct cli_credentials *machine_credentials,
5288 bool test_user)
5291 TALLOC_CTX *user_ctx;
5293 struct samr_CreateUser r;
5294 struct samr_QueryUserInfo q;
5295 union samr_UserInfo *info;
5296 struct samr_DeleteUser d;
5297 uint32_t rid;
5299 /* This call creates a 'normal' account - check that it really does */
5300 const uint32_t acct_flags = ACB_NORMAL;
5301 struct lsa_String name;
5302 bool ret = true;
5303 struct dcerpc_binding_handle *b = p->binding_handle;
5305 struct policy_handle user_handle;
5306 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5307 init_lsa_String(&name, user_name);
5309 r.in.domain_handle = domain_handle;
5310 r.in.account_name = &name;
5311 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5312 r.out.user_handle = &user_handle;
5313 r.out.rid = &rid;
5315 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5317 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5318 "CreateUser failed");
5320 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5321 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5322 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5323 return true;
5324 } else {
5325 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5326 nt_errstr(r.out.result));
5327 return false;
5331 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5332 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5333 talloc_free(user_ctx);
5334 return false;
5336 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5337 "CreateUser failed");
5340 if (!NT_STATUS_IS_OK(r.out.result)) {
5341 talloc_free(user_ctx);
5342 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5343 return false;
5346 if (!test_user) {
5347 if (user_handle_out) {
5348 *user_handle_out = user_handle;
5350 return ret;
5354 q.in.user_handle = &user_handle;
5355 q.in.level = 16;
5356 q.out.info = &info;
5358 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5359 "QueryUserInfo failed");
5360 if (!NT_STATUS_IS_OK(q.out.result)) {
5361 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5362 q.in.level, nt_errstr(q.out.result));
5363 ret = false;
5364 } else {
5365 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5366 torture_warning(tctx, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5367 info->info16.acct_flags,
5368 acct_flags);
5369 ret = false;
5373 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5374 domain_sid, acct_flags, name.string, which_ops,
5375 machine_credentials)) {
5376 ret = false;
5379 if (user_handle_out) {
5380 *user_handle_out = user_handle;
5381 } else {
5382 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5384 d.in.user_handle = &user_handle;
5385 d.out.user_handle = &user_handle;
5387 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5388 "DeleteUser failed");
5389 if (!NT_STATUS_IS_OK(d.out.result)) {
5390 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5391 ret = false;
5397 talloc_free(user_ctx);
5399 return ret;
5403 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5404 struct policy_handle *domain_handle,
5405 struct dom_sid *domain_sid,
5406 enum torture_samr_choice which_ops,
5407 struct cli_credentials *machine_credentials)
5409 struct samr_CreateUser2 r;
5410 struct samr_QueryUserInfo q;
5411 union samr_UserInfo *info;
5412 struct samr_DeleteUser d;
5413 struct policy_handle user_handle;
5414 uint32_t rid;
5415 struct lsa_String name;
5416 bool ret = true;
5417 int i;
5418 struct dcerpc_binding_handle *b = p->binding_handle;
5420 struct {
5421 uint32_t acct_flags;
5422 const char *account_name;
5423 NTSTATUS nt_status;
5424 } account_types[] = {
5425 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5426 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5427 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5428 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5429 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5430 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5431 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5432 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5433 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5434 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5435 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5436 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5437 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5438 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5439 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5442 for (i = 0; account_types[i].account_name; i++) {
5443 TALLOC_CTX *user_ctx;
5444 uint32_t acct_flags = account_types[i].acct_flags;
5445 uint32_t access_granted;
5446 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5447 init_lsa_String(&name, account_types[i].account_name);
5449 r.in.domain_handle = domain_handle;
5450 r.in.account_name = &name;
5451 r.in.acct_flags = acct_flags;
5452 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5453 r.out.user_handle = &user_handle;
5454 r.out.access_granted = &access_granted;
5455 r.out.rid = &rid;
5457 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5459 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5460 "CreateUser2 failed");
5462 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5463 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5464 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5465 continue;
5466 } else {
5467 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5468 nt_errstr(r.out.result));
5469 ret = false;
5470 continue;
5474 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5475 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5476 talloc_free(user_ctx);
5477 ret = false;
5478 continue;
5480 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5481 "CreateUser2 failed");
5484 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5485 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5486 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5487 ret = false;
5490 if (NT_STATUS_IS_OK(r.out.result)) {
5491 q.in.user_handle = &user_handle;
5492 q.in.level = 5;
5493 q.out.info = &info;
5495 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5496 "QueryUserInfo failed");
5497 if (!NT_STATUS_IS_OK(q.out.result)) {
5498 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5499 q.in.level, nt_errstr(q.out.result));
5500 ret = false;
5501 } else {
5502 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5503 if (acct_flags == ACB_NORMAL) {
5504 expected_flags |= ACB_PW_EXPIRED;
5506 if ((info->info5.acct_flags) != expected_flags) {
5507 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5508 info->info5.acct_flags,
5509 expected_flags);
5510 ret = false;
5512 switch (acct_flags) {
5513 case ACB_SVRTRUST:
5514 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5515 torture_warning(tctx, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5516 DOMAIN_RID_DCS, info->info5.primary_gid);
5517 ret = false;
5519 break;
5520 case ACB_WSTRUST:
5521 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5522 torture_warning(tctx, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5523 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5524 ret = false;
5526 break;
5527 case ACB_NORMAL:
5528 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5529 torture_warning(tctx, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5530 DOMAIN_RID_USERS, info->info5.primary_gid);
5531 ret = false;
5533 break;
5537 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5538 domain_sid, acct_flags, name.string, which_ops,
5539 machine_credentials)) {
5540 ret = false;
5543 if (!ndr_policy_handle_empty(&user_handle)) {
5544 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5546 d.in.user_handle = &user_handle;
5547 d.out.user_handle = &user_handle;
5549 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5550 "DeleteUser failed");
5551 if (!NT_STATUS_IS_OK(d.out.result)) {
5552 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5553 ret = false;
5557 talloc_free(user_ctx);
5560 return ret;
5563 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5564 struct torture_context *tctx,
5565 struct policy_handle *handle)
5567 struct samr_QueryAliasInfo r;
5568 union samr_AliasInfo *info;
5569 uint16_t levels[] = {1, 2, 3};
5570 int i;
5571 bool ret = true;
5573 for (i=0;i<ARRAY_SIZE(levels);i++) {
5574 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5576 r.in.alias_handle = handle;
5577 r.in.level = levels[i];
5578 r.out.info = &info;
5580 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5581 "QueryAliasInfo failed");
5582 if (!NT_STATUS_IS_OK(r.out.result)) {
5583 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5584 levels[i], nt_errstr(r.out.result));
5585 ret = false;
5589 return ret;
5592 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5593 struct torture_context *tctx,
5594 struct policy_handle *handle)
5596 struct samr_QueryGroupInfo r;
5597 union samr_GroupInfo *info;
5598 uint16_t levels[] = {1, 2, 3, 4, 5};
5599 int i;
5600 bool ret = true;
5602 for (i=0;i<ARRAY_SIZE(levels);i++) {
5603 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5605 r.in.group_handle = handle;
5606 r.in.level = levels[i];
5607 r.out.info = &info;
5609 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5610 "QueryGroupInfo failed");
5611 if (!NT_STATUS_IS_OK(r.out.result)) {
5612 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5613 levels[i], nt_errstr(r.out.result));
5614 ret = false;
5618 return ret;
5621 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5622 struct torture_context *tctx,
5623 struct policy_handle *handle)
5625 struct samr_QueryGroupMember r;
5626 struct samr_RidAttrArray *rids = NULL;
5627 bool ret = true;
5629 torture_comment(tctx, "Testing QueryGroupMember\n");
5631 r.in.group_handle = handle;
5632 r.out.rids = &rids;
5634 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5635 "QueryGroupMember failed");
5636 if (!NT_STATUS_IS_OK(r.out.result)) {
5637 torture_warning(tctx, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
5638 ret = false;
5641 return ret;
5645 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5646 struct torture_context *tctx,
5647 struct policy_handle *handle)
5649 struct samr_QueryGroupInfo r;
5650 union samr_GroupInfo *info;
5651 struct samr_SetGroupInfo s;
5652 uint16_t levels[] = {1, 2, 3, 4};
5653 uint16_t set_ok[] = {0, 1, 1, 1};
5654 int i;
5655 bool ret = true;
5657 for (i=0;i<ARRAY_SIZE(levels);i++) {
5658 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5660 r.in.group_handle = handle;
5661 r.in.level = levels[i];
5662 r.out.info = &info;
5664 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5665 "QueryGroupInfo failed");
5666 if (!NT_STATUS_IS_OK(r.out.result)) {
5667 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5668 levels[i], nt_errstr(r.out.result));
5669 ret = false;
5672 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5674 s.in.group_handle = handle;
5675 s.in.level = levels[i];
5676 s.in.info = *r.out.info;
5678 #if 0
5679 /* disabled this, as it changes the name only from the point of view of samr,
5680 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5681 the name is still reserved, so creating the old name fails, but deleting by the old name
5682 also fails */
5683 if (s.in.level == 2) {
5684 init_lsa_String(&s.in.info->string, "NewName");
5686 #endif
5688 if (s.in.level == 4) {
5689 init_lsa_String(&s.in.info->description, "test description");
5692 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5693 "SetGroupInfo failed");
5694 if (set_ok[i]) {
5695 if (!NT_STATUS_IS_OK(s.out.result)) {
5696 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5697 r.in.level, nt_errstr(s.out.result));
5698 ret = false;
5699 continue;
5701 } else {
5702 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5703 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5704 r.in.level, nt_errstr(s.out.result));
5705 ret = false;
5706 continue;
5711 return ret;
5714 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5715 struct torture_context *tctx,
5716 struct policy_handle *handle)
5718 struct samr_QueryUserInfo r;
5719 union samr_UserInfo *info;
5720 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5721 11, 12, 13, 14, 16, 17, 20, 21};
5722 int i;
5723 bool ret = true;
5725 for (i=0;i<ARRAY_SIZE(levels);i++) {
5726 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5728 r.in.user_handle = handle;
5729 r.in.level = levels[i];
5730 r.out.info = &info;
5732 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5733 "QueryUserInfo failed");
5734 if (!NT_STATUS_IS_OK(r.out.result)) {
5735 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5736 levels[i], nt_errstr(r.out.result));
5737 ret = false;
5741 return ret;
5744 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5745 struct torture_context *tctx,
5746 struct policy_handle *handle)
5748 struct samr_QueryUserInfo2 r;
5749 union samr_UserInfo *info;
5750 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5751 11, 12, 13, 14, 16, 17, 20, 21};
5752 int i;
5753 bool ret = true;
5755 for (i=0;i<ARRAY_SIZE(levels);i++) {
5756 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5758 r.in.user_handle = handle;
5759 r.in.level = levels[i];
5760 r.out.info = &info;
5762 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5763 "QueryUserInfo2 failed");
5764 if (!NT_STATUS_IS_OK(r.out.result)) {
5765 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5766 levels[i], nt_errstr(r.out.result));
5767 ret = false;
5771 return ret;
5774 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5775 struct torture_context *tctx,
5776 struct policy_handle *handle, uint32_t rid)
5778 struct samr_OpenUser r;
5779 struct policy_handle user_handle;
5780 bool ret = true;
5782 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5784 r.in.domain_handle = handle;
5785 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5786 r.in.rid = rid;
5787 r.out.user_handle = &user_handle;
5789 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5790 "OpenUser failed");
5791 if (!NT_STATUS_IS_OK(r.out.result)) {
5792 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5793 return false;
5796 if (!test_QuerySecurity(b, tctx, &user_handle)) {
5797 ret = false;
5800 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5801 ret = false;
5804 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5805 ret = false;
5808 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5809 ret = false;
5812 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5813 ret = false;
5816 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5817 ret = false;
5820 return ret;
5823 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5824 struct torture_context *tctx,
5825 struct policy_handle *handle, uint32_t rid)
5827 struct samr_OpenGroup r;
5828 struct policy_handle group_handle;
5829 bool ret = true;
5831 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5833 r.in.domain_handle = handle;
5834 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5835 r.in.rid = rid;
5836 r.out.group_handle = &group_handle;
5838 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5839 "OpenGroup failed");
5840 if (!NT_STATUS_IS_OK(r.out.result)) {
5841 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5842 return false;
5845 if (!torture_setting_bool(tctx, "samba3", false)) {
5846 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5847 ret = false;
5851 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5852 ret = false;
5855 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5856 ret = false;
5859 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5860 ret = false;
5863 return ret;
5866 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5867 struct torture_context *tctx,
5868 struct policy_handle *handle, uint32_t rid)
5870 struct samr_OpenAlias r;
5871 struct policy_handle alias_handle;
5872 bool ret = true;
5874 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5876 r.in.domain_handle = handle;
5877 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5878 r.in.rid = rid;
5879 r.out.alias_handle = &alias_handle;
5881 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5882 "OpenAlias failed");
5883 if (!NT_STATUS_IS_OK(r.out.result)) {
5884 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5885 return false;
5888 if (!torture_setting_bool(tctx, "samba3", false)) {
5889 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
5890 ret = false;
5894 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
5895 ret = false;
5898 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
5899 ret = false;
5902 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
5903 ret = false;
5906 return ret;
5909 static bool check_mask(struct dcerpc_binding_handle *b,
5910 struct torture_context *tctx,
5911 struct policy_handle *handle, uint32_t rid,
5912 uint32_t acct_flag_mask)
5914 struct samr_OpenUser r;
5915 struct samr_QueryUserInfo q;
5916 union samr_UserInfo *info;
5917 struct policy_handle user_handle;
5918 bool ret = true;
5920 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5922 r.in.domain_handle = handle;
5923 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5924 r.in.rid = rid;
5925 r.out.user_handle = &user_handle;
5927 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5928 "OpenUser failed");
5929 if (!NT_STATUS_IS_OK(r.out.result)) {
5930 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5931 return false;
5934 q.in.user_handle = &user_handle;
5935 q.in.level = 16;
5936 q.out.info = &info;
5938 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5939 "QueryUserInfo failed");
5940 if (!NT_STATUS_IS_OK(q.out.result)) {
5941 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
5942 nt_errstr(q.out.result));
5943 ret = false;
5944 } else {
5945 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
5946 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
5947 acct_flag_mask, info->info16.acct_flags, rid);
5948 ret = false;
5952 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5953 ret = false;
5956 return ret;
5959 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
5960 struct torture_context *tctx,
5961 struct policy_handle *handle)
5963 struct samr_EnumDomainUsers r;
5964 uint32_t mask, resume_handle=0;
5965 int i, mask_idx;
5966 bool ret = true;
5967 struct samr_LookupNames n;
5968 struct samr_LookupRids lr ;
5969 struct lsa_Strings names;
5970 struct samr_Ids rids, types;
5971 struct samr_SamArray *sam = NULL;
5972 uint32_t num_entries = 0;
5974 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
5975 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
5976 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
5977 ACB_PWNOEXP, 0};
5979 torture_comment(tctx, "Testing EnumDomainUsers\n");
5981 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
5982 r.in.domain_handle = handle;
5983 r.in.resume_handle = &resume_handle;
5984 r.in.acct_flags = mask = masks[mask_idx];
5985 r.in.max_size = (uint32_t)-1;
5986 r.out.resume_handle = &resume_handle;
5987 r.out.num_entries = &num_entries;
5988 r.out.sam = &sam;
5990 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
5991 "EnumDomainUsers failed");
5992 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
5993 !NT_STATUS_IS_OK(r.out.result)) {
5994 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
5995 return false;
5998 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6000 if (sam->count == 0) {
6001 continue;
6004 for (i=0;i<sam->count;i++) {
6005 if (mask) {
6006 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6007 ret = false;
6009 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6010 ret = false;
6015 torture_comment(tctx, "Testing LookupNames\n");
6016 n.in.domain_handle = handle;
6017 n.in.num_names = sam->count;
6018 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6019 n.out.rids = &rids;
6020 n.out.types = &types;
6021 for (i=0;i<sam->count;i++) {
6022 n.in.names[i].string = sam->entries[i].name.string;
6024 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6025 "LookupNames failed");
6026 if (!NT_STATUS_IS_OK(n.out.result)) {
6027 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6028 ret = false;
6032 torture_comment(tctx, "Testing LookupRids\n");
6033 lr.in.domain_handle = handle;
6034 lr.in.num_rids = sam->count;
6035 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6036 lr.out.names = &names;
6037 lr.out.types = &types;
6038 for (i=0;i<sam->count;i++) {
6039 lr.in.rids[i] = sam->entries[i].idx;
6041 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6042 "LookupRids failed");
6043 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6045 return ret;
6049 try blasting the server with a bunch of sync requests
6051 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6052 struct policy_handle *handle)
6054 struct samr_EnumDomainUsers r;
6055 uint32_t resume_handle=0;
6056 int i;
6057 #define ASYNC_COUNT 100
6058 struct tevent_req *req[ASYNC_COUNT];
6060 if (!torture_setting_bool(tctx, "dangerous", false)) {
6061 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6064 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6066 r.in.domain_handle = handle;
6067 r.in.resume_handle = &resume_handle;
6068 r.in.acct_flags = 0;
6069 r.in.max_size = (uint32_t)-1;
6070 r.out.resume_handle = &resume_handle;
6072 for (i=0;i<ASYNC_COUNT;i++) {
6073 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6076 for (i=0;i<ASYNC_COUNT;i++) {
6077 tevent_req_poll(req[i], tctx->ev);
6078 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6079 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6080 i, nt_errstr(r.out.result)));
6083 torture_comment(tctx, "%d async requests OK\n", i);
6085 return true;
6088 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6089 struct torture_context *tctx,
6090 struct policy_handle *handle)
6092 struct samr_EnumDomainGroups r;
6093 uint32_t resume_handle=0;
6094 struct samr_SamArray *sam = NULL;
6095 uint32_t num_entries = 0;
6096 int i;
6097 bool ret = true;
6098 bool universal_group_found = false;
6100 torture_comment(tctx, "Testing EnumDomainGroups\n");
6102 r.in.domain_handle = handle;
6103 r.in.resume_handle = &resume_handle;
6104 r.in.max_size = (uint32_t)-1;
6105 r.out.resume_handle = &resume_handle;
6106 r.out.num_entries = &num_entries;
6107 r.out.sam = &sam;
6109 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6110 "EnumDomainGroups failed");
6111 if (!NT_STATUS_IS_OK(r.out.result)) {
6112 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6113 return false;
6116 if (!sam) {
6117 return false;
6120 for (i=0;i<sam->count;i++) {
6121 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6122 ret = false;
6124 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6125 "Enterprise Admins") == 0)) {
6126 universal_group_found = true;
6130 /* when we are running this on s4 we should get back at least the
6131 * "Enterprise Admins" universal group. If we don't get a group entry
6132 * at all we probably are performing the test on the builtin domain.
6133 * So ignore this case. */
6134 if (torture_setting_bool(tctx, "samba4", false)) {
6135 if ((sam->count > 0) && (!universal_group_found)) {
6136 ret = false;
6140 return ret;
6143 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6144 struct torture_context *tctx,
6145 struct policy_handle *handle)
6147 struct samr_EnumDomainAliases r;
6148 uint32_t resume_handle=0;
6149 struct samr_SamArray *sam = NULL;
6150 uint32_t num_entries = 0;
6151 int i;
6152 bool ret = true;
6154 torture_comment(tctx, "Testing EnumDomainAliases\n");
6156 r.in.domain_handle = handle;
6157 r.in.resume_handle = &resume_handle;
6158 r.in.max_size = (uint32_t)-1;
6159 r.out.sam = &sam;
6160 r.out.num_entries = &num_entries;
6161 r.out.resume_handle = &resume_handle;
6163 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6164 "EnumDomainAliases failed");
6165 if (!NT_STATUS_IS_OK(r.out.result)) {
6166 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6167 return false;
6170 if (!sam) {
6171 return false;
6174 for (i=0;i<sam->count;i++) {
6175 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6176 ret = false;
6180 return ret;
6183 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6184 struct torture_context *tctx,
6185 struct policy_handle *handle)
6187 struct samr_GetDisplayEnumerationIndex r;
6188 bool ret = true;
6189 uint16_t levels[] = {1, 2, 3, 4, 5};
6190 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6191 struct lsa_String name;
6192 uint32_t idx = 0;
6193 int i;
6195 for (i=0;i<ARRAY_SIZE(levels);i++) {
6196 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6198 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6200 r.in.domain_handle = handle;
6201 r.in.level = levels[i];
6202 r.in.name = &name;
6203 r.out.idx = &idx;
6205 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6206 "GetDisplayEnumerationIndex failed");
6208 if (ok_lvl[i] &&
6209 !NT_STATUS_IS_OK(r.out.result) &&
6210 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6211 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6212 levels[i], nt_errstr(r.out.result));
6213 ret = false;
6216 init_lsa_String(&name, "zzzzzzzz");
6218 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6219 "GetDisplayEnumerationIndex failed");
6221 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6222 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6223 levels[i], nt_errstr(r.out.result));
6224 ret = false;
6228 return ret;
6231 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6232 struct torture_context *tctx,
6233 struct policy_handle *handle)
6235 struct samr_GetDisplayEnumerationIndex2 r;
6236 bool ret = true;
6237 uint16_t levels[] = {1, 2, 3, 4, 5};
6238 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6239 struct lsa_String name;
6240 uint32_t idx = 0;
6241 int i;
6243 for (i=0;i<ARRAY_SIZE(levels);i++) {
6244 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6246 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6248 r.in.domain_handle = handle;
6249 r.in.level = levels[i];
6250 r.in.name = &name;
6251 r.out.idx = &idx;
6253 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6254 "GetDisplayEnumerationIndex2 failed");
6255 if (ok_lvl[i] &&
6256 !NT_STATUS_IS_OK(r.out.result) &&
6257 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6258 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6259 levels[i], nt_errstr(r.out.result));
6260 ret = false;
6263 init_lsa_String(&name, "zzzzzzzz");
6265 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6266 "GetDisplayEnumerationIndex2 failed");
6267 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6268 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6269 levels[i], nt_errstr(r.out.result));
6270 ret = false;
6274 return ret;
6277 #define STRING_EQUAL_QUERY(s1, s2, user) \
6278 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6279 /* odd, but valid */ \
6280 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6281 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6282 #s1, user.string, s1.string, s2.string, __location__); \
6283 ret = false; \
6285 #define INT_EQUAL_QUERY(s1, s2, user) \
6286 if (s1 != s2) { \
6287 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6288 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6289 ret = false; \
6292 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6293 struct torture_context *tctx,
6294 struct samr_QueryDisplayInfo *querydisplayinfo,
6295 bool *seen_testuser)
6297 struct samr_OpenUser r;
6298 struct samr_QueryUserInfo q;
6299 union samr_UserInfo *info;
6300 struct policy_handle user_handle;
6301 int i, ret = true;
6302 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6303 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6304 for (i = 0; ; i++) {
6305 switch (querydisplayinfo->in.level) {
6306 case 1:
6307 if (i >= querydisplayinfo->out.info->info1.count) {
6308 return ret;
6310 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6311 break;
6312 case 2:
6313 if (i >= querydisplayinfo->out.info->info2.count) {
6314 return ret;
6316 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6317 break;
6318 case 3:
6319 /* Groups */
6320 case 4:
6321 case 5:
6322 /* Not interested in validating just the account name */
6323 return true;
6326 r.out.user_handle = &user_handle;
6328 switch (querydisplayinfo->in.level) {
6329 case 1:
6330 case 2:
6331 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6332 "OpenUser failed");
6333 if (!NT_STATUS_IS_OK(r.out.result)) {
6334 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6335 return false;
6339 q.in.user_handle = &user_handle;
6340 q.in.level = 21;
6341 q.out.info = &info;
6342 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6343 "QueryUserInfo failed");
6344 if (!NT_STATUS_IS_OK(r.out.result)) {
6345 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6346 return false;
6349 switch (querydisplayinfo->in.level) {
6350 case 1:
6351 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6352 *seen_testuser = true;
6354 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6355 info->info21.full_name, info->info21.account_name);
6356 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6357 info->info21.account_name, info->info21.account_name);
6358 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6359 info->info21.description, info->info21.account_name);
6360 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6361 info->info21.rid, info->info21.account_name);
6362 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6363 info->info21.acct_flags, info->info21.account_name);
6365 break;
6366 case 2:
6367 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6368 info->info21.account_name, info->info21.account_name);
6369 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6370 info->info21.description, info->info21.account_name);
6371 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6372 info->info21.rid, info->info21.account_name);
6373 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6374 info->info21.acct_flags, info->info21.account_name);
6376 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6377 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6378 info->info21.account_name.string);
6381 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6382 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6383 info->info21.account_name.string,
6384 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6385 info->info21.acct_flags);
6386 return false;
6389 break;
6392 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6393 return false;
6396 return ret;
6399 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6400 struct torture_context *tctx,
6401 struct policy_handle *handle)
6403 struct samr_QueryDisplayInfo r;
6404 struct samr_QueryDomainInfo dom_info;
6405 union samr_DomainInfo *info = NULL;
6406 bool ret = true;
6407 uint16_t levels[] = {1, 2, 3, 4, 5};
6408 int i;
6409 bool seen_testuser = false;
6410 uint32_t total_size;
6411 uint32_t returned_size;
6412 union samr_DispInfo disp_info;
6415 for (i=0;i<ARRAY_SIZE(levels);i++) {
6416 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6418 r.in.start_idx = 0;
6419 r.out.result = STATUS_MORE_ENTRIES;
6420 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6421 r.in.domain_handle = handle;
6422 r.in.level = levels[i];
6423 r.in.max_entries = 2;
6424 r.in.buf_size = (uint32_t)-1;
6425 r.out.total_size = &total_size;
6426 r.out.returned_size = &returned_size;
6427 r.out.info = &disp_info;
6429 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6430 "QueryDisplayInfo failed");
6431 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6432 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6433 levels[i], nt_errstr(r.out.result));
6434 ret = false;
6436 switch (r.in.level) {
6437 case 1:
6438 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6439 ret = false;
6441 r.in.start_idx += r.out.info->info1.count;
6442 break;
6443 case 2:
6444 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6445 ret = false;
6447 r.in.start_idx += r.out.info->info2.count;
6448 break;
6449 case 3:
6450 r.in.start_idx += r.out.info->info3.count;
6451 break;
6452 case 4:
6453 r.in.start_idx += r.out.info->info4.count;
6454 break;
6455 case 5:
6456 r.in.start_idx += r.out.info->info5.count;
6457 break;
6460 dom_info.in.domain_handle = handle;
6461 dom_info.in.level = 2;
6462 dom_info.out.info = &info;
6464 /* Check number of users returned is correct */
6465 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6466 "QueryDomainInfo failed");
6467 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6468 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6469 r.in.level, nt_errstr(dom_info.out.result));
6470 ret = false;
6471 break;
6473 switch (r.in.level) {
6474 case 1:
6475 case 4:
6476 if (info->general.num_users < r.in.start_idx) {
6477 /* On AD deployments this numbers don't match
6478 * since QueryDisplayInfo returns universal and
6479 * global groups, QueryDomainInfo only global
6480 * ones. */
6481 if (torture_setting_bool(tctx, "samba3", false)) {
6482 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6483 r.in.start_idx, info->general.num_groups,
6484 info->general.domain_name.string);
6485 ret = false;
6488 if (!seen_testuser) {
6489 struct policy_handle user_handle;
6490 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6491 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6492 info->general.domain_name.string);
6493 ret = false;
6494 test_samr_handle_Close(b, tctx, &user_handle);
6497 break;
6498 case 3:
6499 case 5:
6500 if (info->general.num_groups != r.in.start_idx) {
6501 /* On AD deployments this numbers don't match
6502 * since QueryDisplayInfo returns universal and
6503 * global groups, QueryDomainInfo only global
6504 * ones. */
6505 if (torture_setting_bool(tctx, "samba3", false)) {
6506 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6507 r.in.start_idx, info->general.num_groups,
6508 info->general.domain_name.string);
6509 ret = false;
6513 break;
6518 return ret;
6521 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6522 struct torture_context *tctx,
6523 struct policy_handle *handle)
6525 struct samr_QueryDisplayInfo2 r;
6526 bool ret = true;
6527 uint16_t levels[] = {1, 2, 3, 4, 5};
6528 int i;
6529 uint32_t total_size;
6530 uint32_t returned_size;
6531 union samr_DispInfo info;
6533 for (i=0;i<ARRAY_SIZE(levels);i++) {
6534 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6536 r.in.domain_handle = handle;
6537 r.in.level = levels[i];
6538 r.in.start_idx = 0;
6539 r.in.max_entries = 1000;
6540 r.in.buf_size = (uint32_t)-1;
6541 r.out.total_size = &total_size;
6542 r.out.returned_size = &returned_size;
6543 r.out.info = &info;
6545 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6546 "QueryDisplayInfo2 failed");
6547 if (!NT_STATUS_IS_OK(r.out.result)) {
6548 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6549 levels[i], nt_errstr(r.out.result));
6550 ret = false;
6554 return ret;
6557 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6558 struct torture_context *tctx,
6559 struct policy_handle *handle)
6561 struct samr_QueryDisplayInfo3 r;
6562 bool ret = true;
6563 uint16_t levels[] = {1, 2, 3, 4, 5};
6564 int i;
6565 uint32_t total_size;
6566 uint32_t returned_size;
6567 union samr_DispInfo info;
6569 for (i=0;i<ARRAY_SIZE(levels);i++) {
6570 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6572 r.in.domain_handle = handle;
6573 r.in.level = levels[i];
6574 r.in.start_idx = 0;
6575 r.in.max_entries = 1000;
6576 r.in.buf_size = (uint32_t)-1;
6577 r.out.total_size = &total_size;
6578 r.out.returned_size = &returned_size;
6579 r.out.info = &info;
6581 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6582 "QueryDisplayInfo3 failed");
6583 if (!NT_STATUS_IS_OK(r.out.result)) {
6584 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6585 levels[i], nt_errstr(r.out.result));
6586 ret = false;
6590 return ret;
6594 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6595 struct torture_context *tctx,
6596 struct policy_handle *handle)
6598 struct samr_QueryDisplayInfo r;
6599 bool ret = true;
6600 uint32_t total_size;
6601 uint32_t returned_size;
6602 union samr_DispInfo info;
6604 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6606 r.in.domain_handle = handle;
6607 r.in.level = 1;
6608 r.in.start_idx = 0;
6609 r.in.max_entries = 1;
6610 r.in.buf_size = (uint32_t)-1;
6611 r.out.total_size = &total_size;
6612 r.out.returned_size = &returned_size;
6613 r.out.info = &info;
6615 do {
6616 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6617 "QueryDisplayInfo failed");
6618 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6619 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6620 torture_warning(tctx, "expected idx %d but got %d\n",
6621 r.in.start_idx + 1,
6622 r.out.info->info1.entries[0].idx);
6623 break;
6626 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6627 !NT_STATUS_IS_OK(r.out.result)) {
6628 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6629 r.in.level, nt_errstr(r.out.result));
6630 ret = false;
6631 break;
6633 r.in.start_idx++;
6634 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6635 NT_STATUS_IS_OK(r.out.result)) &&
6636 *r.out.returned_size != 0);
6638 return ret;
6641 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6642 struct torture_context *tctx,
6643 struct policy_handle *handle)
6645 struct samr_QueryDomainInfo r;
6646 union samr_DomainInfo *info = NULL;
6647 struct samr_SetDomainInfo s;
6648 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6649 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6650 int i;
6651 bool ret = true;
6652 struct dcerpc_binding_handle *b = p->binding_handle;
6653 const char *domain_comment = talloc_asprintf(tctx,
6654 "Tortured by Samba4 RPC-SAMR: %s",
6655 timestring(tctx, time(NULL)));
6657 s.in.domain_handle = handle;
6658 s.in.level = 4;
6659 s.in.info = talloc(tctx, union samr_DomainInfo);
6661 s.in.info->oem.oem_information.string = domain_comment;
6662 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6663 "SetDomainInfo failed");
6664 if (!NT_STATUS_IS_OK(s.out.result)) {
6665 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6666 s.in.level, nt_errstr(s.out.result));
6667 return false;
6670 for (i=0;i<ARRAY_SIZE(levels);i++) {
6671 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6673 r.in.domain_handle = handle;
6674 r.in.level = levels[i];
6675 r.out.info = &info;
6677 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6678 "QueryDomainInfo failed");
6679 if (!NT_STATUS_IS_OK(r.out.result)) {
6680 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6681 r.in.level, nt_errstr(r.out.result));
6682 ret = false;
6683 continue;
6686 switch (levels[i]) {
6687 case 2:
6688 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6689 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6690 levels[i], info->general.oem_information.string, domain_comment);
6691 if (!torture_setting_bool(tctx, "samba3", false)) {
6692 ret = false;
6695 if (!info->general.primary.string) {
6696 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6697 levels[i]);
6698 ret = false;
6699 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6700 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6701 if (torture_setting_bool(tctx, "samba3", false)) {
6702 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6703 levels[i], info->general.primary.string, dcerpc_server_name(p));
6707 break;
6708 case 4:
6709 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6710 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6711 levels[i], info->oem.oem_information.string, domain_comment);
6712 if (!torture_setting_bool(tctx, "samba3", false)) {
6713 ret = false;
6716 break;
6717 case 6:
6718 if (!info->info6.primary.string) {
6719 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6720 levels[i]);
6721 ret = false;
6723 break;
6724 case 11:
6725 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6726 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6727 levels[i], info->general2.general.oem_information.string, domain_comment);
6728 if (!torture_setting_bool(tctx, "samba3", false)) {
6729 ret = false;
6732 break;
6735 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6737 s.in.domain_handle = handle;
6738 s.in.level = levels[i];
6739 s.in.info = info;
6741 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6742 "SetDomainInfo failed");
6743 if (set_ok[i]) {
6744 if (!NT_STATUS_IS_OK(s.out.result)) {
6745 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6746 r.in.level, nt_errstr(s.out.result));
6747 ret = false;
6748 continue;
6750 } else {
6751 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6752 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6753 r.in.level, nt_errstr(s.out.result));
6754 ret = false;
6755 continue;
6759 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6760 "QueryDomainInfo failed");
6761 if (!NT_STATUS_IS_OK(r.out.result)) {
6762 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6763 r.in.level, nt_errstr(r.out.result));
6764 ret = false;
6765 continue;
6769 return ret;
6773 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6774 struct torture_context *tctx,
6775 struct policy_handle *handle)
6777 struct samr_QueryDomainInfo2 r;
6778 union samr_DomainInfo *info = NULL;
6779 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6780 int i;
6781 bool ret = true;
6783 for (i=0;i<ARRAY_SIZE(levels);i++) {
6784 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6786 r.in.domain_handle = handle;
6787 r.in.level = levels[i];
6788 r.out.info = &info;
6790 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6791 "QueryDomainInfo2 failed");
6792 if (!NT_STATUS_IS_OK(r.out.result)) {
6793 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6794 r.in.level, nt_errstr(r.out.result));
6795 ret = false;
6796 continue;
6800 return true;
6803 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6804 set of group names. */
6805 static bool test_GroupList(struct dcerpc_binding_handle *b,
6806 struct torture_context *tctx,
6807 struct dom_sid *domain_sid,
6808 struct policy_handle *handle)
6810 struct samr_EnumDomainGroups q1;
6811 struct samr_QueryDisplayInfo q2;
6812 NTSTATUS status;
6813 uint32_t resume_handle=0;
6814 struct samr_SamArray *sam = NULL;
6815 uint32_t num_entries = 0;
6816 int i;
6817 bool ret = true;
6818 uint32_t total_size;
6819 uint32_t returned_size;
6820 union samr_DispInfo info;
6822 int num_names = 0;
6823 const char **names = NULL;
6825 bool builtin_domain = dom_sid_compare(domain_sid,
6826 &global_sid_Builtin) == 0;
6828 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6830 q1.in.domain_handle = handle;
6831 q1.in.resume_handle = &resume_handle;
6832 q1.in.max_size = 5;
6833 q1.out.resume_handle = &resume_handle;
6834 q1.out.num_entries = &num_entries;
6835 q1.out.sam = &sam;
6837 status = STATUS_MORE_ENTRIES;
6838 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6839 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6840 "EnumDomainGroups failed");
6841 status = q1.out.result;
6843 if (!NT_STATUS_IS_OK(status) &&
6844 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6845 break;
6847 for (i=0; i<*q1.out.num_entries; i++) {
6848 add_string_to_array(tctx,
6849 sam->entries[i].name.string,
6850 &names, &num_names);
6854 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6856 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6858 if (builtin_domain) {
6859 torture_assert(tctx, num_names == 0,
6860 "EnumDomainGroups shouldn't return any group in the builtin domain!");
6863 q2.in.domain_handle = handle;
6864 q2.in.level = 5;
6865 q2.in.start_idx = 0;
6866 q2.in.max_entries = 5;
6867 q2.in.buf_size = (uint32_t)-1;
6868 q2.out.total_size = &total_size;
6869 q2.out.returned_size = &returned_size;
6870 q2.out.info = &info;
6872 status = STATUS_MORE_ENTRIES;
6873 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6874 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
6875 "QueryDisplayInfo failed");
6876 status = q2.out.result;
6877 if (!NT_STATUS_IS_OK(status) &&
6878 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6879 break;
6881 for (i=0; i<q2.out.info->info5.count; i++) {
6882 int j;
6883 const char *name = q2.out.info->info5.entries[i].account_name.string;
6884 bool found = false;
6885 for (j=0; j<num_names; j++) {
6886 if (names[j] == NULL)
6887 continue;
6888 if (strequal(names[j], name)) {
6889 names[j] = NULL;
6890 found = true;
6891 break;
6895 if ((!found) && (!builtin_domain)) {
6896 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
6897 name);
6898 ret = false;
6901 q2.in.start_idx += q2.out.info->info5.count;
6904 if (!NT_STATUS_IS_OK(status)) {
6905 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
6906 nt_errstr(status));
6907 ret = false;
6910 if (builtin_domain) {
6911 torture_assert(tctx, q2.in.start_idx != 0,
6912 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
6915 for (i=0; i<num_names; i++) {
6916 if (names[i] != NULL) {
6917 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
6918 names[i]);
6919 ret = false;
6923 return ret;
6926 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
6927 struct torture_context *tctx,
6928 struct policy_handle *group_handle)
6930 struct samr_DeleteDomainGroup d;
6932 torture_comment(tctx, "Testing DeleteDomainGroup\n");
6934 d.in.group_handle = group_handle;
6935 d.out.group_handle = group_handle;
6937 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
6938 "DeleteDomainGroup failed");
6939 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
6941 return true;
6944 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
6945 struct torture_context *tctx,
6946 struct policy_handle *domain_handle)
6948 struct samr_TestPrivateFunctionsDomain r;
6949 bool ret = true;
6951 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
6953 r.in.domain_handle = domain_handle;
6955 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
6956 "TestPrivateFunctionsDomain failed");
6957 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
6959 return ret;
6962 static bool test_RidToSid(struct dcerpc_binding_handle *b,
6963 struct torture_context *tctx,
6964 struct dom_sid *domain_sid,
6965 struct policy_handle *domain_handle)
6967 struct samr_RidToSid r;
6968 bool ret = true;
6969 struct dom_sid *calc_sid, *out_sid;
6970 int rids[] = { 0, 42, 512, 10200 };
6971 int i;
6973 for (i=0;i<ARRAY_SIZE(rids);i++) {
6974 torture_comment(tctx, "Testing RidToSid\n");
6976 calc_sid = dom_sid_dup(tctx, domain_sid);
6977 r.in.domain_handle = domain_handle;
6978 r.in.rid = rids[i];
6979 r.out.sid = &out_sid;
6981 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
6982 "RidToSid failed");
6983 if (!NT_STATUS_IS_OK(r.out.result)) {
6984 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
6985 ret = false;
6986 } else {
6987 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
6989 if (!dom_sid_equal(calc_sid, out_sid)) {
6990 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
6991 dom_sid_string(tctx, out_sid),
6992 dom_sid_string(tctx, calc_sid));
6993 ret = false;
6998 return ret;
7001 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7002 struct torture_context *tctx,
7003 struct policy_handle *domain_handle)
7005 struct samr_GetBootKeyInformation r;
7006 bool ret = true;
7007 uint32_t unknown = 0;
7008 NTSTATUS status;
7010 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7012 r.in.domain_handle = domain_handle;
7013 r.out.unknown = &unknown;
7015 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7016 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7017 status = r.out.result;
7019 if (!NT_STATUS_IS_OK(status)) {
7020 /* w2k3 seems to fail this sometimes and pass it sometimes */
7021 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7024 return ret;
7027 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7028 struct torture_context *tctx,
7029 struct policy_handle *domain_handle,
7030 struct policy_handle *group_handle)
7032 NTSTATUS status;
7033 struct samr_AddGroupMember r;
7034 struct samr_DeleteGroupMember d;
7035 struct samr_QueryGroupMember q;
7036 struct samr_RidAttrArray *rids = NULL;
7037 struct samr_SetMemberAttributesOfGroup s;
7038 uint32_t rid;
7039 bool found_member = false;
7040 int i;
7042 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7043 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7045 r.in.group_handle = group_handle;
7046 r.in.rid = rid;
7047 r.in.flags = 0; /* ??? */
7049 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7051 d.in.group_handle = group_handle;
7052 d.in.rid = rid;
7054 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7055 "DeleteGroupMember failed");
7056 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7058 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7059 "AddGroupMember failed");
7060 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7062 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7063 "AddGroupMember failed");
7064 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7066 if (torture_setting_bool(tctx, "samba4", false) ||
7067 torture_setting_bool(tctx, "samba3", false)) {
7068 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7069 } else {
7070 /* this one is quite strange. I am using random inputs in the
7071 hope of triggering an error that might give us a clue */
7073 s.in.group_handle = group_handle;
7074 s.in.unknown1 = random();
7075 s.in.unknown2 = random();
7077 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7078 "SetMemberAttributesOfGroup failed");
7079 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7082 q.in.group_handle = group_handle;
7083 q.out.rids = &rids;
7085 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7086 "QueryGroupMember failed");
7087 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7088 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7090 for (i=0; i < rids->count; i++) {
7091 if (rids->rids[i] == rid) {
7092 found_member = true;
7096 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7098 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7099 "DeleteGroupMember failed");
7100 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7102 rids = NULL;
7103 found_member = false;
7105 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7106 "QueryGroupMember failed");
7107 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7108 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7110 for (i=0; i < rids->count; i++) {
7111 if (rids->rids[i] == rid) {
7112 found_member = true;
7116 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7118 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7119 "AddGroupMember failed");
7120 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7122 return true;
7126 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7127 struct torture_context *tctx,
7128 struct policy_handle *domain_handle,
7129 const char *group_name,
7130 struct policy_handle *group_handle,
7131 struct dom_sid *domain_sid,
7132 bool test_group)
7134 struct samr_CreateDomainGroup r;
7135 uint32_t rid;
7136 struct lsa_String name;
7137 bool ret = true;
7139 init_lsa_String(&name, group_name);
7141 r.in.domain_handle = domain_handle;
7142 r.in.name = &name;
7143 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7144 r.out.group_handle = group_handle;
7145 r.out.rid = &rid;
7147 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7149 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7150 "CreateDomainGroup failed");
7152 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7153 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7154 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7155 return true;
7156 } else {
7157 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7158 nt_errstr(r.out.result));
7159 return false;
7163 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7164 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7165 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7166 nt_errstr(r.out.result));
7167 return false;
7169 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7170 "CreateDomainGroup failed");
7172 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7173 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7175 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7176 nt_errstr(r.out.result));
7177 return false;
7179 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7180 "CreateDomainGroup failed");
7182 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7184 if (!test_group) {
7185 return ret;
7188 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7189 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7190 ret = false;
7193 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7194 ret = false;
7197 return ret;
7202 its not totally clear what this does. It seems to accept any sid you like.
7204 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7205 struct torture_context *tctx,
7206 struct policy_handle *domain_handle)
7208 struct samr_RemoveMemberFromForeignDomain r;
7210 r.in.domain_handle = domain_handle;
7211 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7213 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7214 "RemoveMemberFromForeignDomain failed");
7215 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7217 return true;
7220 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7221 struct torture_context *tctx,
7222 struct policy_handle *domain_handle,
7223 uint32_t *total_num_entries_p)
7225 NTSTATUS status;
7226 struct samr_EnumDomainUsers r;
7227 uint32_t resume_handle = 0;
7228 uint32_t num_entries = 0;
7229 uint32_t total_num_entries = 0;
7230 struct samr_SamArray *sam;
7232 r.in.domain_handle = domain_handle;
7233 r.in.acct_flags = 0;
7234 r.in.max_size = (uint32_t)-1;
7235 r.in.resume_handle = &resume_handle;
7237 r.out.sam = &sam;
7238 r.out.num_entries = &num_entries;
7239 r.out.resume_handle = &resume_handle;
7241 torture_comment(tctx, "Testing EnumDomainUsers\n");
7243 do {
7244 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7245 "EnumDomainUsers failed");
7246 if (NT_STATUS_IS_ERR(r.out.result)) {
7247 torture_assert_ntstatus_ok(tctx, r.out.result,
7248 "failed to enumerate users");
7250 status = r.out.result;
7252 total_num_entries += num_entries;
7253 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7255 if (total_num_entries_p) {
7256 *total_num_entries_p = total_num_entries;
7259 return true;
7262 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7263 struct torture_context *tctx,
7264 struct policy_handle *domain_handle,
7265 uint32_t *total_num_entries_p)
7267 NTSTATUS status;
7268 struct samr_EnumDomainGroups r;
7269 uint32_t resume_handle = 0;
7270 uint32_t num_entries = 0;
7271 uint32_t total_num_entries = 0;
7272 struct samr_SamArray *sam;
7274 r.in.domain_handle = domain_handle;
7275 r.in.max_size = (uint32_t)-1;
7276 r.in.resume_handle = &resume_handle;
7278 r.out.sam = &sam;
7279 r.out.num_entries = &num_entries;
7280 r.out.resume_handle = &resume_handle;
7282 torture_comment(tctx, "Testing EnumDomainGroups\n");
7284 do {
7285 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7286 "EnumDomainGroups failed");
7287 if (NT_STATUS_IS_ERR(r.out.result)) {
7288 torture_assert_ntstatus_ok(tctx, r.out.result,
7289 "failed to enumerate groups");
7291 status = r.out.result;
7293 total_num_entries += num_entries;
7294 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7296 if (total_num_entries_p) {
7297 *total_num_entries_p = total_num_entries;
7300 return true;
7303 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7304 struct torture_context *tctx,
7305 struct policy_handle *domain_handle,
7306 uint32_t *total_num_entries_p)
7308 NTSTATUS status;
7309 struct samr_EnumDomainAliases r;
7310 uint32_t resume_handle = 0;
7311 uint32_t num_entries = 0;
7312 uint32_t total_num_entries = 0;
7313 struct samr_SamArray *sam;
7315 r.in.domain_handle = domain_handle;
7316 r.in.max_size = (uint32_t)-1;
7317 r.in.resume_handle = &resume_handle;
7319 r.out.sam = &sam;
7320 r.out.num_entries = &num_entries;
7321 r.out.resume_handle = &resume_handle;
7323 torture_comment(tctx, "Testing EnumDomainAliases\n");
7325 do {
7326 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7327 "EnumDomainAliases failed");
7328 if (NT_STATUS_IS_ERR(r.out.result)) {
7329 torture_assert_ntstatus_ok(tctx, r.out.result,
7330 "failed to enumerate aliases");
7332 status = r.out.result;
7334 total_num_entries += num_entries;
7335 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7337 if (total_num_entries_p) {
7338 *total_num_entries_p = total_num_entries;
7341 return true;
7344 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7345 struct torture_context *tctx,
7346 struct policy_handle *handle,
7347 uint16_t level,
7348 uint32_t *total_num_entries_p)
7350 NTSTATUS status;
7351 struct samr_QueryDisplayInfo r;
7352 uint32_t total_num_entries = 0;
7354 r.in.domain_handle = handle;
7355 r.in.level = level;
7356 r.in.start_idx = 0;
7357 r.in.max_entries = (uint32_t)-1;
7358 r.in.buf_size = (uint32_t)-1;
7360 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7362 do {
7363 uint32_t total_size;
7364 uint32_t returned_size;
7365 union samr_DispInfo info;
7367 r.out.total_size = &total_size;
7368 r.out.returned_size = &returned_size;
7369 r.out.info = &info;
7371 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7372 "failed to query displayinfo");
7373 if (NT_STATUS_IS_ERR(r.out.result)) {
7374 torture_assert_ntstatus_ok(tctx, r.out.result,
7375 "failed to query displayinfo");
7377 status = r.out.result;
7379 if (*r.out.returned_size == 0) {
7380 break;
7383 switch (r.in.level) {
7384 case 1:
7385 total_num_entries += info.info1.count;
7386 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7387 break;
7388 case 2:
7389 total_num_entries += info.info2.count;
7390 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7391 break;
7392 case 3:
7393 total_num_entries += info.info3.count;
7394 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7395 break;
7396 case 4:
7397 total_num_entries += info.info4.count;
7398 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7399 break;
7400 case 5:
7401 total_num_entries += info.info5.count;
7402 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7403 break;
7404 default:
7405 return false;
7408 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7410 if (total_num_entries_p) {
7411 *total_num_entries_p = total_num_entries;
7414 return true;
7417 static bool test_ManyObjects(struct dcerpc_pipe *p,
7418 struct torture_context *tctx,
7419 struct policy_handle *domain_handle,
7420 struct dom_sid *domain_sid,
7421 struct torture_samr_context *ctx)
7423 uint32_t num_total = ctx->num_objects_large_dc;
7424 uint32_t num_enum = 0;
7425 uint32_t num_disp = 0;
7426 uint32_t num_created = 0;
7427 uint32_t num_anounced = 0;
7428 uint32_t i;
7429 struct dcerpc_binding_handle *b = p->binding_handle;
7431 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7433 /* query */
7436 struct samr_QueryDomainInfo2 r;
7437 union samr_DomainInfo *info;
7438 r.in.domain_handle = domain_handle;
7439 r.in.level = 2;
7440 r.out.info = &info;
7442 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7443 "QueryDomainInfo2 failed");
7444 torture_assert_ntstatus_ok(tctx, r.out.result,
7445 "failed to query domain info");
7447 switch (ctx->choice) {
7448 case TORTURE_SAMR_MANY_ACCOUNTS:
7449 num_anounced = info->general.num_users;
7450 break;
7451 case TORTURE_SAMR_MANY_GROUPS:
7452 num_anounced = info->general.num_groups;
7453 break;
7454 case TORTURE_SAMR_MANY_ALIASES:
7455 num_anounced = info->general.num_aliases;
7456 break;
7457 default:
7458 return false;
7462 /* create */
7464 for (i=0; i < num_total; i++) {
7466 const char *name = NULL;
7468 switch (ctx->choice) {
7469 case TORTURE_SAMR_MANY_ACCOUNTS:
7470 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7471 torture_assert(tctx,
7472 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7473 "failed to create user");
7474 break;
7475 case TORTURE_SAMR_MANY_GROUPS:
7476 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7477 torture_assert(tctx,
7478 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7479 "failed to create group");
7480 break;
7481 case TORTURE_SAMR_MANY_ALIASES:
7482 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7483 torture_assert(tctx,
7484 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7485 "failed to create alias");
7486 break;
7487 default:
7488 return false;
7490 if (!ndr_policy_handle_empty(&handles[i])) {
7491 num_created++;
7495 /* enum */
7497 switch (ctx->choice) {
7498 case TORTURE_SAMR_MANY_ACCOUNTS:
7499 torture_assert(tctx,
7500 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7501 "failed to enum users");
7502 break;
7503 case TORTURE_SAMR_MANY_GROUPS:
7504 torture_assert(tctx,
7505 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7506 "failed to enum groups");
7507 break;
7508 case TORTURE_SAMR_MANY_ALIASES:
7509 torture_assert(tctx,
7510 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7511 "failed to enum aliases");
7512 break;
7513 default:
7514 return false;
7517 /* dispinfo */
7519 switch (ctx->choice) {
7520 case TORTURE_SAMR_MANY_ACCOUNTS:
7521 torture_assert(tctx,
7522 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
7523 "failed to query display info");
7524 break;
7525 case TORTURE_SAMR_MANY_GROUPS:
7526 torture_assert(tctx,
7527 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
7528 "failed to query display info");
7529 break;
7530 case TORTURE_SAMR_MANY_ALIASES:
7531 /* no aliases in dispinfo */
7532 break;
7533 default:
7534 return false;
7537 /* close or delete */
7539 for (i=0; i < num_total; i++) {
7541 if (ndr_policy_handle_empty(&handles[i])) {
7542 continue;
7545 if (torture_setting_bool(tctx, "samba3", false)) {
7546 torture_assert(tctx,
7547 test_samr_handle_Close(b, tctx, &handles[i]),
7548 "failed to close handle");
7549 } else {
7550 switch (ctx->choice) {
7551 case TORTURE_SAMR_MANY_ACCOUNTS:
7552 torture_assert(tctx,
7553 test_DeleteUser(b, tctx, &handles[i]),
7554 "failed to delete user");
7555 break;
7556 case TORTURE_SAMR_MANY_GROUPS:
7557 torture_assert(tctx,
7558 test_DeleteDomainGroup(b, tctx, &handles[i]),
7559 "failed to delete group");
7560 break;
7561 case TORTURE_SAMR_MANY_ALIASES:
7562 torture_assert(tctx,
7563 test_DeleteAlias(b, tctx, &handles[i]),
7564 "failed to delete alias");
7565 break;
7566 default:
7567 return false;
7572 talloc_free(handles);
7574 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7575 torture_comment(tctx,
7576 "unexpected number of results (%u) returned in enum call, expected %u\n",
7577 num_enum, num_anounced + num_created);
7579 torture_comment(tctx,
7580 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7581 num_disp, num_anounced + num_created);
7584 return true;
7587 static bool test_Connect(struct dcerpc_binding_handle *b,
7588 struct torture_context *tctx,
7589 struct policy_handle *handle);
7591 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7592 struct torture_samr_context *ctx, struct dom_sid *sid)
7594 struct samr_OpenDomain r;
7595 struct policy_handle domain_handle;
7596 struct policy_handle alias_handle;
7597 struct policy_handle user_handle;
7598 struct policy_handle group_handle;
7599 bool ret = true;
7600 struct dcerpc_binding_handle *b = p->binding_handle;
7602 ZERO_STRUCT(alias_handle);
7603 ZERO_STRUCT(user_handle);
7604 ZERO_STRUCT(group_handle);
7605 ZERO_STRUCT(domain_handle);
7607 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7609 r.in.connect_handle = &ctx->handle;
7610 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7611 r.in.sid = sid;
7612 r.out.domain_handle = &domain_handle;
7614 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7615 "OpenDomain failed");
7616 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7618 /* run the domain tests with the main handle closed - this tests
7619 the servers reference counting */
7620 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7622 switch (ctx->choice) {
7623 case TORTURE_SAMR_PASSWORDS:
7624 case TORTURE_SAMR_USER_PRIVILEGES:
7625 if (!torture_setting_bool(tctx, "samba3", false)) {
7626 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7628 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7629 if (!ret) {
7630 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7632 break;
7633 case TORTURE_SAMR_USER_ATTRIBUTES:
7634 if (!torture_setting_bool(tctx, "samba3", false)) {
7635 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7637 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7638 /* This test needs 'complex' users to validate */
7639 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7640 if (!ret) {
7641 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7643 break;
7644 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7645 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7646 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7647 if (!torture_setting_bool(tctx, "samba3", false)) {
7648 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7650 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7651 if (!ret) {
7652 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7654 break;
7655 case TORTURE_SAMR_MANY_ACCOUNTS:
7656 case TORTURE_SAMR_MANY_GROUPS:
7657 case TORTURE_SAMR_MANY_ALIASES:
7658 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7659 if (!ret) {
7660 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7662 break;
7663 case TORTURE_SAMR_OTHER:
7664 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7665 if (!ret) {
7666 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7668 if (!torture_setting_bool(tctx, "samba3", false)) {
7669 ret &= test_QuerySecurity(b, tctx, &domain_handle);
7671 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7672 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7673 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7674 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7675 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7676 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7677 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7678 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7679 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7680 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7681 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7682 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7683 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7685 if (torture_setting_bool(tctx, "samba4", false)) {
7686 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7687 } else {
7688 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7689 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7691 ret &= test_GroupList(b, tctx, sid, &domain_handle);
7692 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7693 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7694 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7695 if (!ret) {
7696 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7698 break;
7701 if (!ndr_policy_handle_empty(&user_handle) &&
7702 !test_DeleteUser(b, tctx, &user_handle)) {
7703 ret = false;
7706 if (!ndr_policy_handle_empty(&alias_handle) &&
7707 !test_DeleteAlias(b, tctx, &alias_handle)) {
7708 ret = false;
7711 if (!ndr_policy_handle_empty(&group_handle) &&
7712 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7713 ret = false;
7716 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7718 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7719 /* reconnect the main handle */
7721 if (!ret) {
7722 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7725 return ret;
7728 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7729 struct torture_samr_context *ctx, const char *domain)
7731 struct samr_LookupDomain r;
7732 struct dom_sid2 *sid = NULL;
7733 struct lsa_String n1;
7734 struct lsa_String n2;
7735 bool ret = true;
7736 struct dcerpc_binding_handle *b = p->binding_handle;
7738 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7740 /* check for correct error codes */
7741 r.in.connect_handle = &ctx->handle;
7742 r.in.domain_name = &n2;
7743 r.out.sid = &sid;
7744 n2.string = NULL;
7746 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7747 "LookupDomain failed");
7748 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7750 init_lsa_String(&n2, "xxNODOMAINxx");
7752 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7753 "LookupDomain failed");
7754 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7756 r.in.connect_handle = &ctx->handle;
7758 init_lsa_String(&n1, domain);
7759 r.in.domain_name = &n1;
7761 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7762 "LookupDomain failed");
7763 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7765 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7766 ret = false;
7769 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7770 ret = false;
7773 return ret;
7777 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7778 struct torture_samr_context *ctx)
7780 struct samr_EnumDomains r;
7781 uint32_t resume_handle = 0;
7782 uint32_t num_entries = 0;
7783 struct samr_SamArray *sam = NULL;
7784 int i;
7785 bool ret = true;
7786 struct dcerpc_binding_handle *b = p->binding_handle;
7788 r.in.connect_handle = &ctx->handle;
7789 r.in.resume_handle = &resume_handle;
7790 r.in.buf_size = (uint32_t)-1;
7791 r.out.resume_handle = &resume_handle;
7792 r.out.num_entries = &num_entries;
7793 r.out.sam = &sam;
7795 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7796 "EnumDomains failed");
7797 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7799 if (!*r.out.sam) {
7800 return false;
7803 for (i=0;i<sam->count;i++) {
7804 if (!test_LookupDomain(p, tctx, ctx,
7805 sam->entries[i].name.string)) {
7806 ret = false;
7810 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7811 "EnumDomains failed");
7812 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7814 return ret;
7818 static bool test_Connect(struct dcerpc_binding_handle *b,
7819 struct torture_context *tctx,
7820 struct policy_handle *handle)
7822 struct samr_Connect r;
7823 struct samr_Connect2 r2;
7824 struct samr_Connect3 r3;
7825 struct samr_Connect4 r4;
7826 struct samr_Connect5 r5;
7827 union samr_ConnectInfo info;
7828 struct policy_handle h;
7829 uint32_t level_out = 0;
7830 bool ret = true, got_handle = false;
7832 torture_comment(tctx, "Testing samr_Connect\n");
7834 r.in.system_name = NULL;
7835 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7836 r.out.connect_handle = &h;
7838 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7839 "Connect failed");
7840 if (!NT_STATUS_IS_OK(r.out.result)) {
7841 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7842 ret = false;
7843 } else {
7844 got_handle = true;
7845 *handle = h;
7848 torture_comment(tctx, "Testing samr_Connect2\n");
7850 r2.in.system_name = NULL;
7851 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7852 r2.out.connect_handle = &h;
7854 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7855 "Connect2 failed");
7856 if (!NT_STATUS_IS_OK(r2.out.result)) {
7857 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7858 ret = false;
7859 } else {
7860 if (got_handle) {
7861 test_samr_handle_Close(b, tctx, handle);
7863 got_handle = true;
7864 *handle = h;
7867 torture_comment(tctx, "Testing samr_Connect3\n");
7869 r3.in.system_name = NULL;
7870 r3.in.unknown = 0;
7871 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7872 r3.out.connect_handle = &h;
7874 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
7875 "Connect3 failed");
7876 if (!NT_STATUS_IS_OK(r3.out.result)) {
7877 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
7878 ret = false;
7879 } else {
7880 if (got_handle) {
7881 test_samr_handle_Close(b, tctx, handle);
7883 got_handle = true;
7884 *handle = h;
7887 torture_comment(tctx, "Testing samr_Connect4\n");
7889 r4.in.system_name = "";
7890 r4.in.client_version = 0;
7891 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7892 r4.out.connect_handle = &h;
7894 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
7895 "Connect4 failed");
7896 if (!NT_STATUS_IS_OK(r4.out.result)) {
7897 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
7898 ret = false;
7899 } else {
7900 if (got_handle) {
7901 test_samr_handle_Close(b, tctx, handle);
7903 got_handle = true;
7904 *handle = h;
7907 torture_comment(tctx, "Testing samr_Connect5\n");
7909 info.info1.client_version = 0;
7910 info.info1.unknown2 = 0;
7912 r5.in.system_name = "";
7913 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7914 r5.in.level_in = 1;
7915 r5.out.level_out = &level_out;
7916 r5.in.info_in = &info;
7917 r5.out.info_out = &info;
7918 r5.out.connect_handle = &h;
7920 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
7921 "Connect5 failed");
7922 if (!NT_STATUS_IS_OK(r5.out.result)) {
7923 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
7924 ret = false;
7925 } else {
7926 if (got_handle) {
7927 test_samr_handle_Close(b, tctx, handle);
7929 got_handle = true;
7930 *handle = h;
7933 return ret;
7937 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
7938 struct torture_context *tctx)
7940 struct samr_ValidatePassword r;
7941 union samr_ValidatePasswordReq req;
7942 union samr_ValidatePasswordRep *repp = NULL;
7943 NTSTATUS status;
7944 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
7945 int i;
7946 struct dcerpc_binding_handle *b = p->binding_handle;
7948 torture_comment(tctx, "Testing samr_ValidatePassword\n");
7950 ZERO_STRUCT(r);
7951 r.in.level = NetValidatePasswordReset;
7952 r.in.req = &req;
7953 r.out.rep = &repp;
7955 ZERO_STRUCT(req);
7956 req.req3.account.string = "non-existent-account-aklsdji";
7958 for (i=0; passwords[i]; i++) {
7959 req.req3.password.string = passwords[i];
7961 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
7962 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
7963 torture_skip(tctx, "ValidatePassword not supported by server\n");
7965 torture_assert_ntstatus_ok(tctx, status,
7966 "samr_ValidatePassword failed");
7967 torture_assert_ntstatus_ok(tctx, r.out.result,
7968 "samr_ValidatePassword failed");
7969 torture_comment(tctx, "Server %s password '%s' with code %i\n",
7970 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
7971 req.req3.password.string, repp->ctr3.status);
7974 return true;
7977 bool torture_rpc_samr(struct torture_context *torture)
7979 NTSTATUS status;
7980 struct dcerpc_pipe *p;
7981 bool ret = true;
7982 struct torture_samr_context *ctx;
7983 struct dcerpc_binding_handle *b;
7985 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7986 if (!NT_STATUS_IS_OK(status)) {
7987 return false;
7989 b = p->binding_handle;
7991 ctx = talloc_zero(torture, struct torture_samr_context);
7993 ctx->choice = TORTURE_SAMR_OTHER;
7995 ret &= test_Connect(b, torture, &ctx->handle);
7997 if (!torture_setting_bool(torture, "samba3", false)) {
7998 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8001 ret &= test_EnumDomains(p, torture, ctx);
8003 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8005 ret &= test_Shutdown(b, torture, &ctx->handle);
8007 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8009 return ret;
8013 bool torture_rpc_samr_users(struct torture_context *torture)
8015 NTSTATUS status;
8016 struct dcerpc_pipe *p;
8017 bool ret = true;
8018 struct torture_samr_context *ctx;
8019 struct dcerpc_binding_handle *b;
8021 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8022 if (!NT_STATUS_IS_OK(status)) {
8023 return false;
8025 b = p->binding_handle;
8027 ctx = talloc_zero(torture, struct torture_samr_context);
8029 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8031 ret &= test_Connect(b, torture, &ctx->handle);
8033 if (!torture_setting_bool(torture, "samba3", false)) {
8034 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8037 ret &= test_EnumDomains(p, torture, ctx);
8039 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8041 ret &= test_Shutdown(b, torture, &ctx->handle);
8043 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8045 return ret;
8049 bool torture_rpc_samr_passwords(struct torture_context *torture)
8051 NTSTATUS status;
8052 struct dcerpc_pipe *p;
8053 bool ret = true;
8054 struct torture_samr_context *ctx;
8055 struct dcerpc_binding_handle *b;
8057 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8058 if (!NT_STATUS_IS_OK(status)) {
8059 return false;
8061 b = p->binding_handle;
8063 ctx = talloc_zero(torture, struct torture_samr_context);
8065 ctx->choice = TORTURE_SAMR_PASSWORDS;
8067 ret &= test_Connect(b, torture, &ctx->handle);
8069 ret &= test_EnumDomains(p, torture, ctx);
8071 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8073 ret &= test_samr_ValidatePassword(p, torture);
8075 return ret;
8078 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8079 struct dcerpc_pipe *p2,
8080 struct cli_credentials *machine_credentials)
8082 NTSTATUS status;
8083 struct dcerpc_pipe *p;
8084 bool ret = true;
8085 struct torture_samr_context *ctx;
8086 struct dcerpc_binding_handle *b;
8088 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8089 if (!NT_STATUS_IS_OK(status)) {
8090 return false;
8092 b = p->binding_handle;
8094 ctx = talloc_zero(torture, struct torture_samr_context);
8096 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8097 ctx->machine_credentials = machine_credentials;
8099 ret &= test_Connect(b, torture, &ctx->handle);
8101 ret &= test_EnumDomains(p, torture, ctx);
8103 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8105 return ret;
8108 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8110 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8111 struct torture_rpc_tcase *tcase;
8113 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8114 &ndr_table_samr,
8115 TEST_ACCOUNT_NAME_PWD);
8117 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8118 torture_rpc_samr_pwdlastset);
8120 return suite;
8123 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8124 struct dcerpc_pipe *p2,
8125 struct cli_credentials *machine_credentials)
8127 NTSTATUS status;
8128 struct dcerpc_pipe *p;
8129 bool ret = true;
8130 struct torture_samr_context *ctx;
8131 struct dcerpc_binding_handle *b;
8133 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8134 if (!NT_STATUS_IS_OK(status)) {
8135 return false;
8137 b = p->binding_handle;
8139 ctx = talloc_zero(torture, struct torture_samr_context);
8141 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8142 ctx->machine_credentials = machine_credentials;
8144 ret &= test_Connect(b, torture, &ctx->handle);
8146 ret &= test_EnumDomains(p, torture, ctx);
8148 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8150 return ret;
8153 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8155 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8156 struct torture_rpc_tcase *tcase;
8158 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8159 &ndr_table_samr,
8160 TEST_ACCOUNT_NAME_PWD);
8162 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8163 torture_rpc_samr_users_privileges_delete_user);
8165 return suite;
8168 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8169 struct dcerpc_pipe *p2,
8170 void *data)
8172 NTSTATUS status;
8173 struct dcerpc_pipe *p;
8174 bool ret = true;
8175 struct torture_samr_context *ctx =
8176 talloc_get_type_abort(data, struct torture_samr_context);
8177 struct dcerpc_binding_handle *b;
8179 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8180 if (!NT_STATUS_IS_OK(status)) {
8181 return false;
8183 b = p->binding_handle;
8185 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8186 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8187 ctx->num_objects_large_dc);
8189 ret &= test_Connect(b, torture, &ctx->handle);
8191 ret &= test_EnumDomains(p, torture, ctx);
8193 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8195 return ret;
8198 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8199 struct dcerpc_pipe *p2,
8200 void *data)
8202 NTSTATUS status;
8203 struct dcerpc_pipe *p;
8204 bool ret = true;
8205 struct torture_samr_context *ctx =
8206 talloc_get_type_abort(data, struct torture_samr_context);
8207 struct dcerpc_binding_handle *b;
8209 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8210 if (!NT_STATUS_IS_OK(status)) {
8211 return false;
8213 b = p->binding_handle;
8215 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8216 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8217 ctx->num_objects_large_dc);
8219 ret &= test_Connect(b, torture, &ctx->handle);
8221 ret &= test_EnumDomains(p, torture, ctx);
8223 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8225 return ret;
8228 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8229 struct dcerpc_pipe *p2,
8230 void *data)
8232 NTSTATUS status;
8233 struct dcerpc_pipe *p;
8234 bool ret = true;
8235 struct torture_samr_context *ctx =
8236 talloc_get_type_abort(data, struct torture_samr_context);
8237 struct dcerpc_binding_handle *b;
8239 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8240 if (!NT_STATUS_IS_OK(status)) {
8241 return false;
8243 b = p->binding_handle;
8245 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8246 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8247 ctx->num_objects_large_dc);
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_large_dc(TALLOC_CTX *mem_ctx)
8260 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8261 struct torture_rpc_tcase *tcase;
8262 struct torture_samr_context *ctx;
8264 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8266 ctx = talloc_zero(suite, struct torture_samr_context);
8267 ctx->num_objects_large_dc = 150;
8269 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8270 torture_rpc_samr_many_aliases, ctx);
8271 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8272 torture_rpc_samr_many_groups, ctx);
8273 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8274 torture_rpc_samr_many_accounts, ctx);
8276 return suite;
8279 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8280 struct dcerpc_pipe *p2,
8281 struct cli_credentials *machine_credentials)
8283 NTSTATUS status;
8284 struct dcerpc_pipe *p;
8285 bool ret = true;
8286 struct torture_samr_context *ctx;
8287 struct dcerpc_binding_handle *b;
8289 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8290 if (!NT_STATUS_IS_OK(status)) {
8291 return false;
8293 b = p->binding_handle;
8295 ctx = talloc_zero(torture, struct torture_samr_context);
8297 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8298 ctx->machine_credentials = machine_credentials;
8300 ret &= test_Connect(b, torture, &ctx->handle);
8302 ret &= test_EnumDomains(p, torture, ctx);
8304 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8306 return ret;
8309 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8311 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8312 struct torture_rpc_tcase *tcase;
8314 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8315 &ndr_table_samr,
8316 TEST_ACCOUNT_NAME_PWD);
8318 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8319 torture_rpc_samr_badpwdcount);
8321 return suite;
8324 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8325 struct dcerpc_pipe *p2,
8326 struct cli_credentials *machine_credentials)
8328 NTSTATUS status;
8329 struct dcerpc_pipe *p;
8330 bool ret = true;
8331 struct torture_samr_context *ctx;
8332 struct dcerpc_binding_handle *b;
8334 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8335 if (!NT_STATUS_IS_OK(status)) {
8336 return false;
8338 b = p->binding_handle;
8340 ctx = talloc_zero(torture, struct torture_samr_context);
8342 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8343 ctx->machine_credentials = machine_credentials;
8345 ret &= test_Connect(b, torture, &ctx->handle);
8347 ret &= test_EnumDomains(p, torture, ctx);
8349 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8351 return ret;
8354 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8356 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8357 struct torture_rpc_tcase *tcase;
8359 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8360 &ndr_table_samr,
8361 TEST_ACCOUNT_NAME_PWD);
8363 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8364 torture_rpc_samr_lockout);
8366 return suite;