CVE-2013-4496:samr: Remove ChangePasswordUser
[Samba.git] / source4 / torture / rpc / samr.c
blobca100aa5b3907f17f95cf1806a0a1e14498af080
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for samr rpc operations
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7 Copyright (C) Jelmer Vernooij 2005-2007
8 Copyright (C) Guenther Deschner 2008-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include <tevent.h>
27 #include "system/time.h"
28 #include "system/network.h"
29 #include "librpc/gen_ndr/lsa.h"
30 #include "librpc/gen_ndr/ndr_netlogon.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
33 #include "librpc/gen_ndr/ndr_lsa_c.h"
34 #include "../lib/crypto/crypto.h"
35 #include "libcli/auth/libcli_auth.h"
36 #include "libcli/security/security.h"
37 #include "torture/rpc/torture_rpc.h"
38 #include "param/param.h"
39 #include "auth/gensec/gensec.h"
40 #include "auth/gensec/schannel.h"
41 #include "auth/gensec/gensec_proto.h"
42 #include "../libcli/auth/schannel.h"
44 #define TEST_ACCOUNT_NAME "samrtorturetest"
45 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
46 #define TEST_ALIASNAME "samrtorturetestalias"
47 #define TEST_GROUPNAME "samrtorturetestgroup"
48 #define TEST_MACHINENAME "samrtestmach$"
49 #define TEST_DOMAINNAME "samrtestdom$"
51 enum torture_samr_choice {
52 TORTURE_SAMR_PASSWORDS,
53 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
54 TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
55 TORTURE_SAMR_PASSWORDS_LOCKOUT,
56 TORTURE_SAMR_USER_ATTRIBUTES,
57 TORTURE_SAMR_USER_PRIVILEGES,
58 TORTURE_SAMR_OTHER,
59 TORTURE_SAMR_MANY_ACCOUNTS,
60 TORTURE_SAMR_MANY_GROUPS,
61 TORTURE_SAMR_MANY_ALIASES
64 struct torture_samr_context {
65 struct policy_handle handle;
66 struct cli_credentials *machine_credentials;
67 enum torture_samr_choice choice;
68 uint32_t num_objects_large_dc;
71 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
72 struct torture_context *tctx,
73 struct policy_handle *handle);
75 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
76 struct torture_context *tctx,
77 struct policy_handle *handle);
79 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
80 struct torture_context *tctx,
81 struct policy_handle *handle);
83 static bool test_ChangePassword(struct dcerpc_pipe *p,
84 struct torture_context *tctx,
85 const char *acct_name,
86 struct policy_handle *domain_handle, char **password);
88 static void init_lsa_String(struct lsa_String *string, const char *s)
90 string->string = s;
93 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
95 string->string = s;
98 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
100 string->length = length;
101 string->size = length;
102 string->array = (uint16_t *)discard_const(s);
105 bool test_samr_handle_Close(struct dcerpc_binding_handle *b,
106 struct torture_context *tctx,
107 struct policy_handle *handle)
109 struct samr_Close r;
111 r.in.handle = handle;
112 r.out.handle = handle;
114 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Close_r(b, tctx, &r),
115 "Close failed");
116 torture_assert_ntstatus_ok(tctx, r.out.result, "Close failed");
118 return true;
121 static bool test_Shutdown(struct dcerpc_binding_handle *b,
122 struct torture_context *tctx,
123 struct policy_handle *handle)
125 struct samr_Shutdown r;
127 if (!torture_setting_bool(tctx, "dangerous", false)) {
128 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
129 return true;
132 r.in.connect_handle = handle;
134 torture_comment(tctx, "Testing samr_Shutdown\n");
136 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Shutdown_r(b, tctx, &r),
137 "Shutdown failed");
138 torture_assert_ntstatus_ok(tctx, r.out.result, "Shutdown failed");
140 return true;
143 static bool test_SetDsrmPassword(struct dcerpc_binding_handle *b,
144 struct torture_context *tctx,
145 struct policy_handle *handle)
147 struct samr_SetDsrmPassword r;
148 struct lsa_String string;
149 struct samr_Password hash;
151 if (!torture_setting_bool(tctx, "dangerous", false)) {
152 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
155 E_md4hash("TeSTDSRM123", hash.hash);
157 init_lsa_String(&string, "Administrator");
159 r.in.name = &string;
160 r.in.unknown = 0;
161 r.in.hash = &hash;
163 torture_comment(tctx, "Testing samr_SetDsrmPassword\n");
165 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDsrmPassword_r(b, tctx, &r),
166 "SetDsrmPassword failed");
167 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_SUPPORTED, "SetDsrmPassword failed");
169 return true;
173 static bool test_QuerySecurity(struct dcerpc_binding_handle *b,
174 struct torture_context *tctx,
175 struct policy_handle *handle)
177 struct samr_QuerySecurity r;
178 struct samr_SetSecurity s;
179 struct sec_desc_buf *sdbuf = NULL;
181 r.in.handle = handle;
182 r.in.sec_info = 7;
183 r.out.sdbuf = &sdbuf;
185 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
186 "QuerySecurity failed");
187 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
189 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
191 s.in.handle = handle;
192 s.in.sec_info = 7;
193 s.in.sdbuf = sdbuf;
195 if (torture_setting_bool(tctx, "samba4", false)) {
196 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
199 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetSecurity_r(b, tctx, &s),
200 "SetSecurity failed");
201 torture_assert_ntstatus_ok(tctx, r.out.result, "SetSecurity failed");
203 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
204 "QuerySecurity failed");
205 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
207 return true;
211 static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_context *tctx,
212 struct policy_handle *handle, uint32_t base_acct_flags,
213 const char *base_account_name)
215 struct samr_SetUserInfo s;
216 struct samr_SetUserInfo2 s2;
217 struct samr_QueryUserInfo q;
218 struct samr_QueryUserInfo q0;
219 union samr_UserInfo u;
220 union samr_UserInfo *info;
221 bool ret = true;
222 const char *test_account_name;
224 uint32_t user_extra_flags = 0;
226 if (!torture_setting_bool(tctx, "samba3", false)) {
227 if (base_acct_flags == ACB_NORMAL) {
228 /* When created, accounts are expired by default */
229 user_extra_flags = ACB_PW_EXPIRED;
233 s.in.user_handle = handle;
234 s.in.info = &u;
236 s2.in.user_handle = handle;
237 s2.in.info = &u;
239 q.in.user_handle = handle;
240 q.out.info = &info;
241 q0 = q;
243 #define TESTCALL(call, r) \
244 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ ##call## _r(b, tctx, &r),\
245 #call " failed"); \
246 if (!NT_STATUS_IS_OK(r.out.result)) { \
247 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
248 r.in.level, nt_errstr(r.out.result), __location__); \
249 ret = false; \
250 break; \
253 #define STRING_EQUAL(s1, s2, field) \
254 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
255 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
256 #field, s2, __location__); \
257 ret = false; \
258 break; \
261 #define MEM_EQUAL(s1, s2, length, field) \
262 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
263 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
264 #field, (const char *)s2, __location__); \
265 ret = false; \
266 break; \
269 #define INT_EQUAL(i1, i2, field) \
270 if (i1 != i2) { \
271 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
272 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
273 ret = false; \
274 break; \
277 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
278 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
279 q.in.level = lvl1; \
280 TESTCALL(QueryUserInfo, q) \
281 s.in.level = lvl1; \
282 s2.in.level = lvl1; \
283 u = *info; \
284 if (lvl1 == 21) { \
285 ZERO_STRUCT(u.info21); \
286 u.info21.fields_present = fpval; \
288 init_lsa_String(&u.info ## lvl1.field1, value); \
289 TESTCALL(SetUserInfo, s) \
290 TESTCALL(SetUserInfo2, s2) \
291 init_lsa_String(&u.info ## lvl1.field1, ""); \
292 TESTCALL(QueryUserInfo, q); \
293 u = *info; \
294 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
295 q.in.level = lvl2; \
296 TESTCALL(QueryUserInfo, q) \
297 u = *info; \
298 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
299 } while (0)
301 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
302 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
303 q.in.level = lvl1; \
304 TESTCALL(QueryUserInfo, q) \
305 s.in.level = lvl1; \
306 s2.in.level = lvl1; \
307 u = *info; \
308 if (lvl1 == 21) { \
309 ZERO_STRUCT(u.info21); \
310 u.info21.fields_present = fpval; \
312 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
313 TESTCALL(SetUserInfo, s) \
314 TESTCALL(SetUserInfo2, s2) \
315 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
316 TESTCALL(QueryUserInfo, q); \
317 u = *info; \
318 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
319 q.in.level = lvl2; \
320 TESTCALL(QueryUserInfo, q) \
321 u = *info; \
322 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
323 } while (0)
325 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
326 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
327 q.in.level = lvl1; \
328 TESTCALL(QueryUserInfo, q) \
329 s.in.level = lvl1; \
330 s2.in.level = lvl1; \
331 u = *info; \
332 if (lvl1 == 21) { \
333 uint8_t *bits = u.info21.logon_hours.bits; \
334 ZERO_STRUCT(u.info21); \
335 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
336 u.info21.logon_hours.units_per_week = 168; \
337 u.info21.logon_hours.bits = bits; \
339 u.info21.fields_present = fpval; \
341 u.info ## lvl1.field1 = value; \
342 TESTCALL(SetUserInfo, s) \
343 TESTCALL(SetUserInfo2, s2) \
344 u.info ## lvl1.field1 = 0; \
345 TESTCALL(QueryUserInfo, q); \
346 u = *info; \
347 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
348 q.in.level = lvl2; \
349 TESTCALL(QueryUserInfo, q) \
350 u = *info; \
351 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
352 } while (0)
354 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
355 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
356 } while (0)
358 q0.in.level = 12;
359 do { TESTCALL(QueryUserInfo, q0) } while (0);
361 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
362 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
363 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
364 SAMR_FIELD_COMMENT);
366 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
367 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
368 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
369 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
370 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
371 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
372 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
373 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
374 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
375 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
376 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
377 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
378 test_account_name = base_account_name;
379 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
380 SAMR_FIELD_ACCOUNT_NAME);
382 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
383 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
384 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
385 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
386 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
387 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
388 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
389 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
390 SAMR_FIELD_FULL_NAME);
392 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
393 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
394 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
395 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
396 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
397 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
398 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
399 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
400 SAMR_FIELD_FULL_NAME);
402 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
403 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
404 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
405 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
406 SAMR_FIELD_LOGON_SCRIPT);
408 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
409 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
410 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
411 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
412 SAMR_FIELD_PROFILE_PATH);
414 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
415 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
416 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
417 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
418 SAMR_FIELD_HOME_DIRECTORY);
419 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
420 SAMR_FIELD_HOME_DIRECTORY);
422 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
423 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
424 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
425 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
426 SAMR_FIELD_HOME_DRIVE);
427 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
428 SAMR_FIELD_HOME_DRIVE);
430 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
431 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
432 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
433 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
434 SAMR_FIELD_DESCRIPTION);
436 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
437 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
438 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
439 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
440 SAMR_FIELD_WORKSTATIONS);
441 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
442 SAMR_FIELD_WORKSTATIONS);
443 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
444 SAMR_FIELD_WORKSTATIONS);
445 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
446 SAMR_FIELD_WORKSTATIONS);
448 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
449 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
450 SAMR_FIELD_PARAMETERS);
451 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
452 SAMR_FIELD_PARAMETERS);
453 /* also empty user parameters are allowed */
454 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
455 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
456 SAMR_FIELD_PARAMETERS);
457 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
458 SAMR_FIELD_PARAMETERS);
460 /* Samba 3 cannot store country_code and code_page atm. - gd */
461 if (!torture_setting_bool(tctx, "samba3", false)) {
462 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
463 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
464 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
465 SAMR_FIELD_COUNTRY_CODE);
466 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
467 SAMR_FIELD_COUNTRY_CODE);
469 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
470 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
471 SAMR_FIELD_CODE_PAGE);
472 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
473 SAMR_FIELD_CODE_PAGE);
476 if (!torture_setting_bool(tctx, "samba3", false)) {
477 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
478 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
479 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
480 SAMR_FIELD_ACCT_EXPIRY);
481 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
482 SAMR_FIELD_ACCT_EXPIRY);
483 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
484 SAMR_FIELD_ACCT_EXPIRY);
485 } else {
486 /* Samba 3 can only store seconds / time_t in passdb - gd */
487 NTTIME nt;
488 unix_to_nt_time(&nt, time(NULL) + __LINE__);
489 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
490 unix_to_nt_time(&nt, time(NULL) + __LINE__);
491 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
492 unix_to_nt_time(&nt, time(NULL) + __LINE__);
493 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
494 unix_to_nt_time(&nt, time(NULL) + __LINE__);
495 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
496 unix_to_nt_time(&nt, time(NULL) + __LINE__);
497 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
500 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
501 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
502 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
503 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
504 SAMR_FIELD_LOGON_HOURS);
506 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
507 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
508 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
510 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
511 (base_acct_flags | ACB_DISABLED),
512 (base_acct_flags | ACB_DISABLED | user_extra_flags),
515 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
516 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
517 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
518 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
520 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
521 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
522 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
526 /* The 'autolock' flag doesn't stick - check this */
527 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
528 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
529 (base_acct_flags | ACB_DISABLED | user_extra_flags),
531 #if 0
532 /* Removing the 'disabled' flag doesn't stick - check this */
533 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
534 (base_acct_flags),
535 (base_acct_flags | ACB_DISABLED | user_extra_flags),
537 #endif
539 /* Samba3 cannot store these atm */
540 if (!torture_setting_bool(tctx, "samba3", false)) {
541 /* The 'store plaintext' flag does stick */
542 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
543 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
544 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
546 /* The 'use DES' flag does stick */
547 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
548 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
549 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
551 /* The 'don't require kerberos pre-authentication flag does stick */
552 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
553 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
554 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
556 /* The 'no kerberos PAC required' flag sticks */
557 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
558 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
559 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
562 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
563 (base_acct_flags | ACB_DISABLED),
564 (base_acct_flags | ACB_DISABLED | user_extra_flags),
565 SAMR_FIELD_ACCT_FLAGS);
567 #if 0
568 /* these fail with win2003 - it appears you can't set the primary gid?
569 the set succeeds, but the gid isn't changed. Very weird! */
570 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
571 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
572 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
573 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
574 #endif
576 return ret;
580 generate a random password for password change tests
582 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
584 size_t len = MAX(8, min_len);
585 char *s = generate_random_password(mem_ctx, len, len+6);
586 return s;
589 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
591 char *s = samr_rand_pass_silent(mem_ctx, min_len);
592 printf("Generated password '%s'\n", s);
593 return s;
598 generate a random password for password change tests
600 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
602 int i;
603 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
604 generate_random_buffer(password.data, password.length);
606 for (i=0; i < len; i++) {
607 if (((uint16_t *)password.data)[i] == 0) {
608 ((uint16_t *)password.data)[i] = 1;
612 return password;
616 generate a random password for password change tests (fixed length)
618 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
620 char *s = generate_random_password(mem_ctx, len, len);
621 printf("Generated password '%s'\n", s);
622 return s;
625 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
626 struct policy_handle *handle, char **password)
628 NTSTATUS status;
629 struct samr_SetUserInfo s;
630 union samr_UserInfo u;
631 bool ret = true;
632 DATA_BLOB session_key;
633 char *newpass;
634 struct dcerpc_binding_handle *b = p->binding_handle;
635 struct samr_GetUserPwInfo pwp;
636 struct samr_PwInfo info;
637 int policy_min_pw_len = 0;
638 pwp.in.user_handle = handle;
639 pwp.out.info = &info;
641 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
642 "GetUserPwInfo failed");
643 if (NT_STATUS_IS_OK(pwp.out.result)) {
644 policy_min_pw_len = pwp.out.info->min_password_length;
646 newpass = samr_rand_pass(tctx, policy_min_pw_len);
648 s.in.user_handle = handle;
649 s.in.info = &u;
650 s.in.level = 24;
652 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
653 u.info24.password_expired = 0;
655 status = dcerpc_fetch_session_key(p, &session_key);
656 if (!NT_STATUS_IS_OK(status)) {
657 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
658 s.in.level, nt_errstr(status));
659 return false;
662 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
664 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
666 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
667 "SetUserInfo failed");
668 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
669 __location__, __FUNCTION__,
670 newpass, nt_errstr(s.out.result));
671 if (!NT_STATUS_IS_OK(s.out.result)) {
672 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
673 s.in.level, nt_errstr(s.out.result));
674 ret = false;
675 } else {
676 *password = newpass;
679 return ret;
683 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
684 struct policy_handle *handle, uint32_t fields_present,
685 char **password)
687 NTSTATUS status;
688 struct samr_SetUserInfo s;
689 union samr_UserInfo u;
690 bool ret = true;
691 DATA_BLOB session_key;
692 struct dcerpc_binding_handle *b = p->binding_handle;
693 char *newpass;
694 struct samr_GetUserPwInfo pwp;
695 struct samr_PwInfo info;
696 int policy_min_pw_len = 0;
697 pwp.in.user_handle = handle;
698 pwp.out.info = &info;
700 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
701 "GetUserPwInfo failed");
702 if (NT_STATUS_IS_OK(pwp.out.result)) {
703 policy_min_pw_len = pwp.out.info->min_password_length;
705 newpass = samr_rand_pass(tctx, policy_min_pw_len);
707 s.in.user_handle = handle;
708 s.in.info = &u;
709 s.in.level = 23;
711 ZERO_STRUCT(u);
713 u.info23.info.fields_present = fields_present;
715 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
717 status = dcerpc_fetch_session_key(p, &session_key);
718 if (!NT_STATUS_IS_OK(status)) {
719 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
720 s.in.level, nt_errstr(status));
721 return false;
724 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
726 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
728 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
729 "SetUserInfo failed");
730 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
731 __location__, __FUNCTION__,
732 newpass, nt_errstr(s.out.result));
733 if (!NT_STATUS_IS_OK(s.out.result)) {
734 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
735 s.in.level, nt_errstr(s.out.result));
736 ret = false;
737 } else {
738 *password = newpass;
741 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
743 status = dcerpc_fetch_session_key(p, &session_key);
744 if (!NT_STATUS_IS_OK(status)) {
745 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
746 s.in.level, nt_errstr(status));
747 return false;
750 /* This should break the key nicely */
751 session_key.length--;
752 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
754 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
756 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
757 "SetUserInfo failed");
758 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
759 __location__, __FUNCTION__,
760 newpass, nt_errstr(s.out.result));
761 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
762 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
763 s.in.level, nt_errstr(s.out.result));
764 ret = false;
767 return ret;
771 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
772 struct policy_handle *handle, bool makeshort,
773 char **password)
775 NTSTATUS status;
776 struct samr_SetUserInfo s;
777 union samr_UserInfo u;
778 bool ret = true;
779 DATA_BLOB session_key;
780 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
781 uint8_t confounder[16];
782 char *newpass;
783 struct dcerpc_binding_handle *b = p->binding_handle;
784 struct MD5Context ctx;
785 struct samr_GetUserPwInfo pwp;
786 struct samr_PwInfo info;
787 int policy_min_pw_len = 0;
788 pwp.in.user_handle = handle;
789 pwp.out.info = &info;
791 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
792 "GetUserPwInfo failed");
793 if (NT_STATUS_IS_OK(pwp.out.result)) {
794 policy_min_pw_len = pwp.out.info->min_password_length;
796 if (makeshort && policy_min_pw_len) {
797 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
798 } else {
799 newpass = samr_rand_pass(tctx, policy_min_pw_len);
802 s.in.user_handle = handle;
803 s.in.info = &u;
804 s.in.level = 26;
806 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
807 u.info26.password_expired = 0;
809 status = dcerpc_fetch_session_key(p, &session_key);
810 if (!NT_STATUS_IS_OK(status)) {
811 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
812 s.in.level, nt_errstr(status));
813 return false;
816 generate_random_buffer((uint8_t *)confounder, 16);
818 MD5Init(&ctx);
819 MD5Update(&ctx, confounder, 16);
820 MD5Update(&ctx, session_key.data, session_key.length);
821 MD5Final(confounded_session_key.data, &ctx);
823 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
824 memcpy(&u.info26.password.data[516], confounder, 16);
826 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
828 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
829 "SetUserInfo failed");
830 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
831 __location__, __FUNCTION__,
832 newpass, nt_errstr(s.out.result));
833 if (!NT_STATUS_IS_OK(s.out.result)) {
834 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
835 s.in.level, nt_errstr(s.out.result));
836 ret = false;
837 } else {
838 *password = newpass;
841 /* This should break the key nicely */
842 confounded_session_key.data[0]++;
844 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
845 memcpy(&u.info26.password.data[516], confounder, 16);
847 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
849 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
850 "SetUserInfo failed");
851 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
852 __location__, __FUNCTION__,
853 newpass, nt_errstr(s.out.result));
854 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
855 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
856 s.in.level, nt_errstr(s.out.result));
857 ret = false;
858 } else {
859 *password = newpass;
862 return ret;
865 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
866 struct policy_handle *handle, uint32_t fields_present,
867 char **password)
869 NTSTATUS status;
870 struct samr_SetUserInfo s;
871 union samr_UserInfo u;
872 bool ret = true;
873 DATA_BLOB session_key;
874 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
875 struct MD5Context ctx;
876 uint8_t confounder[16];
877 char *newpass;
878 struct dcerpc_binding_handle *b = p->binding_handle;
879 struct samr_GetUserPwInfo pwp;
880 struct samr_PwInfo info;
881 int policy_min_pw_len = 0;
882 pwp.in.user_handle = handle;
883 pwp.out.info = &info;
885 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
886 "GetUserPwInfo failed");
887 if (NT_STATUS_IS_OK(pwp.out.result)) {
888 policy_min_pw_len = pwp.out.info->min_password_length;
890 newpass = samr_rand_pass(tctx, policy_min_pw_len);
892 s.in.user_handle = handle;
893 s.in.info = &u;
894 s.in.level = 25;
896 ZERO_STRUCT(u);
898 u.info25.info.fields_present = fields_present;
900 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
902 status = dcerpc_fetch_session_key(p, &session_key);
903 if (!NT_STATUS_IS_OK(status)) {
904 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
905 s.in.level, nt_errstr(status));
906 return false;
909 generate_random_buffer((uint8_t *)confounder, 16);
911 MD5Init(&ctx);
912 MD5Update(&ctx, confounder, 16);
913 MD5Update(&ctx, session_key.data, session_key.length);
914 MD5Final(confounded_session_key.data, &ctx);
916 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
917 memcpy(&u.info25.password.data[516], confounder, 16);
919 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
921 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
922 "SetUserInfo failed");
923 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
924 __location__, __FUNCTION__,
925 newpass, nt_errstr(s.out.result));
926 if (!NT_STATUS_IS_OK(s.out.result)) {
927 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
928 s.in.level, nt_errstr(s.out.result));
929 ret = false;
930 } else {
931 *password = newpass;
934 /* This should break the key nicely */
935 confounded_session_key.data[0]++;
937 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
938 memcpy(&u.info25.password.data[516], confounder, 16);
940 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
942 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
943 "SetUserInfo failed");
944 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
945 __location__, __FUNCTION__,
946 newpass, nt_errstr(s.out.result));
947 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
948 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
949 s.in.level, nt_errstr(s.out.result));
950 ret = false;
953 return ret;
956 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
957 struct policy_handle *handle, char **password)
959 NTSTATUS status;
960 struct samr_SetUserInfo s;
961 union samr_UserInfo u;
962 bool ret = true;
963 DATA_BLOB session_key;
964 char *newpass;
965 struct dcerpc_binding_handle *b = p->binding_handle;
966 struct samr_GetUserPwInfo pwp;
967 struct samr_PwInfo info;
968 int policy_min_pw_len = 0;
969 uint8_t lm_hash[16], nt_hash[16];
971 pwp.in.user_handle = handle;
972 pwp.out.info = &info;
974 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
975 "GetUserPwInfo failed");
976 if (NT_STATUS_IS_OK(pwp.out.result)) {
977 policy_min_pw_len = pwp.out.info->min_password_length;
979 newpass = samr_rand_pass(tctx, policy_min_pw_len);
981 s.in.user_handle = handle;
982 s.in.info = &u;
983 s.in.level = 18;
985 ZERO_STRUCT(u);
987 u.info18.nt_pwd_active = true;
988 u.info18.lm_pwd_active = true;
990 E_md4hash(newpass, nt_hash);
991 E_deshash(newpass, lm_hash);
993 status = dcerpc_fetch_session_key(p, &session_key);
994 if (!NT_STATUS_IS_OK(status)) {
995 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
996 s.in.level, nt_errstr(status));
997 return false;
1001 DATA_BLOB in,out;
1002 in = data_blob_const(nt_hash, 16);
1003 out = data_blob_talloc_zero(tctx, 16);
1004 sess_crypt_blob(&out, &in, &session_key, true);
1005 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1008 DATA_BLOB in,out;
1009 in = data_blob_const(lm_hash, 16);
1010 out = data_blob_talloc_zero(tctx, 16);
1011 sess_crypt_blob(&out, &in, &session_key, true);
1012 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1015 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
1017 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1018 "SetUserInfo failed");
1019 if (!NT_STATUS_IS_OK(s.out.result)) {
1020 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1021 s.in.level, nt_errstr(s.out.result));
1022 ret = false;
1023 } else {
1024 *password = newpass;
1027 return ret;
1030 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1031 struct policy_handle *handle, uint32_t fields_present,
1032 char **password)
1034 NTSTATUS status;
1035 struct samr_SetUserInfo s;
1036 union samr_UserInfo u;
1037 bool ret = true;
1038 DATA_BLOB session_key;
1039 char *newpass;
1040 struct dcerpc_binding_handle *b = p->binding_handle;
1041 struct samr_GetUserPwInfo pwp;
1042 struct samr_PwInfo info;
1043 int policy_min_pw_len = 0;
1044 uint8_t lm_hash[16], nt_hash[16];
1046 pwp.in.user_handle = handle;
1047 pwp.out.info = &info;
1049 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1050 "GetUserPwInfo failed");
1051 if (NT_STATUS_IS_OK(pwp.out.result)) {
1052 policy_min_pw_len = pwp.out.info->min_password_length;
1054 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1056 s.in.user_handle = handle;
1057 s.in.info = &u;
1058 s.in.level = 21;
1060 E_md4hash(newpass, nt_hash);
1061 E_deshash(newpass, lm_hash);
1063 ZERO_STRUCT(u);
1065 u.info21.fields_present = fields_present;
1067 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1068 u.info21.lm_owf_password.length = 16;
1069 u.info21.lm_owf_password.size = 16;
1070 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1071 u.info21.lm_password_set = true;
1074 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1075 u.info21.nt_owf_password.length = 16;
1076 u.info21.nt_owf_password.size = 16;
1077 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1078 u.info21.nt_password_set = true;
1081 status = dcerpc_fetch_session_key(p, &session_key);
1082 if (!NT_STATUS_IS_OK(status)) {
1083 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1084 s.in.level, nt_errstr(status));
1085 return false;
1088 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1089 DATA_BLOB in,out;
1090 in = data_blob_const(u.info21.lm_owf_password.array,
1091 u.info21.lm_owf_password.length);
1092 out = data_blob_talloc_zero(tctx, 16);
1093 sess_crypt_blob(&out, &in, &session_key, true);
1094 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1097 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1098 DATA_BLOB in,out;
1099 in = data_blob_const(u.info21.nt_owf_password.array,
1100 u.info21.nt_owf_password.length);
1101 out = data_blob_talloc_zero(tctx, 16);
1102 sess_crypt_blob(&out, &in, &session_key, true);
1103 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1106 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1108 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1109 "SetUserInfo failed");
1110 if (!NT_STATUS_IS_OK(s.out.result)) {
1111 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1112 s.in.level, nt_errstr(s.out.result));
1113 ret = false;
1114 } else {
1115 *password = newpass;
1118 /* try invalid length */
1119 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1121 u.info21.nt_owf_password.length++;
1123 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1124 "SetUserInfo failed");
1125 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1126 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1127 s.in.level, nt_errstr(s.out.result));
1128 ret = false;
1132 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1134 u.info21.lm_owf_password.length++;
1136 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1137 "SetUserInfo failed");
1138 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1139 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1140 s.in.level, nt_errstr(s.out.result));
1141 ret = false;
1145 return ret;
1148 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1149 struct torture_context *tctx,
1150 struct policy_handle *handle,
1151 uint16_t level,
1152 uint32_t fields_present,
1153 char **password, uint8_t password_expired,
1154 bool use_setinfo2,
1155 bool *matched_expected_error)
1157 NTSTATUS status;
1158 NTSTATUS expected_error = NT_STATUS_OK;
1159 struct samr_SetUserInfo s;
1160 struct samr_SetUserInfo2 s2;
1161 union samr_UserInfo u;
1162 bool ret = true;
1163 DATA_BLOB session_key;
1164 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1165 struct MD5Context ctx;
1166 uint8_t confounder[16];
1167 char *newpass;
1168 struct dcerpc_binding_handle *b = p->binding_handle;
1169 struct samr_GetUserPwInfo pwp;
1170 struct samr_PwInfo info;
1171 int policy_min_pw_len = 0;
1172 const char *comment = NULL;
1173 uint8_t lm_hash[16], nt_hash[16];
1175 pwp.in.user_handle = handle;
1176 pwp.out.info = &info;
1178 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1179 "GetUserPwInfo failed");
1180 if (NT_STATUS_IS_OK(pwp.out.result)) {
1181 policy_min_pw_len = pwp.out.info->min_password_length;
1183 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1185 if (use_setinfo2) {
1186 s2.in.user_handle = handle;
1187 s2.in.info = &u;
1188 s2.in.level = level;
1189 } else {
1190 s.in.user_handle = handle;
1191 s.in.info = &u;
1192 s.in.level = level;
1195 if (fields_present & SAMR_FIELD_COMMENT) {
1196 comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
1199 ZERO_STRUCT(u);
1201 switch (level) {
1202 case 18:
1203 E_md4hash(newpass, nt_hash);
1204 E_deshash(newpass, lm_hash);
1206 u.info18.nt_pwd_active = true;
1207 u.info18.lm_pwd_active = true;
1208 u.info18.password_expired = password_expired;
1210 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1211 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1213 break;
1214 case 21:
1215 E_md4hash(newpass, nt_hash);
1216 E_deshash(newpass, lm_hash);
1218 u.info21.fields_present = fields_present;
1219 u.info21.password_expired = password_expired;
1220 u.info21.comment.string = comment;
1222 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1223 u.info21.lm_owf_password.length = 16;
1224 u.info21.lm_owf_password.size = 16;
1225 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1226 u.info21.lm_password_set = true;
1229 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1230 u.info21.nt_owf_password.length = 16;
1231 u.info21.nt_owf_password.size = 16;
1232 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1233 u.info21.nt_password_set = true;
1236 break;
1237 case 23:
1238 u.info23.info.fields_present = fields_present;
1239 u.info23.info.password_expired = password_expired;
1240 u.info23.info.comment.string = comment;
1242 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1244 break;
1245 case 24:
1246 u.info24.password_expired = password_expired;
1248 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1250 break;
1251 case 25:
1252 u.info25.info.fields_present = fields_present;
1253 u.info25.info.password_expired = password_expired;
1254 u.info25.info.comment.string = comment;
1256 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1258 break;
1259 case 26:
1260 u.info26.password_expired = password_expired;
1262 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1264 break;
1267 status = dcerpc_fetch_session_key(p, &session_key);
1268 if (!NT_STATUS_IS_OK(status)) {
1269 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1270 s.in.level, nt_errstr(status));
1271 return false;
1274 generate_random_buffer((uint8_t *)confounder, 16);
1276 MD5Init(&ctx);
1277 MD5Update(&ctx, confounder, 16);
1278 MD5Update(&ctx, session_key.data, session_key.length);
1279 MD5Final(confounded_session_key.data, &ctx);
1281 switch (level) {
1282 case 18:
1284 DATA_BLOB in,out;
1285 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1286 out = data_blob_talloc_zero(tctx, 16);
1287 sess_crypt_blob(&out, &in, &session_key, true);
1288 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1291 DATA_BLOB in,out;
1292 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1293 out = data_blob_talloc_zero(tctx, 16);
1294 sess_crypt_blob(&out, &in, &session_key, true);
1295 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1298 break;
1299 case 21:
1300 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1301 DATA_BLOB in,out;
1302 in = data_blob_const(u.info21.lm_owf_password.array,
1303 u.info21.lm_owf_password.length);
1304 out = data_blob_talloc_zero(tctx, 16);
1305 sess_crypt_blob(&out, &in, &session_key, true);
1306 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1308 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1309 DATA_BLOB in,out;
1310 in = data_blob_const(u.info21.nt_owf_password.array,
1311 u.info21.nt_owf_password.length);
1312 out = data_blob_talloc_zero(tctx, 16);
1313 sess_crypt_blob(&out, &in, &session_key, true);
1314 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1316 break;
1317 case 23:
1318 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1319 break;
1320 case 24:
1321 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1322 break;
1323 case 25:
1324 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1325 memcpy(&u.info25.password.data[516], confounder, 16);
1326 break;
1327 case 26:
1328 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1329 memcpy(&u.info26.password.data[516], confounder, 16);
1330 break;
1333 if (use_setinfo2) {
1334 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1335 "SetUserInfo2 failed");
1336 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1337 __location__, __FUNCTION__,
1338 newpass, nt_errstr(s2.out.result));
1339 status = s2.out.result;
1340 } else {
1341 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1342 "SetUserInfo failed");
1343 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1344 __location__, __FUNCTION__,
1345 newpass, nt_errstr(s.out.result));
1346 status = s.out.result;
1349 if (!NT_STATUS_IS_OK(status)) {
1350 if (fields_present == 0) {
1351 expected_error = NT_STATUS_INVALID_PARAMETER;
1353 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1354 expected_error = NT_STATUS_ACCESS_DENIED;
1358 if (!NT_STATUS_IS_OK(expected_error)) {
1359 if (use_setinfo2) {
1360 torture_assert_ntstatus_equal(tctx,
1361 s2.out.result,
1362 expected_error, "SetUserInfo2 failed");
1363 } else {
1364 torture_assert_ntstatus_equal(tctx,
1365 s.out.result,
1366 expected_error, "SetUserInfo failed");
1368 *matched_expected_error = true;
1369 return true;
1372 if (!NT_STATUS_IS_OK(status)) {
1373 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1374 use_setinfo2 ? "2":"", level, nt_errstr(status));
1375 ret = false;
1376 } else {
1377 *password = newpass;
1380 return ret;
1383 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1384 struct torture_context *tctx,
1385 struct policy_handle *handle)
1387 struct samr_SetAliasInfo r;
1388 struct samr_QueryAliasInfo q;
1389 union samr_AliasInfo *info;
1390 uint16_t levels[] = {2, 3};
1391 int i;
1392 bool ret = true;
1394 /* Ignoring switch level 1, as that includes the number of members for the alias
1395 * and setting this to a wrong value might have negative consequences
1398 for (i=0;i<ARRAY_SIZE(levels);i++) {
1399 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1401 r.in.alias_handle = handle;
1402 r.in.level = levels[i];
1403 r.in.info = talloc(tctx, union samr_AliasInfo);
1404 switch (r.in.level) {
1405 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1406 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1407 "Test Description, should test I18N as well"); break;
1408 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1411 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1412 "SetAliasInfo failed");
1413 if (!NT_STATUS_IS_OK(r.out.result)) {
1414 torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1415 levels[i], nt_errstr(r.out.result));
1416 ret = false;
1419 q.in.alias_handle = handle;
1420 q.in.level = levels[i];
1421 q.out.info = &info;
1423 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1424 "QueryAliasInfo failed");
1425 if (!NT_STATUS_IS_OK(q.out.result)) {
1426 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1427 levels[i], nt_errstr(q.out.result));
1428 ret = false;
1432 return ret;
1435 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1436 struct torture_context *tctx,
1437 struct policy_handle *user_handle)
1439 struct samr_GetGroupsForUser r;
1440 struct samr_RidWithAttributeArray *rids = NULL;
1442 torture_comment(tctx, "Testing GetGroupsForUser\n");
1444 r.in.user_handle = user_handle;
1445 r.out.rids = &rids;
1447 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1448 "GetGroupsForUser failed");
1449 torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1451 return true;
1455 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1456 struct lsa_String *domain_name)
1458 struct samr_GetDomPwInfo r;
1459 struct samr_PwInfo info;
1460 struct dcerpc_binding_handle *b = p->binding_handle;
1462 r.in.domain_name = domain_name;
1463 r.out.info = &info;
1465 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1467 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1468 "GetDomPwInfo failed");
1469 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1471 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1472 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1474 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1475 "GetDomPwInfo failed");
1476 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1478 r.in.domain_name->string = "\\\\__NONAME__";
1479 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1481 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1482 "GetDomPwInfo failed");
1483 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1485 r.in.domain_name->string = "\\\\Builtin";
1486 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1488 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1489 "GetDomPwInfo failed");
1490 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1492 return true;
1495 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1496 struct torture_context *tctx,
1497 struct policy_handle *handle)
1499 struct samr_GetUserPwInfo r;
1500 struct samr_PwInfo info;
1502 torture_comment(tctx, "Testing GetUserPwInfo\n");
1504 r.in.user_handle = handle;
1505 r.out.info = &info;
1507 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1508 "GetUserPwInfo failed");
1509 torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1511 return true;
1514 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1515 struct torture_context *tctx,
1516 struct policy_handle *domain_handle, const char *name,
1517 uint32_t *rid)
1519 NTSTATUS status;
1520 struct samr_LookupNames n;
1521 struct lsa_String sname[2];
1522 struct samr_Ids rids, types;
1524 init_lsa_String(&sname[0], name);
1526 n.in.domain_handle = domain_handle;
1527 n.in.num_names = 1;
1528 n.in.names = sname;
1529 n.out.rids = &rids;
1530 n.out.types = &types;
1531 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1532 if (!NT_STATUS_IS_OK(status)) {
1533 return status;
1535 if (NT_STATUS_IS_OK(n.out.result)) {
1536 *rid = n.out.rids->ids[0];
1537 } else {
1538 return n.out.result;
1541 init_lsa_String(&sname[1], "xxNONAMExx");
1542 n.in.num_names = 2;
1543 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1544 if (!NT_STATUS_IS_OK(status)) {
1545 return status;
1547 if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1548 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1549 if (NT_STATUS_IS_OK(n.out.result)) {
1550 return NT_STATUS_UNSUCCESSFUL;
1552 return n.out.result;
1555 n.in.num_names = 0;
1556 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1557 if (!NT_STATUS_IS_OK(status)) {
1558 return status;
1560 if (!NT_STATUS_IS_OK(n.out.result)) {
1561 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1562 return n.out.result;
1565 init_lsa_String(&sname[0], "xxNONAMExx");
1566 n.in.num_names = 1;
1567 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 return status;
1571 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1572 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1573 if (NT_STATUS_IS_OK(n.out.result)) {
1574 return NT_STATUS_UNSUCCESSFUL;
1576 return n.out.result;
1579 init_lsa_String(&sname[0], "xxNONAMExx");
1580 init_lsa_String(&sname[1], "xxNONAME2xx");
1581 n.in.num_names = 2;
1582 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1583 if (!NT_STATUS_IS_OK(status)) {
1584 return status;
1586 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1587 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1588 if (NT_STATUS_IS_OK(n.out.result)) {
1589 return NT_STATUS_UNSUCCESSFUL;
1591 return n.out.result;
1594 return NT_STATUS_OK;
1597 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1598 struct torture_context *tctx,
1599 struct policy_handle *domain_handle,
1600 const char *name, struct policy_handle *user_handle)
1602 NTSTATUS status;
1603 struct samr_OpenUser r;
1604 uint32_t rid;
1606 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1607 if (!NT_STATUS_IS_OK(status)) {
1608 return status;
1611 r.in.domain_handle = domain_handle;
1612 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1613 r.in.rid = rid;
1614 r.out.user_handle = user_handle;
1615 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1616 if (!NT_STATUS_IS_OK(status)) {
1617 return status;
1619 if (!NT_STATUS_IS_OK(r.out.result)) {
1620 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1623 return r.out.result;
1626 #if 0
1627 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1628 struct torture_context *tctx,
1629 struct policy_handle *handle)
1631 NTSTATUS status;
1632 struct samr_ChangePasswordUser r;
1633 bool ret = true;
1634 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1635 struct policy_handle user_handle;
1636 char *oldpass = "test";
1637 char *newpass = "test2";
1638 uint8_t old_nt_hash[16], new_nt_hash[16];
1639 uint8_t old_lm_hash[16], new_lm_hash[16];
1641 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 return false;
1646 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1648 torture_comment(tctx, "old password: %s\n", oldpass);
1649 torture_comment(tctx, "new password: %s\n", newpass);
1651 E_md4hash(oldpass, old_nt_hash);
1652 E_md4hash(newpass, new_nt_hash);
1653 E_deshash(oldpass, old_lm_hash);
1654 E_deshash(newpass, new_lm_hash);
1656 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1657 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1658 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1659 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1660 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1661 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1663 r.in.handle = &user_handle;
1664 r.in.lm_present = 1;
1665 r.in.old_lm_crypted = &hash1;
1666 r.in.new_lm_crypted = &hash2;
1667 r.in.nt_present = 1;
1668 r.in.old_nt_crypted = &hash3;
1669 r.in.new_nt_crypted = &hash4;
1670 r.in.cross1_present = 1;
1671 r.in.nt_cross = &hash5;
1672 r.in.cross2_present = 1;
1673 r.in.lm_cross = &hash6;
1675 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1676 "ChangePasswordUser failed");
1677 if (!NT_STATUS_IS_OK(r.out.result)) {
1678 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1679 ret = false;
1682 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1683 ret = false;
1686 return ret;
1688 #endif
1690 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1691 struct torture_context *tctx,
1692 const char *acct_name,
1693 struct policy_handle *handle, char **password)
1695 NTSTATUS status;
1696 struct samr_ChangePasswordUser r;
1697 bool ret = true;
1698 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1699 struct policy_handle user_handle;
1700 char *oldpass;
1701 uint8_t old_nt_hash[16], new_nt_hash[16];
1702 uint8_t old_lm_hash[16], new_lm_hash[16];
1703 bool changed = true;
1705 char *newpass;
1706 struct samr_GetUserPwInfo pwp;
1707 struct samr_PwInfo info;
1708 int policy_min_pw_len = 0;
1710 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1711 if (!NT_STATUS_IS_OK(status)) {
1712 return false;
1714 pwp.in.user_handle = &user_handle;
1715 pwp.out.info = &info;
1717 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1718 "GetUserPwInfo failed");
1719 if (NT_STATUS_IS_OK(pwp.out.result)) {
1720 policy_min_pw_len = pwp.out.info->min_password_length;
1722 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1724 torture_comment(tctx, "Testing ChangePasswordUser\n");
1726 torture_assert(tctx, *password != NULL,
1727 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1729 oldpass = *password;
1731 E_md4hash(oldpass, old_nt_hash);
1732 E_md4hash(newpass, new_nt_hash);
1733 E_deshash(oldpass, old_lm_hash);
1734 E_deshash(newpass, new_lm_hash);
1736 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1737 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1738 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1739 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1740 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1741 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1743 r.in.user_handle = &user_handle;
1744 r.in.lm_present = 1;
1745 /* Break the LM hash */
1746 hash1.hash[0]++;
1747 r.in.old_lm_crypted = &hash1;
1748 r.in.new_lm_crypted = &hash2;
1749 r.in.nt_present = 1;
1750 r.in.old_nt_crypted = &hash3;
1751 r.in.new_nt_crypted = &hash4;
1752 r.in.cross1_present = 1;
1753 r.in.nt_cross = &hash5;
1754 r.in.cross2_present = 1;
1755 r.in.lm_cross = &hash6;
1757 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1758 "ChangePasswordUser failed");
1759 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1760 __location__, __FUNCTION__,
1761 oldpass, newpass, nt_errstr(r.out.result));
1763 /* Do not proceed if this call has been removed */
1764 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
1765 return true;
1768 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1769 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1770 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1773 /* Unbreak the LM hash */
1774 hash1.hash[0]--;
1776 r.in.user_handle = &user_handle;
1777 r.in.lm_present = 1;
1778 r.in.old_lm_crypted = &hash1;
1779 r.in.new_lm_crypted = &hash2;
1780 /* Break the NT hash */
1781 hash3.hash[0]--;
1782 r.in.nt_present = 1;
1783 r.in.old_nt_crypted = &hash3;
1784 r.in.new_nt_crypted = &hash4;
1785 r.in.cross1_present = 1;
1786 r.in.nt_cross = &hash5;
1787 r.in.cross2_present = 1;
1788 r.in.lm_cross = &hash6;
1790 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1791 "ChangePasswordUser failed");
1792 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1793 __location__, __FUNCTION__,
1794 oldpass, newpass, nt_errstr(r.out.result));
1795 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1796 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1797 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1800 /* Unbreak the NT hash */
1801 hash3.hash[0]--;
1803 r.in.user_handle = &user_handle;
1804 r.in.lm_present = 1;
1805 r.in.old_lm_crypted = &hash1;
1806 r.in.new_lm_crypted = &hash2;
1807 r.in.nt_present = 1;
1808 r.in.old_nt_crypted = &hash3;
1809 r.in.new_nt_crypted = &hash4;
1810 r.in.cross1_present = 1;
1811 r.in.nt_cross = &hash5;
1812 r.in.cross2_present = 1;
1813 /* Break the LM cross */
1814 hash6.hash[0]++;
1815 r.in.lm_cross = &hash6;
1817 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1818 "ChangePasswordUser failed");
1819 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1820 __location__, __FUNCTION__,
1821 oldpass, newpass, nt_errstr(r.out.result));
1822 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1823 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1825 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
1826 ret = false;
1829 /* Unbreak the LM cross */
1830 hash6.hash[0]--;
1832 r.in.user_handle = &user_handle;
1833 r.in.lm_present = 1;
1834 r.in.old_lm_crypted = &hash1;
1835 r.in.new_lm_crypted = &hash2;
1836 r.in.nt_present = 1;
1837 r.in.old_nt_crypted = &hash3;
1838 r.in.new_nt_crypted = &hash4;
1839 r.in.cross1_present = 1;
1840 /* Break the NT cross */
1841 hash5.hash[0]++;
1842 r.in.nt_cross = &hash5;
1843 r.in.cross2_present = 1;
1844 r.in.lm_cross = &hash6;
1846 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1847 "ChangePasswordUser failed");
1848 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1849 __location__, __FUNCTION__,
1850 oldpass, newpass, nt_errstr(r.out.result));
1851 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1852 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1854 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
1855 ret = false;
1858 /* Unbreak the NT cross */
1859 hash5.hash[0]--;
1862 /* Reset the hashes to not broken values */
1863 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1864 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1865 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1866 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1867 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1868 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1870 r.in.user_handle = &user_handle;
1871 r.in.lm_present = 1;
1872 r.in.old_lm_crypted = &hash1;
1873 r.in.new_lm_crypted = &hash2;
1874 r.in.nt_present = 1;
1875 r.in.old_nt_crypted = &hash3;
1876 r.in.new_nt_crypted = &hash4;
1877 r.in.cross1_present = 1;
1878 r.in.nt_cross = &hash5;
1879 r.in.cross2_present = 0;
1880 r.in.lm_cross = NULL;
1882 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1883 "ChangePasswordUser failed");
1884 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1885 __location__, __FUNCTION__,
1886 oldpass, newpass, nt_errstr(r.out.result));
1887 if (NT_STATUS_IS_OK(r.out.result)) {
1888 changed = true;
1889 *password = newpass;
1890 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1891 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1892 ret = false;
1895 oldpass = newpass;
1896 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1898 E_md4hash(oldpass, old_nt_hash);
1899 E_md4hash(newpass, new_nt_hash);
1900 E_deshash(oldpass, old_lm_hash);
1901 E_deshash(newpass, new_lm_hash);
1904 /* Reset the hashes to not broken values */
1905 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1906 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1907 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1908 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1909 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1910 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1912 r.in.user_handle = &user_handle;
1913 r.in.lm_present = 1;
1914 r.in.old_lm_crypted = &hash1;
1915 r.in.new_lm_crypted = &hash2;
1916 r.in.nt_present = 1;
1917 r.in.old_nt_crypted = &hash3;
1918 r.in.new_nt_crypted = &hash4;
1919 r.in.cross1_present = 0;
1920 r.in.nt_cross = NULL;
1921 r.in.cross2_present = 1;
1922 r.in.lm_cross = &hash6;
1924 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1925 "ChangePasswordUser failed");
1926 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1927 __location__, __FUNCTION__,
1928 oldpass, newpass, nt_errstr(r.out.result));
1929 if (NT_STATUS_IS_OK(r.out.result)) {
1930 changed = true;
1931 *password = newpass;
1932 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1933 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1934 ret = false;
1937 oldpass = newpass;
1938 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1940 E_md4hash(oldpass, old_nt_hash);
1941 E_md4hash(newpass, new_nt_hash);
1942 E_deshash(oldpass, old_lm_hash);
1943 E_deshash(newpass, new_lm_hash);
1946 /* Reset the hashes to not broken values */
1947 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1948 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1949 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1950 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1951 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1952 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1954 r.in.user_handle = &user_handle;
1955 r.in.lm_present = 1;
1956 r.in.old_lm_crypted = &hash1;
1957 r.in.new_lm_crypted = &hash2;
1958 r.in.nt_present = 1;
1959 r.in.old_nt_crypted = &hash3;
1960 r.in.new_nt_crypted = &hash4;
1961 r.in.cross1_present = 1;
1962 r.in.nt_cross = &hash5;
1963 r.in.cross2_present = 1;
1964 r.in.lm_cross = &hash6;
1966 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1967 "ChangePasswordUser failed");
1968 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1969 __location__, __FUNCTION__,
1970 oldpass, newpass, nt_errstr(r.out.result));
1971 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1972 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1973 } else if (!NT_STATUS_IS_OK(r.out.result)) {
1974 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1975 ret = false;
1976 } else {
1977 changed = true;
1978 *password = newpass;
1981 r.in.user_handle = &user_handle;
1982 r.in.lm_present = 1;
1983 r.in.old_lm_crypted = &hash1;
1984 r.in.new_lm_crypted = &hash2;
1985 r.in.nt_present = 1;
1986 r.in.old_nt_crypted = &hash3;
1987 r.in.new_nt_crypted = &hash4;
1988 r.in.cross1_present = 1;
1989 r.in.nt_cross = &hash5;
1990 r.in.cross2_present = 1;
1991 r.in.lm_cross = &hash6;
1993 if (changed) {
1994 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1995 "ChangePasswordUser failed");
1996 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1997 __location__, __FUNCTION__,
1998 oldpass, newpass, nt_errstr(r.out.result));
1999 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2000 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2001 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2002 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
2003 ret = false;
2008 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
2009 ret = false;
2012 return ret;
2016 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
2017 struct torture_context *tctx,
2018 const char *acct_name,
2019 struct policy_handle *handle, char **password)
2021 struct samr_OemChangePasswordUser2 r;
2022 bool ret = true;
2023 struct samr_Password lm_verifier;
2024 struct samr_CryptPassword lm_pass;
2025 struct lsa_AsciiString server, account, account_bad;
2026 char *oldpass;
2027 char *newpass;
2028 struct dcerpc_binding_handle *b = p->binding_handle;
2029 uint8_t old_lm_hash[16], new_lm_hash[16];
2031 struct samr_GetDomPwInfo dom_pw_info;
2032 struct samr_PwInfo info;
2033 int policy_min_pw_len = 0;
2035 struct lsa_String domain_name;
2037 domain_name.string = "";
2038 dom_pw_info.in.domain_name = &domain_name;
2039 dom_pw_info.out.info = &info;
2041 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
2043 torture_assert(tctx, *password != NULL,
2044 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
2046 oldpass = *password;
2048 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2049 "GetDomPwInfo failed");
2050 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2051 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2054 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2056 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2057 account.string = acct_name;
2059 E_deshash(oldpass, old_lm_hash);
2060 E_deshash(newpass, new_lm_hash);
2062 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2063 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2064 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2066 r.in.server = &server;
2067 r.in.account = &account;
2068 r.in.password = &lm_pass;
2069 r.in.hash = &lm_verifier;
2071 /* Break the verification */
2072 lm_verifier.hash[0]++;
2074 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2075 "OemChangePasswordUser2 failed");
2076 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2077 __location__, __FUNCTION__,
2078 oldpass, newpass, nt_errstr(r.out.result));
2080 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2081 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2082 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2083 nt_errstr(r.out.result));
2084 ret = false;
2087 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2088 /* Break the old password */
2089 old_lm_hash[0]++;
2090 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2091 /* unbreak it for the next operation */
2092 old_lm_hash[0]--;
2093 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2095 r.in.server = &server;
2096 r.in.account = &account;
2097 r.in.password = &lm_pass;
2098 r.in.hash = &lm_verifier;
2100 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2101 "OemChangePasswordUser2 failed");
2102 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2103 __location__, __FUNCTION__,
2104 oldpass, newpass, nt_errstr(r.out.result));
2106 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2107 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2108 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2109 nt_errstr(r.out.result));
2110 ret = false;
2113 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2114 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2116 r.in.server = &server;
2117 r.in.account = &account;
2118 r.in.password = &lm_pass;
2119 r.in.hash = NULL;
2121 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2122 "OemChangePasswordUser2 failed");
2123 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2124 __location__, __FUNCTION__,
2125 oldpass, newpass, nt_errstr(r.out.result));
2127 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2128 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2129 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2130 nt_errstr(r.out.result));
2131 ret = false;
2134 /* This shouldn't be a valid name */
2135 account_bad.string = TEST_ACCOUNT_NAME "XX";
2136 r.in.account = &account_bad;
2138 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2139 "OemChangePasswordUser2 failed");
2140 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2141 __location__, __FUNCTION__,
2142 oldpass, newpass, nt_errstr(r.out.result));
2144 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2145 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2146 nt_errstr(r.out.result));
2147 ret = false;
2150 /* This shouldn't be a valid name */
2151 account_bad.string = TEST_ACCOUNT_NAME "XX";
2152 r.in.account = &account_bad;
2153 r.in.password = &lm_pass;
2154 r.in.hash = &lm_verifier;
2156 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2157 "OemChangePasswordUser2 failed");
2158 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2159 __location__, __FUNCTION__,
2160 oldpass, newpass, nt_errstr(r.out.result));
2162 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2163 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2164 nt_errstr(r.out.result));
2165 ret = false;
2168 /* This shouldn't be a valid name */
2169 account_bad.string = TEST_ACCOUNT_NAME "XX";
2170 r.in.account = &account_bad;
2171 r.in.password = NULL;
2172 r.in.hash = &lm_verifier;
2174 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2175 "OemChangePasswordUser2 failed");
2176 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2177 __location__, __FUNCTION__,
2178 oldpass, newpass, nt_errstr(r.out.result));
2180 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2181 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2182 nt_errstr(r.out.result));
2183 ret = false;
2186 E_deshash(oldpass, old_lm_hash);
2187 E_deshash(newpass, new_lm_hash);
2189 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2190 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2191 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2193 r.in.server = &server;
2194 r.in.account = &account;
2195 r.in.password = &lm_pass;
2196 r.in.hash = &lm_verifier;
2198 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2199 "OemChangePasswordUser2 failed");
2200 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2201 __location__, __FUNCTION__,
2202 oldpass, newpass, nt_errstr(r.out.result));
2204 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2205 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2206 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2207 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2208 ret = false;
2209 } else {
2210 *password = newpass;
2213 return ret;
2217 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2218 const char *acct_name,
2219 char **password,
2220 char *newpass, bool allow_password_restriction)
2222 struct samr_ChangePasswordUser2 r;
2223 bool ret = true;
2224 struct lsa_String server, account;
2225 struct samr_CryptPassword nt_pass, lm_pass;
2226 struct samr_Password nt_verifier, lm_verifier;
2227 char *oldpass;
2228 struct dcerpc_binding_handle *b = p->binding_handle;
2229 uint8_t old_nt_hash[16], new_nt_hash[16];
2230 uint8_t old_lm_hash[16], new_lm_hash[16];
2232 struct samr_GetDomPwInfo dom_pw_info;
2233 struct samr_PwInfo info;
2235 struct lsa_String domain_name;
2237 domain_name.string = "";
2238 dom_pw_info.in.domain_name = &domain_name;
2239 dom_pw_info.out.info = &info;
2241 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2243 torture_assert(tctx, *password != NULL,
2244 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2245 oldpass = *password;
2247 if (!newpass) {
2248 int policy_min_pw_len = 0;
2249 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2250 "GetDomPwInfo failed");
2251 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2252 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2255 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2258 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2259 init_lsa_String(&account, acct_name);
2261 E_md4hash(oldpass, old_nt_hash);
2262 E_md4hash(newpass, new_nt_hash);
2264 E_deshash(oldpass, old_lm_hash);
2265 E_deshash(newpass, new_lm_hash);
2267 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2268 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2269 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2271 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2272 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2273 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2275 r.in.server = &server;
2276 r.in.account = &account;
2277 r.in.nt_password = &nt_pass;
2278 r.in.nt_verifier = &nt_verifier;
2279 r.in.lm_change = 1;
2280 r.in.lm_password = &lm_pass;
2281 r.in.lm_verifier = &lm_verifier;
2283 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2284 "ChangePasswordUser2 failed");
2285 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2286 __location__, __FUNCTION__,
2287 oldpass, newpass, nt_errstr(r.out.result));
2289 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2290 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2291 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2292 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2293 ret = false;
2294 } else {
2295 *password = newpass;
2298 return ret;
2302 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2303 const char *account_string,
2304 int policy_min_pw_len,
2305 char **password,
2306 const char *newpass,
2307 NTTIME last_password_change,
2308 bool handle_reject_reason)
2310 struct samr_ChangePasswordUser3 r;
2311 bool ret = true;
2312 struct lsa_String server, account, account_bad;
2313 struct samr_CryptPassword nt_pass, lm_pass;
2314 struct samr_Password nt_verifier, lm_verifier;
2315 char *oldpass;
2316 struct dcerpc_binding_handle *b = p->binding_handle;
2317 uint8_t old_nt_hash[16], new_nt_hash[16];
2318 uint8_t old_lm_hash[16], new_lm_hash[16];
2319 NTTIME t;
2320 struct samr_DomInfo1 *dominfo = NULL;
2321 struct userPwdChangeFailureInformation *reject = NULL;
2323 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2325 if (newpass == NULL) {
2326 do {
2327 if (policy_min_pw_len == 0) {
2328 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2329 } else {
2330 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2332 } while (check_password_quality(newpass) == false);
2333 } else {
2334 torture_comment(tctx, "Using password '%s'\n", newpass);
2337 torture_assert(tctx, *password != NULL,
2338 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2340 oldpass = *password;
2341 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2342 init_lsa_String(&account, account_string);
2344 E_md4hash(oldpass, old_nt_hash);
2345 E_md4hash(newpass, new_nt_hash);
2347 E_deshash(oldpass, old_lm_hash);
2348 E_deshash(newpass, new_lm_hash);
2350 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2351 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2352 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2354 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2355 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2356 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2358 /* Break the verification */
2359 nt_verifier.hash[0]++;
2361 r.in.server = &server;
2362 r.in.account = &account;
2363 r.in.nt_password = &nt_pass;
2364 r.in.nt_verifier = &nt_verifier;
2365 r.in.lm_change = 1;
2366 r.in.lm_password = &lm_pass;
2367 r.in.lm_verifier = &lm_verifier;
2368 r.in.password3 = NULL;
2369 r.out.dominfo = &dominfo;
2370 r.out.reject = &reject;
2372 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2373 "ChangePasswordUser3 failed");
2374 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2375 __location__, __FUNCTION__,
2376 oldpass, newpass, nt_errstr(r.out.result));
2377 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2378 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2379 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2380 nt_errstr(r.out.result));
2381 ret = false;
2384 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2385 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2386 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2388 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2389 /* Break the NT hash */
2390 old_nt_hash[0]++;
2391 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2392 /* Unbreak it again */
2393 old_nt_hash[0]--;
2394 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2396 r.in.server = &server;
2397 r.in.account = &account;
2398 r.in.nt_password = &nt_pass;
2399 r.in.nt_verifier = &nt_verifier;
2400 r.in.lm_change = 1;
2401 r.in.lm_password = &lm_pass;
2402 r.in.lm_verifier = &lm_verifier;
2403 r.in.password3 = NULL;
2404 r.out.dominfo = &dominfo;
2405 r.out.reject = &reject;
2407 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2408 "ChangePasswordUser3 failed");
2409 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2410 __location__, __FUNCTION__,
2411 oldpass, newpass, nt_errstr(r.out.result));
2412 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2413 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2414 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2415 nt_errstr(r.out.result));
2416 ret = false;
2419 /* This shouldn't be a valid name */
2420 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2422 r.in.account = &account_bad;
2423 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2424 "ChangePasswordUser3 failed");
2425 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2426 __location__, __FUNCTION__,
2427 oldpass, newpass, nt_errstr(r.out.result));
2428 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2429 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2430 nt_errstr(r.out.result));
2431 ret = false;
2434 E_md4hash(oldpass, old_nt_hash);
2435 E_md4hash(newpass, new_nt_hash);
2437 E_deshash(oldpass, old_lm_hash);
2438 E_deshash(newpass, new_lm_hash);
2440 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2441 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2442 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2444 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2445 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2446 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2448 r.in.server = &server;
2449 r.in.account = &account;
2450 r.in.nt_password = &nt_pass;
2451 r.in.nt_verifier = &nt_verifier;
2452 r.in.lm_change = 1;
2453 r.in.lm_password = &lm_pass;
2454 r.in.lm_verifier = &lm_verifier;
2455 r.in.password3 = NULL;
2456 r.out.dominfo = &dominfo;
2457 r.out.reject = &reject;
2459 unix_to_nt_time(&t, time(NULL));
2461 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2462 "ChangePasswordUser3 failed");
2463 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2464 __location__, __FUNCTION__,
2465 oldpass, newpass, nt_errstr(r.out.result));
2467 torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2468 "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2469 __location__,
2470 (dominfo == NULL)? "NULL" : "present",
2471 reject ? "true" : "false",
2472 handle_reject_reason ? "true" : "false",
2473 null_nttime(last_password_change) ? "null" : "not null",
2474 dominfo ? (long long)dominfo->min_password_age : (long long)0);
2476 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2477 && dominfo
2478 && reject
2479 && handle_reject_reason
2480 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2481 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2483 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2484 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2485 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2486 return false;
2490 /* We tested the order of precendence which is as follows:
2492 * pwd min_age
2493 * pwd length
2494 * pwd complexity
2495 * pwd history
2497 Guenther */
2499 if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
2500 (last_password_change - dominfo->min_password_age > t)) {
2502 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2503 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2504 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2505 return false;
2508 } else if ((dominfo->min_password_length > 0) &&
2509 (strlen(newpass) < dominfo->min_password_length)) {
2511 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2512 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2513 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2514 return false;
2517 } else if ((dominfo->password_history_length > 0) &&
2518 strequal(oldpass, newpass)) {
2520 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2521 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2522 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2523 return false;
2525 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2527 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2528 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2529 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2530 return false;
2535 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2536 /* retry with adjusted size */
2537 return test_ChangePasswordUser3(p, tctx, account_string,
2538 dominfo->min_password_length,
2539 password, NULL, 0, false);
2543 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2544 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2545 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2546 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2547 return false;
2549 /* Perhaps the server has a 'min password age' set? */
2551 } else {
2552 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2554 *password = talloc_strdup(tctx, newpass);
2557 return ret;
2560 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2561 const char *account_string,
2562 struct policy_handle *handle,
2563 char **password)
2565 NTSTATUS status;
2566 struct samr_ChangePasswordUser3 r;
2567 struct samr_SetUserInfo s;
2568 union samr_UserInfo u;
2569 DATA_BLOB session_key;
2570 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2571 uint8_t confounder[16];
2572 struct MD5Context ctx;
2574 bool ret = true;
2575 struct lsa_String server, account;
2576 struct samr_CryptPassword nt_pass;
2577 struct samr_Password nt_verifier;
2578 DATA_BLOB new_random_pass;
2579 char *newpass;
2580 char *oldpass;
2581 struct dcerpc_binding_handle *b = p->binding_handle;
2582 uint8_t old_nt_hash[16], new_nt_hash[16];
2583 NTTIME t;
2584 struct samr_DomInfo1 *dominfo = NULL;
2585 struct userPwdChangeFailureInformation *reject = NULL;
2587 new_random_pass = samr_very_rand_pass(tctx, 128);
2589 torture_assert(tctx, *password != NULL,
2590 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2592 oldpass = *password;
2593 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2594 init_lsa_String(&account, account_string);
2596 s.in.user_handle = handle;
2597 s.in.info = &u;
2598 s.in.level = 25;
2600 ZERO_STRUCT(u);
2602 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2604 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2606 status = dcerpc_fetch_session_key(p, &session_key);
2607 if (!NT_STATUS_IS_OK(status)) {
2608 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2609 s.in.level, nt_errstr(status));
2610 return false;
2613 generate_random_buffer((uint8_t *)confounder, 16);
2615 MD5Init(&ctx);
2616 MD5Update(&ctx, confounder, 16);
2617 MD5Update(&ctx, session_key.data, session_key.length);
2618 MD5Final(confounded_session_key.data, &ctx);
2620 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2621 memcpy(&u.info25.password.data[516], confounder, 16);
2623 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2625 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2626 "SetUserInfo failed");
2627 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2628 __location__, __FUNCTION__,
2629 oldpass, "RANDOM", nt_errstr(s.out.result));
2630 if (!NT_STATUS_IS_OK(s.out.result)) {
2631 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2632 s.in.level, nt_errstr(s.out.result));
2633 ret = false;
2636 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2638 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2640 new_random_pass = samr_very_rand_pass(tctx, 128);
2642 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2644 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2645 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2646 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2648 r.in.server = &server;
2649 r.in.account = &account;
2650 r.in.nt_password = &nt_pass;
2651 r.in.nt_verifier = &nt_verifier;
2652 r.in.lm_change = 0;
2653 r.in.lm_password = NULL;
2654 r.in.lm_verifier = NULL;
2655 r.in.password3 = NULL;
2656 r.out.dominfo = &dominfo;
2657 r.out.reject = &reject;
2659 unix_to_nt_time(&t, time(NULL));
2661 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2662 "ChangePasswordUser3 failed");
2663 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2664 __location__, __FUNCTION__,
2665 oldpass, "RANDOM", nt_errstr(r.out.result));
2667 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2668 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2669 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2670 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2671 return false;
2673 /* Perhaps the server has a 'min password age' set? */
2675 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2676 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2677 ret = false;
2680 newpass = samr_rand_pass(tctx, 128);
2682 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2684 E_md4hash(newpass, new_nt_hash);
2686 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2687 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2688 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2690 r.in.server = &server;
2691 r.in.account = &account;
2692 r.in.nt_password = &nt_pass;
2693 r.in.nt_verifier = &nt_verifier;
2694 r.in.lm_change = 0;
2695 r.in.lm_password = NULL;
2696 r.in.lm_verifier = NULL;
2697 r.in.password3 = NULL;
2698 r.out.dominfo = &dominfo;
2699 r.out.reject = &reject;
2701 unix_to_nt_time(&t, time(NULL));
2703 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2704 "ChangePasswordUser3 failed");
2705 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2706 __location__, __FUNCTION__,
2707 oldpass, newpass, nt_errstr(r.out.result));
2709 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2710 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2711 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2712 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2713 return false;
2715 /* Perhaps the server has a 'min password age' set? */
2717 } else {
2718 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2719 *password = talloc_strdup(tctx, newpass);
2722 return ret;
2726 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2727 struct torture_context *tctx,
2728 struct policy_handle *alias_handle)
2730 struct samr_GetMembersInAlias r;
2731 struct lsa_SidArray sids;
2733 torture_comment(tctx, "Testing GetMembersInAlias\n");
2735 r.in.alias_handle = alias_handle;
2736 r.out.sids = &sids;
2738 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2739 "GetMembersInAlias failed");
2740 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2742 return true;
2745 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2746 struct torture_context *tctx,
2747 struct policy_handle *alias_handle,
2748 const struct dom_sid *domain_sid)
2750 struct samr_AddAliasMember r;
2751 struct samr_DeleteAliasMember d;
2752 struct dom_sid *sid;
2754 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2756 torture_comment(tctx, "Testing AddAliasMember\n");
2757 r.in.alias_handle = alias_handle;
2758 r.in.sid = sid;
2760 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2761 "AddAliasMember failed");
2762 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2764 d.in.alias_handle = alias_handle;
2765 d.in.sid = sid;
2767 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2768 "DeleteAliasMember failed");
2769 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2771 return true;
2774 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2775 struct torture_context *tctx,
2776 struct policy_handle *alias_handle)
2778 struct samr_AddMultipleMembersToAlias a;
2779 struct samr_RemoveMultipleMembersFromAlias r;
2780 struct lsa_SidArray sids;
2782 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2783 a.in.alias_handle = alias_handle;
2784 a.in.sids = &sids;
2786 sids.num_sids = 3;
2787 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2789 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2790 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2791 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2793 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2794 "AddMultipleMembersToAlias failed");
2795 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2798 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2799 r.in.alias_handle = alias_handle;
2800 r.in.sids = &sids;
2802 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2803 "RemoveMultipleMembersFromAlias failed");
2804 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2806 /* strange! removing twice doesn't give any error */
2807 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2808 "RemoveMultipleMembersFromAlias failed");
2809 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2811 /* but removing an alias that isn't there does */
2812 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2814 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2815 "RemoveMultipleMembersFromAlias failed");
2816 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2818 return true;
2821 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2822 struct torture_context *tctx,
2823 struct policy_handle *domain_handle)
2825 struct samr_GetAliasMembership r;
2826 struct lsa_SidArray sids;
2827 struct samr_Ids rids;
2829 torture_comment(tctx, "Testing GetAliasMembership\n");
2831 r.in.domain_handle = domain_handle;
2832 r.in.sids = &sids;
2833 r.out.rids = &rids;
2835 sids.num_sids = 0;
2836 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2838 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2839 "GetAliasMembership failed");
2840 torture_assert_ntstatus_ok(tctx, r.out.result,
2841 "samr_GetAliasMembership failed");
2843 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2844 "protocol misbehaviour");
2846 sids.num_sids = 1;
2847 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2848 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2850 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2851 "samr_GetAliasMembership failed");
2852 torture_assert_ntstatus_ok(tctx, r.out.result,
2853 "samr_GetAliasMembership failed");
2855 #if 0
2856 /* only true for w2k8 it seems
2857 * win7, xp, w2k3 will return a 0 length array pointer */
2859 if (rids.ids && (rids.count == 0)) {
2860 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2862 #endif
2863 if (!rids.ids && rids.count) {
2864 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2867 return true;
2870 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2871 struct torture_context *tctx,
2872 struct policy_handle *user_handle)
2874 struct samr_TestPrivateFunctionsUser r;
2876 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2878 r.in.user_handle = user_handle;
2880 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2881 "TestPrivateFunctionsUser failed");
2882 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2884 return true;
2887 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2888 struct torture_context *tctx,
2889 struct policy_handle *handle,
2890 bool use_info2,
2891 NTTIME *pwdlastset)
2893 NTSTATUS status;
2894 uint16_t levels[] = { /* 3, */ 5, 21 };
2895 int i;
2896 NTTIME pwdlastset3 = 0;
2897 NTTIME pwdlastset5 = 0;
2898 NTTIME pwdlastset21 = 0;
2900 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2901 use_info2 ? "2":"");
2903 for (i=0; i<ARRAY_SIZE(levels); i++) {
2905 struct samr_QueryUserInfo r;
2906 struct samr_QueryUserInfo2 r2;
2907 union samr_UserInfo *info;
2909 if (use_info2) {
2910 r2.in.user_handle = handle;
2911 r2.in.level = levels[i];
2912 r2.out.info = &info;
2913 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2914 "QueryUserInfo2 failed");
2915 status = r2.out.result;
2917 } else {
2918 r.in.user_handle = handle;
2919 r.in.level = levels[i];
2920 r.out.info = &info;
2921 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2922 "QueryUserInfo failed");
2923 status = r.out.result;
2926 if (!NT_STATUS_IS_OK(status) &&
2927 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2928 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2929 use_info2 ? "2":"", levels[i], nt_errstr(status));
2930 return false;
2933 switch (levels[i]) {
2934 case 3:
2935 pwdlastset3 = info->info3.last_password_change;
2936 break;
2937 case 5:
2938 pwdlastset5 = info->info5.last_password_change;
2939 break;
2940 case 21:
2941 pwdlastset21 = info->info21.last_password_change;
2942 break;
2943 default:
2944 return false;
2947 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2948 "pwdlastset mixup"); */
2949 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2950 "pwdlastset mixup");
2952 *pwdlastset = pwdlastset21;
2954 torture_comment(tctx, "(pwdlastset: %llu)\n",
2955 (unsigned long long) *pwdlastset);
2957 return true;
2960 static bool test_SamLogon(struct torture_context *tctx,
2961 struct dcerpc_pipe *p,
2962 struct cli_credentials *test_credentials,
2963 NTSTATUS expected_result,
2964 bool interactive)
2966 NTSTATUS status;
2967 struct netr_LogonSamLogonEx r;
2968 union netr_LogonLevel logon;
2969 union netr_Validation validation;
2970 uint8_t authoritative;
2971 struct netr_IdentityInfo identity;
2972 struct netr_NetworkInfo ninfo;
2973 struct netr_PasswordInfo pinfo;
2974 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2975 int flags = CLI_CRED_NTLM_AUTH;
2976 uint32_t samlogon_flags = 0;
2977 struct netlogon_creds_CredentialState *creds;
2978 struct netr_Authenticator a;
2979 struct dcerpc_binding_handle *b = p->binding_handle;
2981 torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2983 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
2984 flags |= CLI_CRED_LANMAN_AUTH;
2987 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
2988 flags |= CLI_CRED_NTLMv2_AUTH;
2991 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2992 &identity.account_name.string,
2993 &identity.domain_name.string);
2995 identity.parameter_control =
2996 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2997 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2998 identity.logon_id_low = 0;
2999 identity.logon_id_high = 0;
3000 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
3002 if (interactive) {
3003 netlogon_creds_client_authenticator(creds, &a);
3005 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
3006 ZERO_STRUCT(pinfo.lmpassword.hash);
3008 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
3010 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3011 netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
3012 netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
3013 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
3014 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
3015 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
3016 } else {
3017 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
3018 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
3021 pinfo.identity_info = identity;
3022 logon.password = &pinfo;
3024 r.in.logon_level = NetlogonInteractiveInformation;
3025 } else {
3026 generate_random_buffer(ninfo.challenge,
3027 sizeof(ninfo.challenge));
3028 chal = data_blob_const(ninfo.challenge,
3029 sizeof(ninfo.challenge));
3031 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3032 cli_credentials_get_domain(test_credentials));
3034 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3035 &flags,
3036 chal,
3037 names_blob,
3038 &lm_resp, &nt_resp,
3039 NULL, NULL);
3040 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3042 ninfo.lm.data = lm_resp.data;
3043 ninfo.lm.length = lm_resp.length;
3045 ninfo.nt.data = nt_resp.data;
3046 ninfo.nt.length = nt_resp.length;
3048 ninfo.identity_info = identity;
3049 logon.network = &ninfo;
3051 r.in.logon_level = NetlogonNetworkInformation;
3054 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3055 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3056 r.in.logon = &logon;
3057 r.in.flags = &samlogon_flags;
3058 r.out.flags = &samlogon_flags;
3059 r.out.validation = &validation;
3060 r.out.authoritative = &authoritative;
3062 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3064 r.in.validation_level = 6;
3066 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3067 "netr_LogonSamLogonEx failed");
3068 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3069 r.in.validation_level = 3;
3070 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3071 "netr_LogonSamLogonEx failed");
3073 if (!NT_STATUS_IS_OK(r.out.result)) {
3074 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3075 return true;
3076 } else {
3077 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3080 return true;
3083 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3084 struct dcerpc_pipe *p,
3085 struct cli_credentials *machine_creds,
3086 const char *acct_name,
3087 const char *password,
3088 NTSTATUS expected_samlogon_result,
3089 bool interactive)
3091 bool ret = true;
3092 struct cli_credentials *test_credentials;
3094 test_credentials = cli_credentials_init(tctx);
3096 cli_credentials_set_workstation(test_credentials,
3097 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3098 cli_credentials_set_domain(test_credentials,
3099 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3100 cli_credentials_set_username(test_credentials,
3101 acct_name, CRED_SPECIFIED);
3102 cli_credentials_set_password(test_credentials,
3103 password, CRED_SPECIFIED);
3105 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3106 interactive ? "interactive" : "network", acct_name, password);
3108 if (!test_SamLogon(tctx, p, test_credentials,
3109 expected_samlogon_result, interactive)) {
3110 torture_warning(tctx, "new password did not work\n");
3111 ret = false;
3114 return ret;
3117 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3118 struct dcerpc_pipe *np,
3119 struct torture_context *tctx,
3120 struct policy_handle *handle,
3121 uint16_t level,
3122 uint32_t fields_present,
3123 uint8_t password_expired,
3124 bool *matched_expected_error,
3125 bool use_setinfo2,
3126 const char *acct_name,
3127 char **password,
3128 struct cli_credentials *machine_creds,
3129 bool use_queryinfo2,
3130 NTTIME *pwdlastset,
3131 NTSTATUS expected_samlogon_result)
3133 const char *fields = NULL;
3134 bool ret = true;
3135 struct dcerpc_binding_handle *b = p->binding_handle;
3137 switch (level) {
3138 case 21:
3139 case 23:
3140 case 25:
3141 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3142 fields_present);
3143 break;
3144 default:
3145 break;
3148 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3149 "(password_expired: %d) %s\n",
3150 use_setinfo2 ? "2":"", level, password_expired,
3151 fields ? fields : "");
3153 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3154 fields_present,
3155 password,
3156 password_expired,
3157 use_setinfo2,
3158 matched_expected_error)) {
3159 ret = false;
3162 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3163 use_queryinfo2,
3164 pwdlastset)) {
3165 ret = false;
3168 if (*matched_expected_error == true) {
3169 return ret;
3172 if (!test_SamLogon_with_creds(tctx, np,
3173 machine_creds,
3174 acct_name,
3175 *password,
3176 expected_samlogon_result,
3177 false)) {
3178 ret = false;
3181 return ret;
3184 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3185 struct cli_credentials *credentials,
3186 struct dcerpc_pipe **p)
3188 struct dcerpc_binding *b;
3190 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3191 "failed to get rpc binding");
3193 /* We have to use schannel, otherwise the SamLogonEx fails
3194 * with INTERNAL_ERROR */
3196 b->flags &= ~DCERPC_AUTH_OPTIONS;
3197 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO;
3199 torture_assert_ntstatus_ok(tctx,
3200 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3201 credentials, tctx->ev, tctx->lp_ctx),
3202 "failed to bind to netlogon");
3204 return true;
3207 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3208 struct torture_context *tctx,
3209 uint32_t acct_flags,
3210 const char *acct_name,
3211 struct policy_handle *handle,
3212 char **password,
3213 struct cli_credentials *machine_credentials)
3215 int s = 0, q = 0, f = 0, l = 0, z = 0;
3216 bool ret = true;
3217 int delay = 50000;
3218 bool set_levels[] = { false, true };
3219 bool query_levels[] = { false, true };
3220 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3221 uint32_t nonzeros[] = { 1, 24 };
3222 uint32_t fields_present[] = {
3224 SAMR_FIELD_EXPIRED_FLAG,
3225 SAMR_FIELD_LAST_PWD_CHANGE,
3226 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3227 SAMR_FIELD_COMMENT,
3228 SAMR_FIELD_NT_PASSWORD_PRESENT,
3229 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3230 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3231 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3232 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3233 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3234 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3236 struct dcerpc_pipe *np = NULL;
3238 if (torture_setting_bool(tctx, "samba3", false) ||
3239 torture_setting_bool(tctx, "samba4", false)) {
3240 delay = 999999;
3241 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3242 delay);
3245 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3247 /* set to 1 to enable testing for all possible opcode
3248 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3249 combinations */
3250 #if 0
3251 #define TEST_ALL_LEVELS 1
3252 #define TEST_SET_LEVELS 1
3253 #define TEST_QUERY_LEVELS 1
3254 #endif
3255 #ifdef TEST_ALL_LEVELS
3256 for (l=0; l<ARRAY_SIZE(levels); l++) {
3257 #else
3258 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3259 #endif
3260 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3261 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3262 #ifdef TEST_SET_LEVELS
3263 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3264 #endif
3265 #ifdef TEST_QUERY_LEVELS
3266 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3267 #endif
3268 NTTIME pwdlastset_old = 0;
3269 NTTIME pwdlastset_new = 0;
3270 bool matched_expected_error = false;
3271 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3273 torture_comment(tctx, "------------------------------\n"
3274 "Testing pwdLastSet attribute for flags: 0x%08x "
3275 "(s: %d (l: %d), q: %d)\n",
3276 acct_flags, s, levels[l], q);
3278 switch (levels[l]) {
3279 case 21:
3280 case 23:
3281 case 25:
3282 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3283 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3284 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3286 break;
3290 /* set #1 */
3292 /* set a password and force password change (pwdlastset 0) by
3293 * setting the password expired flag to a non-0 value */
3295 if (!test_SetPassword_level(p, np, tctx, handle,
3296 levels[l],
3297 fields_present[f],
3298 nonzeros[z],
3299 &matched_expected_error,
3300 set_levels[s],
3301 acct_name,
3302 password,
3303 machine_credentials,
3304 query_levels[q],
3305 &pwdlastset_new,
3306 expected_samlogon_result)) {
3307 ret = false;
3310 if (matched_expected_error == true) {
3311 /* skipping on expected failure */
3312 continue;
3315 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3316 * set without the SAMR_FIELD_EXPIRED_FLAG */
3318 switch (levels[l]) {
3319 case 21:
3320 case 23:
3321 case 25:
3322 if ((pwdlastset_new != 0) &&
3323 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3324 torture_comment(tctx, "not considering a non-0 "
3325 "pwdLastSet as a an error as the "
3326 "SAMR_FIELD_EXPIRED_FLAG has not "
3327 "been set\n");
3328 break;
3330 break;
3331 default:
3332 if (pwdlastset_new != 0) {
3333 torture_warning(tctx, "pwdLastSet test failed: "
3334 "expected pwdLastSet 0 but got %llu\n",
3335 (unsigned long long) pwdlastset_old);
3336 ret = false;
3338 break;
3341 switch (levels[l]) {
3342 case 21:
3343 case 23:
3344 case 25:
3345 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3346 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3347 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3348 (pwdlastset_old >= pwdlastset_new)) {
3349 torture_warning(tctx, "pwdlastset not increasing\n");
3350 ret = false;
3352 break;
3355 pwdlastset_old = pwdlastset_new;
3357 usleep(delay);
3359 /* set #2 */
3361 /* set a password, pwdlastset needs to get updated (increased
3362 * value), password_expired value used here is 0 */
3364 if (!test_SetPassword_level(p, np, tctx, handle,
3365 levels[l],
3366 fields_present[f],
3368 &matched_expected_error,
3369 set_levels[s],
3370 acct_name,
3371 password,
3372 machine_credentials,
3373 query_levels[q],
3374 &pwdlastset_new,
3375 expected_samlogon_result)) {
3376 ret = false;
3379 /* when a password has been changed, pwdlastset must not be 0 afterwards
3380 * and must be larger then the old value */
3382 switch (levels[l]) {
3383 case 21:
3384 case 23:
3385 case 25:
3386 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3387 * password has been changed, old and new pwdlastset
3388 * need to be the same value */
3390 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3391 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3392 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3394 torture_assert_int_equal(tctx, pwdlastset_old,
3395 pwdlastset_new, "pwdlastset must be equal");
3396 break;
3398 break;
3399 default:
3400 if (pwdlastset_old >= pwdlastset_new) {
3401 torture_warning(tctx, "pwdLastSet test failed: "
3402 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3403 (unsigned long long) pwdlastset_old,
3404 (unsigned long long) pwdlastset_new);
3405 ret = false;
3407 if (pwdlastset_new == 0) {
3408 torture_warning(tctx, "pwdLastSet test failed: "
3409 "expected non-0 pwdlastset, got: %llu\n",
3410 (unsigned long long) pwdlastset_new);
3411 ret = false;
3413 break;
3416 switch (levels[l]) {
3417 case 21:
3418 case 23:
3419 case 25:
3420 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3421 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3422 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3423 (pwdlastset_old >= pwdlastset_new)) {
3424 torture_warning(tctx, "pwdlastset not increasing\n");
3425 ret = false;
3427 break;
3430 pwdlastset_old = pwdlastset_new;
3432 usleep(delay);
3434 /* set #2b */
3436 /* set a password, pwdlastset needs to get updated (increased
3437 * value), password_expired value used here is 0 */
3439 if (!test_SetPassword_level(p, np, tctx, handle,
3440 levels[l],
3441 fields_present[f],
3443 &matched_expected_error,
3444 set_levels[s],
3445 acct_name,
3446 password,
3447 machine_credentials,
3448 query_levels[q],
3449 &pwdlastset_new,
3450 expected_samlogon_result)) {
3451 ret = false;
3454 /* when a password has been changed, pwdlastset must not be 0 afterwards
3455 * and must be larger then the old value */
3457 switch (levels[l]) {
3458 case 21:
3459 case 23:
3460 case 25:
3462 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3463 * password has been changed, old and new pwdlastset
3464 * need to be the same value */
3466 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3467 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3468 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3470 torture_assert_int_equal(tctx, pwdlastset_old,
3471 pwdlastset_new, "pwdlastset must be equal");
3472 break;
3474 break;
3475 default:
3476 if (pwdlastset_old >= pwdlastset_new) {
3477 torture_warning(tctx, "pwdLastSet test failed: "
3478 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3479 (unsigned long long) pwdlastset_old,
3480 (unsigned long long) pwdlastset_new);
3481 ret = false;
3483 if (pwdlastset_new == 0) {
3484 torture_warning(tctx, "pwdLastSet test failed: "
3485 "expected non-0 pwdlastset, got: %llu\n",
3486 (unsigned long long) pwdlastset_new);
3487 ret = false;
3489 break;
3492 switch (levels[l]) {
3493 case 21:
3494 case 23:
3495 case 25:
3496 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3497 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3498 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3499 (pwdlastset_old >= pwdlastset_new)) {
3500 torture_warning(tctx, "pwdlastset not increasing\n");
3501 ret = false;
3503 break;
3506 pwdlastset_old = pwdlastset_new;
3508 usleep(delay);
3510 /* set #3 */
3512 /* set a password and force password change (pwdlastset 0) by
3513 * setting the password expired flag to a non-0 value */
3515 if (!test_SetPassword_level(p, np, tctx, handle,
3516 levels[l],
3517 fields_present[f],
3518 nonzeros[z],
3519 &matched_expected_error,
3520 set_levels[s],
3521 acct_name,
3522 password,
3523 machine_credentials,
3524 query_levels[q],
3525 &pwdlastset_new,
3526 expected_samlogon_result)) {
3527 ret = false;
3530 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3531 * set without the SAMR_FIELD_EXPIRED_FLAG */
3533 switch (levels[l]) {
3534 case 21:
3535 case 23:
3536 case 25:
3537 if ((pwdlastset_new != 0) &&
3538 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3539 torture_comment(tctx, "not considering a non-0 "
3540 "pwdLastSet as a an error as the "
3541 "SAMR_FIELD_EXPIRED_FLAG has not "
3542 "been set\n");
3543 break;
3546 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3547 * password has been changed, old and new pwdlastset
3548 * need to be the same value */
3550 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3551 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3552 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3554 torture_assert_int_equal(tctx, pwdlastset_old,
3555 pwdlastset_new, "pwdlastset must be equal");
3556 break;
3558 break;
3559 default:
3560 if (pwdlastset_new != 0) {
3561 torture_warning(tctx, "pwdLastSet test failed: "
3562 "expected pwdLastSet 0, got %llu\n",
3563 (unsigned long long) pwdlastset_old);
3564 ret = false;
3566 break;
3569 switch (levels[l]) {
3570 case 21:
3571 case 23:
3572 case 25:
3573 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3574 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3575 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3576 (pwdlastset_old >= pwdlastset_new)) {
3577 torture_warning(tctx, "pwdlastset not increasing\n");
3578 ret = false;
3580 break;
3583 /* if the level we are testing does not have a fields_present
3584 * field, skip all fields present tests by setting f to to
3585 * arraysize */
3586 switch (levels[l]) {
3587 case 18:
3588 case 24:
3589 case 26:
3590 f = ARRAY_SIZE(fields_present);
3591 break;
3594 #ifdef TEST_QUERY_LEVELS
3596 #endif
3597 #ifdef TEST_SET_LEVELS
3599 #endif
3600 } /* fields present */
3601 } /* nonzeros */
3602 } /* levels */
3604 #undef TEST_SET_LEVELS
3605 #undef TEST_QUERY_LEVELS
3607 talloc_free(np);
3609 return ret;
3612 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3613 struct torture_context *tctx,
3614 struct policy_handle *handle,
3615 uint32_t *badpwdcount)
3617 union samr_UserInfo *info;
3618 struct samr_QueryUserInfo r;
3620 r.in.user_handle = handle;
3621 r.in.level = 3;
3622 r.out.info = &info;
3624 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3626 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3627 "failed to query userinfo");
3628 torture_assert_ntstatus_ok(tctx, r.out.result,
3629 "failed to query userinfo");
3631 *badpwdcount = info->info3.bad_password_count;
3633 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3635 return true;
3638 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3639 struct torture_context *tctx,
3640 struct policy_handle *user_handle,
3641 uint32_t acct_flags)
3643 struct samr_SetUserInfo r;
3644 union samr_UserInfo user_info;
3646 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3648 user_info.info16.acct_flags = acct_flags;
3650 r.in.user_handle = user_handle;
3651 r.in.level = 16;
3652 r.in.info = &user_info;
3654 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3655 "failed to set account flags");
3656 torture_assert_ntstatus_ok(tctx, r.out.result,
3657 "failed to set account flags");
3659 return true;
3662 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3663 struct torture_context *tctx,
3664 struct policy_handle *user_handle,
3665 uint32_t acct_flags,
3666 char **password)
3668 struct dcerpc_binding_handle *b = p->binding_handle;
3670 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3671 "failed to set password");
3673 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3675 torture_assert(tctx,
3676 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3677 acct_flags & ~ACB_DISABLED),
3678 "failed to enable user");
3680 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3681 "failed to set password");
3683 return true;
3686 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3687 struct torture_context *tctx,
3688 struct policy_handle *domain_handle,
3689 enum samr_DomainInfoClass level,
3690 union samr_DomainInfo *info)
3692 struct samr_SetDomainInfo r;
3694 r.in.domain_handle = domain_handle;
3695 r.in.level = level;
3696 r.in.info = info;
3698 torture_assert_ntstatus_ok(tctx,
3699 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3700 "failed to set domain info");
3701 torture_assert_ntstatus_ok(tctx, r.out.result,
3702 "failed to set domain info");
3704 return true;
3707 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3708 struct torture_context *tctx,
3709 struct policy_handle *domain_handle,
3710 enum samr_DomainInfoClass level,
3711 union samr_DomainInfo *info,
3712 NTSTATUS expected)
3714 struct samr_SetDomainInfo r;
3716 r.in.domain_handle = domain_handle;
3717 r.in.level = level;
3718 r.in.info = info;
3720 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3721 "SetDomainInfo failed");
3722 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3724 return true;
3727 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3728 struct torture_context *tctx,
3729 struct policy_handle *domain_handle,
3730 enum samr_DomainInfoClass level,
3731 union samr_DomainInfo **q_info)
3733 struct samr_QueryDomainInfo2 r;
3735 r.in.domain_handle = domain_handle;
3736 r.in.level = level;
3737 r.out.info = q_info;
3739 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3740 "failed to query domain info");
3741 torture_assert_ntstatus_ok(tctx, r.out.result,
3742 "failed to query domain info");
3744 return true;
3747 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3748 struct dcerpc_pipe *np,
3749 struct torture_context *tctx,
3750 uint32_t acct_flags,
3751 const char *acct_name,
3752 struct policy_handle *domain_handle,
3753 struct policy_handle *user_handle,
3754 char **password,
3755 struct cli_credentials *machine_credentials,
3756 const char *comment,
3757 bool disable,
3758 bool interactive,
3759 NTSTATUS expected_success_status,
3760 struct samr_DomInfo1 *info1,
3761 struct samr_DomInfo12 *info12)
3763 union samr_DomainInfo info;
3764 char **passwords;
3765 int i;
3766 uint32_t badpwdcount, tmp;
3767 uint32_t password_history_length = 12;
3768 uint32_t lockout_threshold = 15;
3769 struct dcerpc_binding_handle *b = p->binding_handle;
3771 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3773 torture_assert(tctx, password_history_length < lockout_threshold,
3774 "password history length needs to be smaller than account lockout threshold for this test");
3777 /* set policies */
3779 info.info1 = *info1;
3780 info.info1.password_history_length = password_history_length;
3782 torture_assert(tctx,
3783 test_SetDomainInfo(b, tctx, domain_handle,
3784 DomainPasswordInformation, &info),
3785 "failed to set password history length");
3787 info.info12 = *info12;
3788 info.info12.lockout_threshold = lockout_threshold;
3790 torture_assert(tctx,
3791 test_SetDomainInfo(b, tctx, domain_handle,
3792 DomainLockoutInformation, &info),
3793 "failed to set lockout threshold");
3795 /* reset bad pwd count */
3797 torture_assert(tctx,
3798 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3801 /* enable or disable account */
3802 if (disable) {
3803 torture_assert(tctx,
3804 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3805 acct_flags | ACB_DISABLED),
3806 "failed to disable user");
3807 } else {
3808 torture_assert(tctx,
3809 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3810 acct_flags & ~ACB_DISABLED),
3811 "failed to enable user");
3815 /* setup password history */
3817 passwords = talloc_array(tctx, char *, password_history_length);
3819 for (i=0; i < password_history_length; i++) {
3821 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3822 "failed to set password");
3823 passwords[i] = talloc_strdup(tctx, *password);
3825 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3826 acct_name, passwords[i],
3827 expected_success_status, interactive)) {
3828 torture_fail(tctx, "failed to auth with latest password");
3831 torture_assert(tctx,
3832 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3834 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3838 /* test with wrong password */
3840 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3841 acct_name, "random_crap",
3842 NT_STATUS_WRONG_PASSWORD, interactive)) {
3843 torture_fail(tctx, "succeeded to authenticate with wrong password");
3846 torture_assert(tctx,
3847 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3849 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3852 /* test with latest good password */
3854 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3855 passwords[password_history_length-1],
3856 expected_success_status, interactive)) {
3857 torture_fail(tctx, "succeeded to authenticate with wrong password");
3860 torture_assert(tctx,
3861 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3863 if (disable) {
3864 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3865 } else {
3866 /* only enabled accounts get the bad pwd count reset upon
3867 * successful logon */
3868 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3871 tmp = badpwdcount;
3874 /* test password history */
3876 for (i=0; i < password_history_length; i++) {
3878 torture_comment(tctx, "Testing bad password count behavior with "
3879 "password #%d of #%d\n", i, password_history_length);
3881 /* - network samlogon will succeed auth and not
3882 * increase badpwdcount for 2 last entries
3883 * - interactive samlogon only for the last one */
3885 if (i == password_history_length - 1 ||
3886 (i == password_history_length - 2 && !interactive)) {
3888 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3889 acct_name, passwords[i],
3890 expected_success_status, interactive)) {
3891 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3894 torture_assert(tctx,
3895 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3897 if (disable) {
3898 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3899 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3900 } else {
3901 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3902 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3905 tmp = badpwdcount;
3907 continue;
3910 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3911 acct_name, passwords[i],
3912 NT_STATUS_WRONG_PASSWORD, interactive)) {
3913 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3916 torture_assert(tctx,
3917 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3919 /* - network samlogon will fail auth but not increase
3920 * badpwdcount for 3rd last entry
3921 * - interactive samlogon for 3rd and 2nd last entry */
3923 if (i == password_history_length - 3 ||
3924 (i == password_history_length - 2 && interactive)) {
3925 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3926 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3927 } else {
3928 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3929 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3932 tmp = badpwdcount;
3935 return true;
3938 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3939 struct torture_context *tctx,
3940 uint32_t acct_flags,
3941 const char *acct_name,
3942 struct policy_handle *domain_handle,
3943 struct policy_handle *user_handle,
3944 char **password,
3945 struct cli_credentials *machine_credentials)
3947 union samr_DomainInfo *q_info, s_info;
3948 struct samr_DomInfo1 info1, _info1;
3949 struct samr_DomInfo12 info12, _info12;
3950 bool ret = true;
3951 struct dcerpc_binding_handle *b = p->binding_handle;
3952 struct dcerpc_pipe *np;
3953 int i;
3955 struct {
3956 const char *comment;
3957 bool disabled;
3958 bool interactive;
3959 NTSTATUS expected_success_status;
3960 } creds[] = {
3962 .comment = "network logon (disabled account)",
3963 .disabled = true,
3964 .interactive = false,
3965 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3968 .comment = "network logon (enabled account)",
3969 .disabled = false,
3970 .interactive = false,
3971 .expected_success_status= NT_STATUS_OK
3974 .comment = "interactive logon (disabled account)",
3975 .disabled = true,
3976 .interactive = true,
3977 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3980 .comment = "interactive logon (enabled account)",
3981 .disabled = false,
3982 .interactive = true,
3983 .expected_success_status= NT_STATUS_OK
3987 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3989 /* backup old policies */
3991 torture_assert(tctx,
3992 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3993 DomainPasswordInformation, &q_info),
3994 "failed to query domain info level 1");
3996 info1 = q_info->info1;
3997 _info1 = info1;
3999 torture_assert(tctx,
4000 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4001 DomainLockoutInformation, &q_info),
4002 "failed to query domain info level 12");
4004 info12 = q_info->info12;
4005 _info12 = info12;
4007 /* run tests */
4009 for (i=0; i < ARRAY_SIZE(creds); i++) {
4011 /* skip trust tests for now */
4012 if (acct_flags & ACB_WSTRUST ||
4013 acct_flags & ACB_SVRTRUST ||
4014 acct_flags & ACB_DOMTRUST) {
4015 continue;
4018 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4019 domain_handle, user_handle, password,
4020 machine_credentials,
4021 creds[i].comment,
4022 creds[i].disabled,
4023 creds[i].interactive,
4024 creds[i].expected_success_status,
4025 &_info1, &_info12);
4026 if (!ret) {
4027 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4028 } else {
4029 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4033 /* restore policies */
4035 s_info.info1 = info1;
4037 torture_assert(tctx,
4038 test_SetDomainInfo(b, tctx, domain_handle,
4039 DomainPasswordInformation, &s_info),
4040 "failed to set password information");
4042 s_info.info12 = info12;
4044 torture_assert(tctx,
4045 test_SetDomainInfo(b, tctx, domain_handle,
4046 DomainLockoutInformation, &s_info),
4047 "failed to set lockout information");
4049 return ret;
4052 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
4053 struct torture_context *tctx,
4054 struct policy_handle *handle,
4055 uint32_t *acct_flags)
4057 union samr_UserInfo *info;
4058 struct samr_QueryUserInfo r;
4060 r.in.user_handle = handle;
4061 r.in.level = 16;
4062 r.out.info = &info;
4064 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4066 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4067 "failed to query userinfo");
4068 torture_assert_ntstatus_ok(tctx, r.out.result,
4069 "failed to query userinfo");
4071 *acct_flags = info->info16.acct_flags;
4073 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
4075 return true;
4078 static bool test_Password_lockout(struct dcerpc_pipe *p,
4079 struct dcerpc_pipe *np,
4080 struct torture_context *tctx,
4081 uint32_t acct_flags,
4082 const char *acct_name,
4083 struct policy_handle *domain_handle,
4084 struct policy_handle *user_handle,
4085 char **password,
4086 struct cli_credentials *machine_credentials,
4087 const char *comment,
4088 bool disable,
4089 bool interactive,
4090 NTSTATUS expected_success_status,
4091 struct samr_DomInfo1 *info1,
4092 struct samr_DomInfo12 *info12)
4094 union samr_DomainInfo info;
4095 uint32_t badpwdcount;
4096 uint32_t password_history_length = 1;
4097 uint64_t lockout_threshold = 1;
4098 uint32_t lockout_seconds = 5;
4099 uint64_t delta_time_factor = 10 * 1000 * 1000;
4100 struct dcerpc_binding_handle *b = p->binding_handle;
4102 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4104 /* set policies */
4106 info.info1 = *info1;
4108 torture_comment(tctx, "setting password history length.\n");
4109 info.info1.password_history_length = password_history_length;
4111 torture_assert(tctx,
4112 test_SetDomainInfo(b, tctx, domain_handle,
4113 DomainPasswordInformation, &info),
4114 "failed to set password history length");
4116 info.info12 = *info12;
4117 info.info12.lockout_threshold = lockout_threshold;
4119 /* set lockout duration < lockout window: should fail */
4120 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4121 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4123 torture_assert(tctx,
4124 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4125 DomainLockoutInformation, &info,
4126 NT_STATUS_INVALID_PARAMETER),
4127 "setting lockout duration < lockout window gave unexpected result");
4129 info.info12.lockout_duration = 0;
4130 info.info12.lockout_window = 0;
4132 torture_assert(tctx,
4133 test_SetDomainInfo(b, tctx, domain_handle,
4134 DomainLockoutInformation, &info),
4135 "failed to set lockout window and duration to 0");
4138 /* set lockout duration of 5 seconds */
4139 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4140 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4142 torture_assert(tctx,
4143 test_SetDomainInfo(b, tctx, domain_handle,
4144 DomainLockoutInformation, &info),
4145 "failed to set lockout window and duration to 5 seconds");
4147 /* reset bad pwd count */
4149 torture_assert(tctx,
4150 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4153 /* enable or disable account */
4155 if (disable) {
4156 torture_assert(tctx,
4157 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4158 acct_flags | ACB_DISABLED),
4159 "failed to disable user");
4160 } else {
4161 torture_assert(tctx,
4162 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4163 acct_flags & ~ACB_DISABLED),
4164 "failed to enable user");
4168 /* test logon with right password */
4170 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4171 acct_name, *password,
4172 expected_success_status, interactive)) {
4173 torture_fail(tctx, "failed to auth with latest password");
4176 torture_assert(tctx,
4177 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4178 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4181 /* test with wrong password ==> lockout */
4183 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4184 acct_name, "random_crap",
4185 NT_STATUS_WRONG_PASSWORD, interactive)) {
4186 torture_fail(tctx, "succeeded to authenticate with wrong password");
4189 torture_assert(tctx,
4190 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4191 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4193 torture_assert(tctx,
4194 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4195 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4196 "expected account to be locked");
4199 /* test with good password */
4201 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4202 *password,
4203 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4205 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4208 /* bad pwd count should not get updated */
4209 torture_assert(tctx,
4210 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4211 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4213 /* curiously, windows does _not_ set the autlock flag */
4214 torture_assert(tctx,
4215 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4216 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4217 "expected account to be locked");
4220 /* with bad password */
4222 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4223 acct_name, "random_crap2",
4224 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4226 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4229 /* bad pwd count should not get updated */
4230 torture_assert(tctx,
4231 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4232 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4234 /* curiously, windows does _not_ set the autlock flag */
4235 torture_assert(tctx,
4236 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4237 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4238 "expected account to be locked");
4241 /* let lockout duration expire ==> unlock */
4243 torture_comment(tctx, "let lockout duration expire...\n");
4244 sleep(lockout_seconds + 1);
4246 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4247 *password,
4248 expected_success_status, interactive))
4250 torture_fail(tctx, "failed to authenticate after lockout expired");
4253 torture_assert(tctx,
4254 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4255 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4256 "expected account not to be locked");
4258 return true;
4261 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4262 struct torture_context *tctx,
4263 uint32_t acct_flags,
4264 const char *acct_name,
4265 struct policy_handle *domain_handle,
4266 struct policy_handle *user_handle,
4267 char **password,
4268 struct cli_credentials *machine_credentials)
4270 union samr_DomainInfo *q_info, s_info;
4271 struct samr_DomInfo1 info1, _info1;
4272 struct samr_DomInfo12 info12, _info12;
4273 bool ret = true;
4274 struct dcerpc_binding_handle *b = p->binding_handle;
4275 struct dcerpc_pipe *np;
4276 int i;
4278 struct {
4279 const char *comment;
4280 bool disabled;
4281 bool interactive;
4282 NTSTATUS expected_success_status;
4283 } creds[] = {
4285 .comment = "network logon (disabled account)",
4286 .disabled = true,
4287 .interactive = false,
4288 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4291 .comment = "network logon (enabled account)",
4292 .disabled = false,
4293 .interactive = false,
4294 .expected_success_status= NT_STATUS_OK
4297 .comment = "interactive logon (disabled account)",
4298 .disabled = true,
4299 .interactive = true,
4300 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4303 .comment = "interactive logon (enabled account)",
4304 .disabled = false,
4305 .interactive = true,
4306 .expected_success_status= NT_STATUS_OK
4310 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4312 /* backup old policies */
4314 torture_assert(tctx,
4315 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4316 DomainPasswordInformation, &q_info),
4317 "failed to query domain info level 1");
4319 info1 = q_info->info1;
4320 _info1 = info1;
4322 torture_assert(tctx,
4323 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4324 DomainLockoutInformation, &q_info),
4325 "failed to query domain info level 12");
4327 info12 = q_info->info12;
4328 _info12 = info12;
4330 /* run tests */
4332 for (i=0; i < ARRAY_SIZE(creds); i++) {
4334 /* skip trust tests for now */
4335 if (acct_flags & ACB_WSTRUST ||
4336 acct_flags & ACB_SVRTRUST ||
4337 acct_flags & ACB_DOMTRUST) {
4338 continue;
4341 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4342 domain_handle, user_handle, password,
4343 machine_credentials,
4344 creds[i].comment,
4345 creds[i].disabled,
4346 creds[i].interactive,
4347 creds[i].expected_success_status,
4348 &_info1, &_info12);
4349 if (!ret) {
4350 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4351 } else {
4352 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4356 /* restore policies */
4358 s_info.info1 = info1;
4360 torture_assert(tctx,
4361 test_SetDomainInfo(b, tctx, domain_handle,
4362 DomainPasswordInformation, &s_info),
4363 "failed to set password information");
4365 s_info.info12 = info12;
4367 torture_assert(tctx,
4368 test_SetDomainInfo(b, tctx, domain_handle,
4369 DomainLockoutInformation, &s_info),
4370 "failed to set lockout information");
4372 return ret;
4375 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4376 struct dcerpc_pipe *lp,
4377 struct torture_context *tctx,
4378 struct policy_handle *domain_handle,
4379 struct policy_handle *lsa_handle,
4380 struct policy_handle *user_handle,
4381 const struct dom_sid *domain_sid,
4382 uint32_t rid,
4383 struct cli_credentials *machine_credentials)
4385 bool ret = true;
4386 struct dcerpc_binding_handle *b = p->binding_handle;
4387 struct dcerpc_binding_handle *lb = lp->binding_handle;
4389 struct policy_handle lsa_acct_handle;
4390 struct dom_sid *user_sid;
4392 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4395 struct lsa_EnumAccountRights r;
4396 struct lsa_RightSet rights;
4398 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4400 r.in.handle = lsa_handle;
4401 r.in.sid = user_sid;
4402 r.out.rights = &rights;
4404 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4405 "lsa_EnumAccountRights failed");
4406 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4407 "Expected enum rights for account to fail");
4411 struct lsa_RightSet rights;
4412 struct lsa_StringLarge names[2];
4413 struct lsa_AddAccountRights r;
4415 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4417 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4418 init_lsa_StringLarge(&names[1], NULL);
4420 rights.count = 1;
4421 rights.names = names;
4423 r.in.handle = lsa_handle;
4424 r.in.sid = user_sid;
4425 r.in.rights = &rights;
4427 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4428 "lsa_AddAccountRights failed");
4429 torture_assert_ntstatus_ok(tctx, r.out.result,
4430 "Failed to add privileges");
4434 struct lsa_EnumAccounts r;
4435 uint32_t resume_handle = 0;
4436 struct lsa_SidArray lsa_sid_array;
4437 int i;
4438 bool found_sid = false;
4440 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4442 r.in.handle = lsa_handle;
4443 r.in.num_entries = 0x1000;
4444 r.in.resume_handle = &resume_handle;
4445 r.out.sids = &lsa_sid_array;
4446 r.out.resume_handle = &resume_handle;
4448 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4449 "lsa_EnumAccounts failed");
4450 torture_assert_ntstatus_ok(tctx, r.out.result,
4451 "Failed to enum accounts");
4453 for (i=0; i < lsa_sid_array.num_sids; i++) {
4454 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4455 found_sid = true;
4459 torture_assert(tctx, found_sid,
4460 "failed to list privileged account");
4464 struct lsa_EnumAccountRights r;
4465 struct lsa_RightSet user_rights;
4467 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4469 r.in.handle = lsa_handle;
4470 r.in.sid = user_sid;
4471 r.out.rights = &user_rights;
4473 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4474 "lsa_EnumAccountRights failed");
4475 torture_assert_ntstatus_ok(tctx, r.out.result,
4476 "Failed to enum rights for account");
4478 if (user_rights.count < 1) {
4479 torture_warning(tctx, "failed to find newly added rights");
4480 return false;
4485 struct lsa_OpenAccount r;
4487 torture_comment(tctx, "Testing LSA OpenAccount\n");
4489 r.in.handle = lsa_handle;
4490 r.in.sid = user_sid;
4491 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4492 r.out.acct_handle = &lsa_acct_handle;
4494 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4495 "lsa_OpenAccount failed");
4496 torture_assert_ntstatus_ok(tctx, r.out.result,
4497 "Failed to open lsa account");
4501 struct lsa_GetSystemAccessAccount r;
4502 uint32_t access_mask;
4504 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4506 r.in.handle = &lsa_acct_handle;
4507 r.out.access_mask = &access_mask;
4509 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4510 "lsa_GetSystemAccessAccount failed");
4511 torture_assert_ntstatus_ok(tctx, r.out.result,
4512 "Failed to get lsa system access account");
4516 struct lsa_Close r;
4518 torture_comment(tctx, "Testing LSA Close\n");
4520 r.in.handle = &lsa_acct_handle;
4521 r.out.handle = &lsa_acct_handle;
4523 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4524 "lsa_Close failed");
4525 torture_assert_ntstatus_ok(tctx, r.out.result,
4526 "Failed to close lsa");
4530 struct samr_DeleteUser r;
4532 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4534 r.in.user_handle = user_handle;
4535 r.out.user_handle = user_handle;
4537 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4538 "DeleteUser failed");
4539 torture_assert_ntstatus_ok(tctx, r.out.result,
4540 "DeleteUser failed");
4544 struct lsa_EnumAccounts r;
4545 uint32_t resume_handle = 0;
4546 struct lsa_SidArray lsa_sid_array;
4547 int i;
4548 bool found_sid = false;
4550 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4552 r.in.handle = lsa_handle;
4553 r.in.num_entries = 0x1000;
4554 r.in.resume_handle = &resume_handle;
4555 r.out.sids = &lsa_sid_array;
4556 r.out.resume_handle = &resume_handle;
4558 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4559 "lsa_EnumAccounts failed");
4560 torture_assert_ntstatus_ok(tctx, r.out.result,
4561 "Failed to enum accounts");
4563 for (i=0; i < lsa_sid_array.num_sids; i++) {
4564 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4565 found_sid = true;
4569 torture_assert(tctx, found_sid,
4570 "failed to list privileged account");
4574 struct lsa_EnumAccountRights r;
4575 struct lsa_RightSet user_rights;
4577 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4579 r.in.handle = lsa_handle;
4580 r.in.sid = user_sid;
4581 r.out.rights = &user_rights;
4583 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4584 "lsa_EnumAccountRights failed");
4585 torture_assert_ntstatus_ok(tctx, r.out.result,
4586 "Failed to enum rights for account");
4588 if (user_rights.count < 1) {
4589 torture_warning(tctx, "failed to find newly added rights");
4590 return false;
4595 struct lsa_OpenAccount r;
4597 torture_comment(tctx, "Testing LSA OpenAccount\n");
4599 r.in.handle = lsa_handle;
4600 r.in.sid = user_sid;
4601 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4602 r.out.acct_handle = &lsa_acct_handle;
4604 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4605 "lsa_OpenAccount failed");
4606 torture_assert_ntstatus_ok(tctx, r.out.result,
4607 "Failed to open lsa account");
4611 struct lsa_GetSystemAccessAccount r;
4612 uint32_t access_mask;
4614 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4616 r.in.handle = &lsa_acct_handle;
4617 r.out.access_mask = &access_mask;
4619 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4620 "lsa_GetSystemAccessAccount failed");
4621 torture_assert_ntstatus_ok(tctx, r.out.result,
4622 "Failed to get lsa system access account");
4626 struct lsa_DeleteObject r;
4628 torture_comment(tctx, "Testing LSA DeleteObject\n");
4630 r.in.handle = &lsa_acct_handle;
4631 r.out.handle = &lsa_acct_handle;
4633 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4634 "lsa_DeleteObject failed");
4635 torture_assert_ntstatus_ok(tctx, r.out.result,
4636 "Failed to delete object");
4640 struct lsa_EnumAccounts r;
4641 uint32_t resume_handle = 0;
4642 struct lsa_SidArray lsa_sid_array;
4643 int i;
4644 bool found_sid = false;
4646 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4648 r.in.handle = lsa_handle;
4649 r.in.num_entries = 0x1000;
4650 r.in.resume_handle = &resume_handle;
4651 r.out.sids = &lsa_sid_array;
4652 r.out.resume_handle = &resume_handle;
4654 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4655 "lsa_EnumAccounts failed");
4656 torture_assert_ntstatus_ok(tctx, r.out.result,
4657 "Failed to enum accounts");
4659 for (i=0; i < lsa_sid_array.num_sids; i++) {
4660 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4661 found_sid = true;
4665 torture_assert(tctx, !found_sid,
4666 "should not have listed privileged account");
4670 struct lsa_EnumAccountRights r;
4671 struct lsa_RightSet user_rights;
4673 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4675 r.in.handle = lsa_handle;
4676 r.in.sid = user_sid;
4677 r.out.rights = &user_rights;
4679 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4680 "lsa_EnumAccountRights failed");
4681 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4682 "Failed to enum rights for account");
4685 return ret;
4688 static bool test_user_ops(struct dcerpc_pipe *p,
4689 struct torture_context *tctx,
4690 struct policy_handle *user_handle,
4691 struct policy_handle *domain_handle,
4692 const struct dom_sid *domain_sid,
4693 uint32_t base_acct_flags,
4694 const char *base_acct_name, enum torture_samr_choice which_ops,
4695 struct cli_credentials *machine_credentials)
4697 char *password = NULL;
4698 struct samr_QueryUserInfo q;
4699 union samr_UserInfo *info;
4700 NTSTATUS status;
4701 struct dcerpc_binding_handle *b = p->binding_handle;
4703 bool ret = true;
4704 int i;
4705 uint32_t rid;
4706 const uint32_t password_fields[] = {
4707 SAMR_FIELD_NT_PASSWORD_PRESENT,
4708 SAMR_FIELD_LM_PASSWORD_PRESENT,
4709 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4713 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4714 if (!NT_STATUS_IS_OK(status)) {
4715 ret = false;
4718 switch (which_ops) {
4719 case TORTURE_SAMR_USER_ATTRIBUTES:
4720 if (!test_QuerySecurity(b, tctx, user_handle)) {
4721 ret = false;
4724 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4725 ret = false;
4728 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4729 ret = false;
4732 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4733 base_acct_name)) {
4734 ret = false;
4737 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4738 ret = false;
4741 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4742 ret = false;
4745 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4746 ret = false;
4748 break;
4749 case TORTURE_SAMR_PASSWORDS:
4750 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4751 char simple_pass[9];
4752 char *v = generate_random_str(tctx, 1);
4754 ZERO_STRUCT(simple_pass);
4755 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4757 torture_comment(tctx, "Testing machine account password policy rules\n");
4759 /* Workstation trust accounts don't seem to need to honour password quality policy */
4760 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4761 ret = false;
4764 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4765 ret = false;
4768 /* reset again, to allow another 'user' password change */
4769 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4770 ret = false;
4773 /* Try a 'short' password */
4774 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4775 ret = false;
4778 /* Try a compleatly random password */
4779 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4780 ret = false;
4784 for (i = 0; password_fields[i]; i++) {
4785 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4786 ret = false;
4789 /* check it was set right */
4790 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4791 ret = false;
4795 for (i = 0; password_fields[i]; i++) {
4796 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4797 ret = false;
4800 /* check it was set right */
4801 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4802 ret = false;
4806 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4807 ret = false;
4810 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4811 ret = false;
4814 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4815 ret = false;
4818 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4819 ret = false;
4822 for (i = 0; password_fields[i]; i++) {
4824 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4825 /* we need to skip as that would break
4826 * the ChangePasswordUser3 verify */
4827 continue;
4830 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4831 ret = false;
4834 /* check it was set right */
4835 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4836 ret = false;
4840 q.in.user_handle = user_handle;
4841 q.in.level = 5;
4842 q.out.info = &info;
4844 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4845 "QueryUserInfo failed");
4846 if (!NT_STATUS_IS_OK(q.out.result)) {
4847 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4848 q.in.level, nt_errstr(q.out.result));
4849 ret = false;
4850 } else {
4851 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4852 if ((info->info5.acct_flags) != expected_flags) {
4853 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4854 info->info5.acct_flags,
4855 expected_flags);
4856 /* FIXME: GD */
4857 if (!torture_setting_bool(tctx, "samba3", false)) {
4858 ret = false;
4861 if (info->info5.rid != rid) {
4862 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4863 info->info5.rid, rid);
4868 break;
4870 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4872 /* test last password change timestamp behaviour */
4873 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4874 base_acct_name,
4875 user_handle, &password,
4876 machine_credentials)) {
4877 ret = false;
4880 if (ret == true) {
4881 torture_comment(tctx, "pwdLastSet test succeeded\n");
4882 } else {
4883 torture_warning(tctx, "pwdLastSet test failed\n");
4886 break;
4888 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4890 /* test bad pwd count change behaviour */
4891 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4892 base_acct_name,
4893 domain_handle,
4894 user_handle, &password,
4895 machine_credentials)) {
4896 ret = false;
4899 if (ret == true) {
4900 torture_comment(tctx, "badPwdCount test succeeded\n");
4901 } else {
4902 torture_warning(tctx, "badPwdCount test failed\n");
4905 break;
4907 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4909 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4910 base_acct_name,
4911 domain_handle,
4912 user_handle, &password,
4913 machine_credentials))
4915 ret = false;
4918 if (ret == true) {
4919 torture_comment(tctx, "lockout test succeeded\n");
4920 } else {
4921 torture_warning(tctx, "lockout test failed\n");
4924 break;
4927 case TORTURE_SAMR_USER_PRIVILEGES: {
4929 struct dcerpc_pipe *lp;
4930 struct policy_handle *lsa_handle;
4931 struct dcerpc_binding_handle *lb;
4933 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4934 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4935 lb = lp->binding_handle;
4937 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4938 ret = false;
4941 if (!test_DeleteUser_with_privs(p, lp, tctx,
4942 domain_handle, lsa_handle, user_handle,
4943 domain_sid, rid,
4944 machine_credentials)) {
4945 ret = false;
4948 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4949 ret = false;
4952 if (!ret) {
4953 torture_warning(tctx, "privileged user delete test failed\n");
4956 break;
4958 case TORTURE_SAMR_OTHER:
4959 case TORTURE_SAMR_MANY_ACCOUNTS:
4960 case TORTURE_SAMR_MANY_GROUPS:
4961 case TORTURE_SAMR_MANY_ALIASES:
4962 /* We just need the account to exist */
4963 break;
4965 return ret;
4968 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4969 struct torture_context *tctx,
4970 struct policy_handle *alias_handle,
4971 const struct dom_sid *domain_sid)
4973 bool ret = true;
4975 if (!torture_setting_bool(tctx, "samba3", false)) {
4976 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4977 ret = false;
4981 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4982 ret = false;
4985 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4986 ret = false;
4989 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
4990 ret = false;
4993 if (torture_setting_bool(tctx, "samba3", false) ||
4994 torture_setting_bool(tctx, "samba4", false)) {
4995 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4996 return ret;
4999 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
5000 ret = false;
5003 return ret;
5007 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
5008 struct torture_context *tctx,
5009 struct policy_handle *user_handle)
5011 struct samr_DeleteUser d;
5012 torture_comment(tctx, "Testing DeleteUser\n");
5014 d.in.user_handle = user_handle;
5015 d.out.user_handle = user_handle;
5017 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5018 "DeleteUser failed");
5019 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5021 return true;
5024 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5025 struct torture_context *tctx,
5026 struct policy_handle *handle, const char *name)
5028 NTSTATUS status;
5029 struct samr_DeleteUser d;
5030 struct policy_handle user_handle;
5031 uint32_t rid;
5033 status = test_LookupName(b, tctx, handle, name, &rid);
5034 if (!NT_STATUS_IS_OK(status)) {
5035 goto failed;
5038 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5039 if (!NT_STATUS_IS_OK(status)) {
5040 goto failed;
5043 d.in.user_handle = &user_handle;
5044 d.out.user_handle = &user_handle;
5045 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5046 "DeleteUser failed");
5047 if (!NT_STATUS_IS_OK(d.out.result)) {
5048 status = d.out.result;
5049 goto failed;
5052 return true;
5054 failed:
5055 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
5056 return false;
5060 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
5061 struct torture_context *tctx,
5062 struct policy_handle *handle, const char *name)
5064 NTSTATUS status;
5065 struct samr_OpenGroup r;
5066 struct samr_DeleteDomainGroup d;
5067 struct policy_handle group_handle;
5068 uint32_t rid;
5070 status = test_LookupName(b, tctx, handle, name, &rid);
5071 if (!NT_STATUS_IS_OK(status)) {
5072 goto failed;
5075 r.in.domain_handle = handle;
5076 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5077 r.in.rid = rid;
5078 r.out.group_handle = &group_handle;
5079 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5080 "OpenGroup failed");
5081 if (!NT_STATUS_IS_OK(r.out.result)) {
5082 status = r.out.result;
5083 goto failed;
5086 d.in.group_handle = &group_handle;
5087 d.out.group_handle = &group_handle;
5088 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
5089 "DeleteDomainGroup failed");
5090 if (!NT_STATUS_IS_OK(d.out.result)) {
5091 status = d.out.result;
5092 goto failed;
5095 return true;
5097 failed:
5098 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
5099 return false;
5103 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
5104 struct torture_context *tctx,
5105 struct policy_handle *domain_handle,
5106 const char *name)
5108 NTSTATUS status;
5109 struct samr_OpenAlias r;
5110 struct samr_DeleteDomAlias d;
5111 struct policy_handle alias_handle;
5112 uint32_t rid;
5114 torture_comment(tctx, "Testing DeleteAlias_byname\n");
5116 status = test_LookupName(b, tctx, domain_handle, name, &rid);
5117 if (!NT_STATUS_IS_OK(status)) {
5118 goto failed;
5121 r.in.domain_handle = domain_handle;
5122 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5123 r.in.rid = rid;
5124 r.out.alias_handle = &alias_handle;
5125 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5126 "OpenAlias failed");
5127 if (!NT_STATUS_IS_OK(r.out.result)) {
5128 status = r.out.result;
5129 goto failed;
5132 d.in.alias_handle = &alias_handle;
5133 d.out.alias_handle = &alias_handle;
5134 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5135 "DeleteDomAlias failed");
5136 if (!NT_STATUS_IS_OK(d.out.result)) {
5137 status = d.out.result;
5138 goto failed;
5141 return true;
5143 failed:
5144 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5145 return false;
5148 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5149 struct torture_context *tctx,
5150 struct policy_handle *alias_handle)
5152 struct samr_DeleteDomAlias d;
5153 bool ret = true;
5155 torture_comment(tctx, "Testing DeleteAlias\n");
5157 d.in.alias_handle = alias_handle;
5158 d.out.alias_handle = alias_handle;
5160 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5161 "DeleteDomAlias failed");
5162 if (!NT_STATUS_IS_OK(d.out.result)) {
5163 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5164 ret = false;
5167 return ret;
5170 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5171 struct torture_context *tctx,
5172 struct policy_handle *domain_handle,
5173 const char *alias_name,
5174 struct policy_handle *alias_handle,
5175 const struct dom_sid *domain_sid,
5176 bool test_alias)
5178 struct samr_CreateDomAlias r;
5179 struct lsa_String name;
5180 uint32_t rid;
5181 bool ret = true;
5183 init_lsa_String(&name, alias_name);
5184 r.in.domain_handle = domain_handle;
5185 r.in.alias_name = &name;
5186 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5187 r.out.alias_handle = alias_handle;
5188 r.out.rid = &rid;
5190 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5192 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5193 "CreateDomAlias failed");
5195 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5196 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5197 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5198 return true;
5199 } else {
5200 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5201 nt_errstr(r.out.result));
5202 return false;
5206 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5207 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5208 return false;
5210 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5211 "CreateDomAlias failed");
5214 if (!NT_STATUS_IS_OK(r.out.result)) {
5215 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5216 return false;
5219 if (!test_alias) {
5220 return ret;
5223 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5224 ret = false;
5227 return ret;
5230 static bool test_ChangePassword(struct dcerpc_pipe *p,
5231 struct torture_context *tctx,
5232 const char *acct_name,
5233 struct policy_handle *domain_handle, char **password)
5235 bool ret = true;
5236 struct dcerpc_binding_handle *b = p->binding_handle;
5238 if (!*password) {
5239 return false;
5242 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5243 ret = false;
5246 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5247 ret = false;
5250 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5251 ret = false;
5254 /* test what happens when setting the old password again */
5255 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5256 ret = false;
5260 char simple_pass[9];
5261 char *v = generate_random_str(tctx, 1);
5263 ZERO_STRUCT(simple_pass);
5264 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5266 /* test what happens when picking a simple password */
5267 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5268 ret = false;
5272 /* set samr_SetDomainInfo level 1 with min_length 5 */
5274 struct samr_QueryDomainInfo r;
5275 union samr_DomainInfo *info = NULL;
5276 struct samr_SetDomainInfo s;
5277 uint16_t len_old, len;
5278 uint32_t pwd_prop_old;
5279 int64_t min_pwd_age_old;
5281 len = 5;
5283 r.in.domain_handle = domain_handle;
5284 r.in.level = 1;
5285 r.out.info = &info;
5287 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5288 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5289 "QueryDomainInfo failed");
5290 if (!NT_STATUS_IS_OK(r.out.result)) {
5291 return false;
5294 s.in.domain_handle = domain_handle;
5295 s.in.level = 1;
5296 s.in.info = info;
5298 /* remember the old min length, so we can reset it */
5299 len_old = s.in.info->info1.min_password_length;
5300 s.in.info->info1.min_password_length = len;
5301 pwd_prop_old = s.in.info->info1.password_properties;
5302 /* turn off password complexity checks for this test */
5303 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5305 min_pwd_age_old = s.in.info->info1.min_password_age;
5306 s.in.info->info1.min_password_age = 0;
5308 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5309 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5310 "SetDomainInfo failed");
5311 if (!NT_STATUS_IS_OK(s.out.result)) {
5312 return false;
5315 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5317 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5318 ret = false;
5321 s.in.info->info1.min_password_length = len_old;
5322 s.in.info->info1.password_properties = pwd_prop_old;
5323 s.in.info->info1.min_password_age = min_pwd_age_old;
5325 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5326 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5327 "SetDomainInfo failed");
5328 if (!NT_STATUS_IS_OK(s.out.result)) {
5329 return false;
5335 struct samr_OpenUser r;
5336 struct samr_QueryUserInfo q;
5337 union samr_UserInfo *info;
5338 struct samr_LookupNames n;
5339 struct policy_handle user_handle;
5340 struct samr_Ids rids, types;
5342 n.in.domain_handle = domain_handle;
5343 n.in.num_names = 1;
5344 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5345 n.in.names[0].string = acct_name;
5346 n.out.rids = &rids;
5347 n.out.types = &types;
5349 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5350 "LookupNames failed");
5351 if (!NT_STATUS_IS_OK(n.out.result)) {
5352 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5353 return false;
5356 r.in.domain_handle = domain_handle;
5357 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5358 r.in.rid = n.out.rids->ids[0];
5359 r.out.user_handle = &user_handle;
5361 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5362 "OpenUser failed");
5363 if (!NT_STATUS_IS_OK(r.out.result)) {
5364 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5365 return false;
5368 q.in.user_handle = &user_handle;
5369 q.in.level = 5;
5370 q.out.info = &info;
5372 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5373 "QueryUserInfo failed");
5374 if (!NT_STATUS_IS_OK(q.out.result)) {
5375 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5376 return false;
5379 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5381 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5382 info->info5.last_password_change, true)) {
5383 ret = false;
5387 /* we change passwords twice - this has the effect of verifying
5388 they were changed correctly for the final call */
5389 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5390 ret = false;
5393 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5394 ret = false;
5397 return ret;
5400 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5401 struct policy_handle *domain_handle,
5402 const char *user_name,
5403 struct policy_handle *user_handle_out,
5404 struct dom_sid *domain_sid,
5405 enum torture_samr_choice which_ops,
5406 struct cli_credentials *machine_credentials,
5407 bool test_user)
5410 TALLOC_CTX *user_ctx;
5412 struct samr_CreateUser r;
5413 struct samr_QueryUserInfo q;
5414 union samr_UserInfo *info;
5415 struct samr_DeleteUser d;
5416 uint32_t rid;
5418 /* This call creates a 'normal' account - check that it really does */
5419 const uint32_t acct_flags = ACB_NORMAL;
5420 struct lsa_String name;
5421 bool ret = true;
5422 struct dcerpc_binding_handle *b = p->binding_handle;
5424 struct policy_handle user_handle;
5425 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5426 init_lsa_String(&name, user_name);
5428 r.in.domain_handle = domain_handle;
5429 r.in.account_name = &name;
5430 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5431 r.out.user_handle = &user_handle;
5432 r.out.rid = &rid;
5434 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5436 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5437 "CreateUser failed");
5439 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5440 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5441 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5442 return true;
5443 } else {
5444 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5445 nt_errstr(r.out.result));
5446 return false;
5450 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5451 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5452 talloc_free(user_ctx);
5453 return false;
5455 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5456 "CreateUser failed");
5459 if (!NT_STATUS_IS_OK(r.out.result)) {
5460 talloc_free(user_ctx);
5461 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5462 return false;
5465 if (!test_user) {
5466 if (user_handle_out) {
5467 *user_handle_out = user_handle;
5469 return ret;
5473 q.in.user_handle = &user_handle;
5474 q.in.level = 16;
5475 q.out.info = &info;
5477 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5478 "QueryUserInfo failed");
5479 if (!NT_STATUS_IS_OK(q.out.result)) {
5480 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5481 q.in.level, nt_errstr(q.out.result));
5482 ret = false;
5483 } else {
5484 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5485 torture_warning(tctx, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5486 info->info16.acct_flags,
5487 acct_flags);
5488 ret = false;
5492 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5493 domain_sid, acct_flags, name.string, which_ops,
5494 machine_credentials)) {
5495 ret = false;
5498 if (user_handle_out) {
5499 *user_handle_out = user_handle;
5500 } else {
5501 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5503 d.in.user_handle = &user_handle;
5504 d.out.user_handle = &user_handle;
5506 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5507 "DeleteUser failed");
5508 if (!NT_STATUS_IS_OK(d.out.result)) {
5509 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5510 ret = false;
5516 talloc_free(user_ctx);
5518 return ret;
5522 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5523 struct policy_handle *domain_handle,
5524 struct dom_sid *domain_sid,
5525 enum torture_samr_choice which_ops,
5526 struct cli_credentials *machine_credentials)
5528 struct samr_CreateUser2 r;
5529 struct samr_QueryUserInfo q;
5530 union samr_UserInfo *info;
5531 struct samr_DeleteUser d;
5532 struct policy_handle user_handle;
5533 uint32_t rid;
5534 struct lsa_String name;
5535 bool ret = true;
5536 int i;
5537 struct dcerpc_binding_handle *b = p->binding_handle;
5539 struct {
5540 uint32_t acct_flags;
5541 const char *account_name;
5542 NTSTATUS nt_status;
5543 } account_types[] = {
5544 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5545 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5546 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5547 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5548 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5549 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5550 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5551 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5552 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5553 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5554 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5555 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5556 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5557 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5558 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5561 for (i = 0; account_types[i].account_name; i++) {
5562 TALLOC_CTX *user_ctx;
5563 uint32_t acct_flags = account_types[i].acct_flags;
5564 uint32_t access_granted;
5565 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5566 init_lsa_String(&name, account_types[i].account_name);
5568 r.in.domain_handle = domain_handle;
5569 r.in.account_name = &name;
5570 r.in.acct_flags = acct_flags;
5571 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5572 r.out.user_handle = &user_handle;
5573 r.out.access_granted = &access_granted;
5574 r.out.rid = &rid;
5576 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5578 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5579 "CreateUser2 failed");
5581 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5582 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5583 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5584 continue;
5585 } else {
5586 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5587 nt_errstr(r.out.result));
5588 ret = false;
5589 continue;
5593 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5594 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5595 talloc_free(user_ctx);
5596 ret = false;
5597 continue;
5599 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5600 "CreateUser2 failed");
5603 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5604 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5605 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5606 ret = false;
5609 if (NT_STATUS_IS_OK(r.out.result)) {
5610 q.in.user_handle = &user_handle;
5611 q.in.level = 5;
5612 q.out.info = &info;
5614 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5615 "QueryUserInfo failed");
5616 if (!NT_STATUS_IS_OK(q.out.result)) {
5617 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5618 q.in.level, nt_errstr(q.out.result));
5619 ret = false;
5620 } else {
5621 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5622 if (acct_flags == ACB_NORMAL) {
5623 expected_flags |= ACB_PW_EXPIRED;
5625 if ((info->info5.acct_flags) != expected_flags) {
5626 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5627 info->info5.acct_flags,
5628 expected_flags);
5629 ret = false;
5631 switch (acct_flags) {
5632 case ACB_SVRTRUST:
5633 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5634 torture_warning(tctx, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5635 DOMAIN_RID_DCS, info->info5.primary_gid);
5636 ret = false;
5638 break;
5639 case ACB_WSTRUST:
5640 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5641 torture_warning(tctx, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5642 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5643 ret = false;
5645 break;
5646 case ACB_NORMAL:
5647 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5648 torture_warning(tctx, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5649 DOMAIN_RID_USERS, info->info5.primary_gid);
5650 ret = false;
5652 break;
5656 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5657 domain_sid, acct_flags, name.string, which_ops,
5658 machine_credentials)) {
5659 ret = false;
5662 if (!ndr_policy_handle_empty(&user_handle)) {
5663 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5665 d.in.user_handle = &user_handle;
5666 d.out.user_handle = &user_handle;
5668 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5669 "DeleteUser failed");
5670 if (!NT_STATUS_IS_OK(d.out.result)) {
5671 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5672 ret = false;
5676 talloc_free(user_ctx);
5679 return ret;
5682 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5683 struct torture_context *tctx,
5684 struct policy_handle *handle)
5686 struct samr_QueryAliasInfo r;
5687 union samr_AliasInfo *info;
5688 uint16_t levels[] = {1, 2, 3};
5689 int i;
5690 bool ret = true;
5692 for (i=0;i<ARRAY_SIZE(levels);i++) {
5693 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5695 r.in.alias_handle = handle;
5696 r.in.level = levels[i];
5697 r.out.info = &info;
5699 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5700 "QueryAliasInfo failed");
5701 if (!NT_STATUS_IS_OK(r.out.result)) {
5702 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5703 levels[i], nt_errstr(r.out.result));
5704 ret = false;
5708 return ret;
5711 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5712 struct torture_context *tctx,
5713 struct policy_handle *handle)
5715 struct samr_QueryGroupInfo r;
5716 union samr_GroupInfo *info;
5717 uint16_t levels[] = {1, 2, 3, 4, 5};
5718 int i;
5719 bool ret = true;
5721 for (i=0;i<ARRAY_SIZE(levels);i++) {
5722 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5724 r.in.group_handle = handle;
5725 r.in.level = levels[i];
5726 r.out.info = &info;
5728 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5729 "QueryGroupInfo failed");
5730 if (!NT_STATUS_IS_OK(r.out.result)) {
5731 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5732 levels[i], nt_errstr(r.out.result));
5733 ret = false;
5737 return ret;
5740 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5741 struct torture_context *tctx,
5742 struct policy_handle *handle)
5744 struct samr_QueryGroupMember r;
5745 struct samr_RidAttrArray *rids = NULL;
5746 bool ret = true;
5748 torture_comment(tctx, "Testing QueryGroupMember\n");
5750 r.in.group_handle = handle;
5751 r.out.rids = &rids;
5753 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5754 "QueryGroupMember failed");
5755 if (!NT_STATUS_IS_OK(r.out.result)) {
5756 torture_warning(tctx, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
5757 ret = false;
5760 return ret;
5764 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5765 struct torture_context *tctx,
5766 struct policy_handle *handle)
5768 struct samr_QueryGroupInfo r;
5769 union samr_GroupInfo *info;
5770 struct samr_SetGroupInfo s;
5771 uint16_t levels[] = {1, 2, 3, 4};
5772 uint16_t set_ok[] = {0, 1, 1, 1};
5773 int i;
5774 bool ret = true;
5776 for (i=0;i<ARRAY_SIZE(levels);i++) {
5777 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5779 r.in.group_handle = handle;
5780 r.in.level = levels[i];
5781 r.out.info = &info;
5783 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5784 "QueryGroupInfo failed");
5785 if (!NT_STATUS_IS_OK(r.out.result)) {
5786 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5787 levels[i], nt_errstr(r.out.result));
5788 ret = false;
5791 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5793 s.in.group_handle = handle;
5794 s.in.level = levels[i];
5795 s.in.info = *r.out.info;
5797 #if 0
5798 /* disabled this, as it changes the name only from the point of view of samr,
5799 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5800 the name is still reserved, so creating the old name fails, but deleting by the old name
5801 also fails */
5802 if (s.in.level == 2) {
5803 init_lsa_String(&s.in.info->string, "NewName");
5805 #endif
5807 if (s.in.level == 4) {
5808 init_lsa_String(&s.in.info->description, "test description");
5811 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5812 "SetGroupInfo failed");
5813 if (set_ok[i]) {
5814 if (!NT_STATUS_IS_OK(s.out.result)) {
5815 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5816 r.in.level, nt_errstr(s.out.result));
5817 ret = false;
5818 continue;
5820 } else {
5821 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5822 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5823 r.in.level, nt_errstr(s.out.result));
5824 ret = false;
5825 continue;
5830 return ret;
5833 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5834 struct torture_context *tctx,
5835 struct policy_handle *handle)
5837 struct samr_QueryUserInfo r;
5838 union samr_UserInfo *info;
5839 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5840 11, 12, 13, 14, 16, 17, 20, 21};
5841 int i;
5842 bool ret = true;
5844 for (i=0;i<ARRAY_SIZE(levels);i++) {
5845 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5847 r.in.user_handle = handle;
5848 r.in.level = levels[i];
5849 r.out.info = &info;
5851 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5852 "QueryUserInfo failed");
5853 if (!NT_STATUS_IS_OK(r.out.result)) {
5854 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5855 levels[i], nt_errstr(r.out.result));
5856 ret = false;
5860 return ret;
5863 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5864 struct torture_context *tctx,
5865 struct policy_handle *handle)
5867 struct samr_QueryUserInfo2 r;
5868 union samr_UserInfo *info;
5869 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5870 11, 12, 13, 14, 16, 17, 20, 21};
5871 int i;
5872 bool ret = true;
5874 for (i=0;i<ARRAY_SIZE(levels);i++) {
5875 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5877 r.in.user_handle = handle;
5878 r.in.level = levels[i];
5879 r.out.info = &info;
5881 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5882 "QueryUserInfo2 failed");
5883 if (!NT_STATUS_IS_OK(r.out.result)) {
5884 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5885 levels[i], nt_errstr(r.out.result));
5886 ret = false;
5890 return ret;
5893 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5894 struct torture_context *tctx,
5895 struct policy_handle *handle, uint32_t rid)
5897 struct samr_OpenUser r;
5898 struct policy_handle user_handle;
5899 bool ret = true;
5901 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5903 r.in.domain_handle = handle;
5904 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5905 r.in.rid = rid;
5906 r.out.user_handle = &user_handle;
5908 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5909 "OpenUser failed");
5910 if (!NT_STATUS_IS_OK(r.out.result)) {
5911 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5912 return false;
5915 if (!test_QuerySecurity(b, tctx, &user_handle)) {
5916 ret = false;
5919 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5920 ret = false;
5923 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5924 ret = false;
5927 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5928 ret = false;
5931 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5932 ret = false;
5935 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5936 ret = false;
5939 return ret;
5942 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5943 struct torture_context *tctx,
5944 struct policy_handle *handle, uint32_t rid)
5946 struct samr_OpenGroup r;
5947 struct policy_handle group_handle;
5948 bool ret = true;
5950 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5952 r.in.domain_handle = handle;
5953 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5954 r.in.rid = rid;
5955 r.out.group_handle = &group_handle;
5957 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5958 "OpenGroup failed");
5959 if (!NT_STATUS_IS_OK(r.out.result)) {
5960 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5961 return false;
5964 if (!torture_setting_bool(tctx, "samba3", false)) {
5965 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5966 ret = false;
5970 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5971 ret = false;
5974 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5975 ret = false;
5978 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5979 ret = false;
5982 return ret;
5985 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5986 struct torture_context *tctx,
5987 struct policy_handle *handle, uint32_t rid)
5989 struct samr_OpenAlias r;
5990 struct policy_handle alias_handle;
5991 bool ret = true;
5993 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5995 r.in.domain_handle = handle;
5996 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5997 r.in.rid = rid;
5998 r.out.alias_handle = &alias_handle;
6000 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
6001 "OpenAlias failed");
6002 if (!NT_STATUS_IS_OK(r.out.result)) {
6003 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6004 return false;
6007 if (!torture_setting_bool(tctx, "samba3", false)) {
6008 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
6009 ret = false;
6013 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6014 ret = false;
6017 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6018 ret = false;
6021 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6022 ret = false;
6025 return ret;
6028 static bool check_mask(struct dcerpc_binding_handle *b,
6029 struct torture_context *tctx,
6030 struct policy_handle *handle, uint32_t rid,
6031 uint32_t acct_flag_mask)
6033 struct samr_OpenUser r;
6034 struct samr_QueryUserInfo q;
6035 union samr_UserInfo *info;
6036 struct policy_handle user_handle;
6037 bool ret = true;
6039 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6041 r.in.domain_handle = handle;
6042 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6043 r.in.rid = rid;
6044 r.out.user_handle = &user_handle;
6046 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6047 "OpenUser failed");
6048 if (!NT_STATUS_IS_OK(r.out.result)) {
6049 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6050 return false;
6053 q.in.user_handle = &user_handle;
6054 q.in.level = 16;
6055 q.out.info = &info;
6057 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6058 "QueryUserInfo failed");
6059 if (!NT_STATUS_IS_OK(q.out.result)) {
6060 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
6061 nt_errstr(q.out.result));
6062 ret = false;
6063 } else {
6064 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
6065 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
6066 acct_flag_mask, info->info16.acct_flags, rid);
6067 ret = false;
6071 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6072 ret = false;
6075 return ret;
6078 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
6079 struct torture_context *tctx,
6080 struct policy_handle *handle)
6082 struct samr_EnumDomainUsers r;
6083 uint32_t mask, resume_handle=0;
6084 int i, mask_idx;
6085 bool ret = true;
6086 struct samr_LookupNames n;
6087 struct samr_LookupRids lr ;
6088 struct lsa_Strings names;
6089 struct samr_Ids rids, types;
6090 struct samr_SamArray *sam = NULL;
6091 uint32_t num_entries = 0;
6093 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
6094 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
6095 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
6096 ACB_PWNOEXP, 0};
6098 torture_comment(tctx, "Testing EnumDomainUsers\n");
6100 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
6101 r.in.domain_handle = handle;
6102 r.in.resume_handle = &resume_handle;
6103 r.in.acct_flags = mask = masks[mask_idx];
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_EnumDomainUsers_r(b, tctx, &r),
6110 "EnumDomainUsers failed");
6111 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6112 !NT_STATUS_IS_OK(r.out.result)) {
6113 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
6114 return false;
6117 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
6119 if (sam->count == 0) {
6120 continue;
6123 for (i=0;i<sam->count;i++) {
6124 if (mask) {
6125 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6126 ret = false;
6128 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6129 ret = false;
6134 torture_comment(tctx, "Testing LookupNames\n");
6135 n.in.domain_handle = handle;
6136 n.in.num_names = sam->count;
6137 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6138 n.out.rids = &rids;
6139 n.out.types = &types;
6140 for (i=0;i<sam->count;i++) {
6141 n.in.names[i].string = sam->entries[i].name.string;
6143 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6144 "LookupNames failed");
6145 if (!NT_STATUS_IS_OK(n.out.result)) {
6146 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6147 ret = false;
6151 torture_comment(tctx, "Testing LookupRids\n");
6152 lr.in.domain_handle = handle;
6153 lr.in.num_rids = sam->count;
6154 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6155 lr.out.names = &names;
6156 lr.out.types = &types;
6157 for (i=0;i<sam->count;i++) {
6158 lr.in.rids[i] = sam->entries[i].idx;
6160 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6161 "LookupRids failed");
6162 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6164 return ret;
6168 try blasting the server with a bunch of sync requests
6170 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6171 struct policy_handle *handle)
6173 struct samr_EnumDomainUsers r;
6174 uint32_t resume_handle=0;
6175 int i;
6176 #define ASYNC_COUNT 100
6177 struct tevent_req *req[ASYNC_COUNT];
6179 if (!torture_setting_bool(tctx, "dangerous", false)) {
6180 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6183 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6185 r.in.domain_handle = handle;
6186 r.in.resume_handle = &resume_handle;
6187 r.in.acct_flags = 0;
6188 r.in.max_size = (uint32_t)-1;
6189 r.out.resume_handle = &resume_handle;
6191 for (i=0;i<ASYNC_COUNT;i++) {
6192 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6195 for (i=0;i<ASYNC_COUNT;i++) {
6196 tevent_req_poll(req[i], tctx->ev);
6197 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6198 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6199 i, nt_errstr(r.out.result)));
6202 torture_comment(tctx, "%d async requests OK\n", i);
6204 return true;
6207 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6208 struct torture_context *tctx,
6209 struct policy_handle *handle)
6211 struct samr_EnumDomainGroups r;
6212 uint32_t resume_handle=0;
6213 struct samr_SamArray *sam = NULL;
6214 uint32_t num_entries = 0;
6215 int i;
6216 bool ret = true;
6217 bool universal_group_found = false;
6219 torture_comment(tctx, "Testing EnumDomainGroups\n");
6221 r.in.domain_handle = handle;
6222 r.in.resume_handle = &resume_handle;
6223 r.in.max_size = (uint32_t)-1;
6224 r.out.resume_handle = &resume_handle;
6225 r.out.num_entries = &num_entries;
6226 r.out.sam = &sam;
6228 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6229 "EnumDomainGroups failed");
6230 if (!NT_STATUS_IS_OK(r.out.result)) {
6231 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6232 return false;
6235 if (!sam) {
6236 return false;
6239 for (i=0;i<sam->count;i++) {
6240 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6241 ret = false;
6243 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6244 "Enterprise Admins") == 0)) {
6245 universal_group_found = true;
6249 /* when we are running this on s4 we should get back at least the
6250 * "Enterprise Admins" universal group. If we don't get a group entry
6251 * at all we probably are performing the test on the builtin domain.
6252 * So ignore this case. */
6253 if (torture_setting_bool(tctx, "samba4", false)) {
6254 if ((sam->count > 0) && (!universal_group_found)) {
6255 ret = false;
6259 return ret;
6262 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6263 struct torture_context *tctx,
6264 struct policy_handle *handle)
6266 struct samr_EnumDomainAliases r;
6267 uint32_t resume_handle=0;
6268 struct samr_SamArray *sam = NULL;
6269 uint32_t num_entries = 0;
6270 int i;
6271 bool ret = true;
6273 torture_comment(tctx, "Testing EnumDomainAliases\n");
6275 r.in.domain_handle = handle;
6276 r.in.resume_handle = &resume_handle;
6277 r.in.max_size = (uint32_t)-1;
6278 r.out.sam = &sam;
6279 r.out.num_entries = &num_entries;
6280 r.out.resume_handle = &resume_handle;
6282 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6283 "EnumDomainAliases failed");
6284 if (!NT_STATUS_IS_OK(r.out.result)) {
6285 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6286 return false;
6289 if (!sam) {
6290 return false;
6293 for (i=0;i<sam->count;i++) {
6294 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6295 ret = false;
6299 return ret;
6302 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6303 struct torture_context *tctx,
6304 struct policy_handle *handle)
6306 struct samr_GetDisplayEnumerationIndex r;
6307 bool ret = true;
6308 uint16_t levels[] = {1, 2, 3, 4, 5};
6309 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6310 struct lsa_String name;
6311 uint32_t idx = 0;
6312 int i;
6314 for (i=0;i<ARRAY_SIZE(levels);i++) {
6315 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6317 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6319 r.in.domain_handle = handle;
6320 r.in.level = levels[i];
6321 r.in.name = &name;
6322 r.out.idx = &idx;
6324 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6325 "GetDisplayEnumerationIndex failed");
6327 if (ok_lvl[i] &&
6328 !NT_STATUS_IS_OK(r.out.result) &&
6329 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6330 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6331 levels[i], nt_errstr(r.out.result));
6332 ret = false;
6335 init_lsa_String(&name, "zzzzzzzz");
6337 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6338 "GetDisplayEnumerationIndex failed");
6340 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6341 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6342 levels[i], nt_errstr(r.out.result));
6343 ret = false;
6347 return ret;
6350 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6351 struct torture_context *tctx,
6352 struct policy_handle *handle)
6354 struct samr_GetDisplayEnumerationIndex2 r;
6355 bool ret = true;
6356 uint16_t levels[] = {1, 2, 3, 4, 5};
6357 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6358 struct lsa_String name;
6359 uint32_t idx = 0;
6360 int i;
6362 for (i=0;i<ARRAY_SIZE(levels);i++) {
6363 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6365 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6367 r.in.domain_handle = handle;
6368 r.in.level = levels[i];
6369 r.in.name = &name;
6370 r.out.idx = &idx;
6372 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6373 "GetDisplayEnumerationIndex2 failed");
6374 if (ok_lvl[i] &&
6375 !NT_STATUS_IS_OK(r.out.result) &&
6376 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6377 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6378 levels[i], nt_errstr(r.out.result));
6379 ret = false;
6382 init_lsa_String(&name, "zzzzzzzz");
6384 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6385 "GetDisplayEnumerationIndex2 failed");
6386 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6387 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6388 levels[i], nt_errstr(r.out.result));
6389 ret = false;
6393 return ret;
6396 #define STRING_EQUAL_QUERY(s1, s2, user) \
6397 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6398 /* odd, but valid */ \
6399 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6400 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6401 #s1, user.string, s1.string, s2.string, __location__); \
6402 ret = false; \
6404 #define INT_EQUAL_QUERY(s1, s2, user) \
6405 if (s1 != s2) { \
6406 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6407 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6408 ret = false; \
6411 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6412 struct torture_context *tctx,
6413 struct samr_QueryDisplayInfo *querydisplayinfo,
6414 bool *seen_testuser)
6416 struct samr_OpenUser r;
6417 struct samr_QueryUserInfo q;
6418 union samr_UserInfo *info;
6419 struct policy_handle user_handle;
6420 int i, ret = true;
6421 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6422 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6423 for (i = 0; ; i++) {
6424 switch (querydisplayinfo->in.level) {
6425 case 1:
6426 if (i >= querydisplayinfo->out.info->info1.count) {
6427 return ret;
6429 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6430 break;
6431 case 2:
6432 if (i >= querydisplayinfo->out.info->info2.count) {
6433 return ret;
6435 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6436 break;
6437 case 3:
6438 /* Groups */
6439 case 4:
6440 case 5:
6441 /* Not interested in validating just the account name */
6442 return true;
6445 r.out.user_handle = &user_handle;
6447 switch (querydisplayinfo->in.level) {
6448 case 1:
6449 case 2:
6450 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6451 "OpenUser failed");
6452 if (!NT_STATUS_IS_OK(r.out.result)) {
6453 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6454 return false;
6458 q.in.user_handle = &user_handle;
6459 q.in.level = 21;
6460 q.out.info = &info;
6461 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6462 "QueryUserInfo failed");
6463 if (!NT_STATUS_IS_OK(r.out.result)) {
6464 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6465 return false;
6468 switch (querydisplayinfo->in.level) {
6469 case 1:
6470 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6471 *seen_testuser = true;
6473 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6474 info->info21.full_name, info->info21.account_name);
6475 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6476 info->info21.account_name, info->info21.account_name);
6477 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6478 info->info21.description, info->info21.account_name);
6479 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6480 info->info21.rid, info->info21.account_name);
6481 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6482 info->info21.acct_flags, info->info21.account_name);
6484 break;
6485 case 2:
6486 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6487 info->info21.account_name, info->info21.account_name);
6488 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6489 info->info21.description, info->info21.account_name);
6490 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6491 info->info21.rid, info->info21.account_name);
6492 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6493 info->info21.acct_flags, info->info21.account_name);
6495 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6496 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6497 info->info21.account_name.string);
6500 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6501 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6502 info->info21.account_name.string,
6503 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6504 info->info21.acct_flags);
6505 return false;
6508 break;
6511 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6512 return false;
6515 return ret;
6518 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6519 struct torture_context *tctx,
6520 struct policy_handle *handle)
6522 struct samr_QueryDisplayInfo r;
6523 struct samr_QueryDomainInfo dom_info;
6524 union samr_DomainInfo *info = NULL;
6525 bool ret = true;
6526 uint16_t levels[] = {1, 2, 3, 4, 5};
6527 int i;
6528 bool seen_testuser = false;
6529 uint32_t total_size;
6530 uint32_t returned_size;
6531 union samr_DispInfo disp_info;
6534 for (i=0;i<ARRAY_SIZE(levels);i++) {
6535 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6537 r.in.start_idx = 0;
6538 r.out.result = STATUS_MORE_ENTRIES;
6539 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6540 r.in.domain_handle = handle;
6541 r.in.level = levels[i];
6542 r.in.max_entries = 2;
6543 r.in.buf_size = (uint32_t)-1;
6544 r.out.total_size = &total_size;
6545 r.out.returned_size = &returned_size;
6546 r.out.info = &disp_info;
6548 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6549 "QueryDisplayInfo failed");
6550 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6551 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6552 levels[i], nt_errstr(r.out.result));
6553 ret = false;
6555 switch (r.in.level) {
6556 case 1:
6557 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6558 ret = false;
6560 r.in.start_idx += r.out.info->info1.count;
6561 break;
6562 case 2:
6563 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6564 ret = false;
6566 r.in.start_idx += r.out.info->info2.count;
6567 break;
6568 case 3:
6569 r.in.start_idx += r.out.info->info3.count;
6570 break;
6571 case 4:
6572 r.in.start_idx += r.out.info->info4.count;
6573 break;
6574 case 5:
6575 r.in.start_idx += r.out.info->info5.count;
6576 break;
6579 dom_info.in.domain_handle = handle;
6580 dom_info.in.level = 2;
6581 dom_info.out.info = &info;
6583 /* Check number of users returned is correct */
6584 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6585 "QueryDomainInfo failed");
6586 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6587 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6588 r.in.level, nt_errstr(dom_info.out.result));
6589 ret = false;
6590 break;
6592 switch (r.in.level) {
6593 case 1:
6594 case 4:
6595 if (info->general.num_users < r.in.start_idx) {
6596 /* On AD deployments this numbers don't match
6597 * since QueryDisplayInfo returns universal and
6598 * global groups, QueryDomainInfo only global
6599 * ones. */
6600 if (torture_setting_bool(tctx, "samba3", false)) {
6601 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6602 r.in.start_idx, info->general.num_groups,
6603 info->general.domain_name.string);
6604 ret = false;
6607 if (!seen_testuser) {
6608 struct policy_handle user_handle;
6609 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6610 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6611 info->general.domain_name.string);
6612 ret = false;
6613 test_samr_handle_Close(b, tctx, &user_handle);
6616 break;
6617 case 3:
6618 case 5:
6619 if (info->general.num_groups != r.in.start_idx) {
6620 /* On AD deployments this numbers don't match
6621 * since QueryDisplayInfo returns universal and
6622 * global groups, QueryDomainInfo only global
6623 * ones. */
6624 if (torture_setting_bool(tctx, "samba3", false)) {
6625 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6626 r.in.start_idx, info->general.num_groups,
6627 info->general.domain_name.string);
6628 ret = false;
6632 break;
6637 return ret;
6640 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6641 struct torture_context *tctx,
6642 struct policy_handle *handle)
6644 struct samr_QueryDisplayInfo2 r;
6645 bool ret = true;
6646 uint16_t levels[] = {1, 2, 3, 4, 5};
6647 int i;
6648 uint32_t total_size;
6649 uint32_t returned_size;
6650 union samr_DispInfo info;
6652 for (i=0;i<ARRAY_SIZE(levels);i++) {
6653 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6655 r.in.domain_handle = handle;
6656 r.in.level = levels[i];
6657 r.in.start_idx = 0;
6658 r.in.max_entries = 1000;
6659 r.in.buf_size = (uint32_t)-1;
6660 r.out.total_size = &total_size;
6661 r.out.returned_size = &returned_size;
6662 r.out.info = &info;
6664 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6665 "QueryDisplayInfo2 failed");
6666 if (!NT_STATUS_IS_OK(r.out.result)) {
6667 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6668 levels[i], nt_errstr(r.out.result));
6669 ret = false;
6673 return ret;
6676 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6677 struct torture_context *tctx,
6678 struct policy_handle *handle)
6680 struct samr_QueryDisplayInfo3 r;
6681 bool ret = true;
6682 uint16_t levels[] = {1, 2, 3, 4, 5};
6683 int i;
6684 uint32_t total_size;
6685 uint32_t returned_size;
6686 union samr_DispInfo info;
6688 for (i=0;i<ARRAY_SIZE(levels);i++) {
6689 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6691 r.in.domain_handle = handle;
6692 r.in.level = levels[i];
6693 r.in.start_idx = 0;
6694 r.in.max_entries = 1000;
6695 r.in.buf_size = (uint32_t)-1;
6696 r.out.total_size = &total_size;
6697 r.out.returned_size = &returned_size;
6698 r.out.info = &info;
6700 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6701 "QueryDisplayInfo3 failed");
6702 if (!NT_STATUS_IS_OK(r.out.result)) {
6703 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6704 levels[i], nt_errstr(r.out.result));
6705 ret = false;
6709 return ret;
6713 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6714 struct torture_context *tctx,
6715 struct policy_handle *handle)
6717 struct samr_QueryDisplayInfo r;
6718 bool ret = true;
6719 uint32_t total_size;
6720 uint32_t returned_size;
6721 union samr_DispInfo info;
6723 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6725 r.in.domain_handle = handle;
6726 r.in.level = 1;
6727 r.in.start_idx = 0;
6728 r.in.max_entries = 1;
6729 r.in.buf_size = (uint32_t)-1;
6730 r.out.total_size = &total_size;
6731 r.out.returned_size = &returned_size;
6732 r.out.info = &info;
6734 do {
6735 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6736 "QueryDisplayInfo failed");
6737 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6738 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6739 torture_warning(tctx, "expected idx %d but got %d\n",
6740 r.in.start_idx + 1,
6741 r.out.info->info1.entries[0].idx);
6742 break;
6745 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6746 !NT_STATUS_IS_OK(r.out.result)) {
6747 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6748 r.in.level, nt_errstr(r.out.result));
6749 ret = false;
6750 break;
6752 r.in.start_idx++;
6753 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6754 NT_STATUS_IS_OK(r.out.result)) &&
6755 *r.out.returned_size != 0);
6757 return ret;
6760 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6761 struct torture_context *tctx,
6762 struct policy_handle *handle)
6764 struct samr_QueryDomainInfo r;
6765 union samr_DomainInfo *info = NULL;
6766 struct samr_SetDomainInfo s;
6767 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6768 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6769 int i;
6770 bool ret = true;
6771 struct dcerpc_binding_handle *b = p->binding_handle;
6772 const char *domain_comment = talloc_asprintf(tctx,
6773 "Tortured by Samba4 RPC-SAMR: %s",
6774 timestring(tctx, time(NULL)));
6776 s.in.domain_handle = handle;
6777 s.in.level = 4;
6778 s.in.info = talloc(tctx, union samr_DomainInfo);
6780 s.in.info->oem.oem_information.string = domain_comment;
6781 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6782 "SetDomainInfo failed");
6783 if (!NT_STATUS_IS_OK(s.out.result)) {
6784 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6785 s.in.level, nt_errstr(s.out.result));
6786 return false;
6789 for (i=0;i<ARRAY_SIZE(levels);i++) {
6790 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6792 r.in.domain_handle = handle;
6793 r.in.level = levels[i];
6794 r.out.info = &info;
6796 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6797 "QueryDomainInfo failed");
6798 if (!NT_STATUS_IS_OK(r.out.result)) {
6799 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6800 r.in.level, nt_errstr(r.out.result));
6801 ret = false;
6802 continue;
6805 switch (levels[i]) {
6806 case 2:
6807 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6808 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6809 levels[i], info->general.oem_information.string, domain_comment);
6810 if (!torture_setting_bool(tctx, "samba3", false)) {
6811 ret = false;
6814 if (!info->general.primary.string) {
6815 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6816 levels[i]);
6817 ret = false;
6818 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6819 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6820 if (torture_setting_bool(tctx, "samba3", false)) {
6821 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6822 levels[i], info->general.primary.string, dcerpc_server_name(p));
6826 break;
6827 case 4:
6828 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6829 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6830 levels[i], info->oem.oem_information.string, domain_comment);
6831 if (!torture_setting_bool(tctx, "samba3", false)) {
6832 ret = false;
6835 break;
6836 case 6:
6837 if (!info->info6.primary.string) {
6838 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6839 levels[i]);
6840 ret = false;
6842 break;
6843 case 11:
6844 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6845 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6846 levels[i], info->general2.general.oem_information.string, domain_comment);
6847 if (!torture_setting_bool(tctx, "samba3", false)) {
6848 ret = false;
6851 break;
6854 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6856 s.in.domain_handle = handle;
6857 s.in.level = levels[i];
6858 s.in.info = info;
6860 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6861 "SetDomainInfo failed");
6862 if (set_ok[i]) {
6863 if (!NT_STATUS_IS_OK(s.out.result)) {
6864 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6865 r.in.level, nt_errstr(s.out.result));
6866 ret = false;
6867 continue;
6869 } else {
6870 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6871 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6872 r.in.level, nt_errstr(s.out.result));
6873 ret = false;
6874 continue;
6878 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6879 "QueryDomainInfo failed");
6880 if (!NT_STATUS_IS_OK(r.out.result)) {
6881 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6882 r.in.level, nt_errstr(r.out.result));
6883 ret = false;
6884 continue;
6888 return ret;
6892 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6893 struct torture_context *tctx,
6894 struct policy_handle *handle)
6896 struct samr_QueryDomainInfo2 r;
6897 union samr_DomainInfo *info = NULL;
6898 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6899 int i;
6900 bool ret = true;
6902 for (i=0;i<ARRAY_SIZE(levels);i++) {
6903 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6905 r.in.domain_handle = handle;
6906 r.in.level = levels[i];
6907 r.out.info = &info;
6909 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6910 "QueryDomainInfo2 failed");
6911 if (!NT_STATUS_IS_OK(r.out.result)) {
6912 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6913 r.in.level, nt_errstr(r.out.result));
6914 ret = false;
6915 continue;
6919 return true;
6922 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6923 set of group names. */
6924 static bool test_GroupList(struct dcerpc_binding_handle *b,
6925 struct torture_context *tctx,
6926 struct dom_sid *domain_sid,
6927 struct policy_handle *handle)
6929 struct samr_EnumDomainGroups q1;
6930 struct samr_QueryDisplayInfo q2;
6931 NTSTATUS status;
6932 uint32_t resume_handle=0;
6933 struct samr_SamArray *sam = NULL;
6934 uint32_t num_entries = 0;
6935 int i;
6936 bool ret = true;
6937 uint32_t total_size;
6938 uint32_t returned_size;
6939 union samr_DispInfo info;
6941 int num_names = 0;
6942 const char **names = NULL;
6944 bool builtin_domain = dom_sid_compare(domain_sid,
6945 &global_sid_Builtin) == 0;
6947 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6949 q1.in.domain_handle = handle;
6950 q1.in.resume_handle = &resume_handle;
6951 q1.in.max_size = 5;
6952 q1.out.resume_handle = &resume_handle;
6953 q1.out.num_entries = &num_entries;
6954 q1.out.sam = &sam;
6956 status = STATUS_MORE_ENTRIES;
6957 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6958 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6959 "EnumDomainGroups failed");
6960 status = q1.out.result;
6962 if (!NT_STATUS_IS_OK(status) &&
6963 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6964 break;
6966 for (i=0; i<*q1.out.num_entries; i++) {
6967 add_string_to_array(tctx,
6968 sam->entries[i].name.string,
6969 &names, &num_names);
6973 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6975 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6977 if (builtin_domain) {
6978 torture_assert(tctx, num_names == 0,
6979 "EnumDomainGroups shouldn't return any group in the builtin domain!");
6982 q2.in.domain_handle = handle;
6983 q2.in.level = 5;
6984 q2.in.start_idx = 0;
6985 q2.in.max_entries = 5;
6986 q2.in.buf_size = (uint32_t)-1;
6987 q2.out.total_size = &total_size;
6988 q2.out.returned_size = &returned_size;
6989 q2.out.info = &info;
6991 status = STATUS_MORE_ENTRIES;
6992 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6993 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
6994 "QueryDisplayInfo failed");
6995 status = q2.out.result;
6996 if (!NT_STATUS_IS_OK(status) &&
6997 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6998 break;
7000 for (i=0; i<q2.out.info->info5.count; i++) {
7001 int j;
7002 const char *name = q2.out.info->info5.entries[i].account_name.string;
7003 bool found = false;
7004 for (j=0; j<num_names; j++) {
7005 if (names[j] == NULL)
7006 continue;
7007 if (strequal(names[j], name)) {
7008 names[j] = NULL;
7009 found = true;
7010 break;
7014 if ((!found) && (!builtin_domain)) {
7015 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7016 name);
7017 ret = false;
7020 q2.in.start_idx += q2.out.info->info5.count;
7023 if (!NT_STATUS_IS_OK(status)) {
7024 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
7025 nt_errstr(status));
7026 ret = false;
7029 if (builtin_domain) {
7030 torture_assert(tctx, q2.in.start_idx != 0,
7031 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
7034 for (i=0; i<num_names; i++) {
7035 if (names[i] != NULL) {
7036 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
7037 names[i]);
7038 ret = false;
7042 return ret;
7045 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
7046 struct torture_context *tctx,
7047 struct policy_handle *group_handle)
7049 struct samr_DeleteDomainGroup d;
7051 torture_comment(tctx, "Testing DeleteDomainGroup\n");
7053 d.in.group_handle = group_handle;
7054 d.out.group_handle = group_handle;
7056 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
7057 "DeleteDomainGroup failed");
7058 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
7060 return true;
7063 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
7064 struct torture_context *tctx,
7065 struct policy_handle *domain_handle)
7067 struct samr_TestPrivateFunctionsDomain r;
7068 bool ret = true;
7070 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
7072 r.in.domain_handle = domain_handle;
7074 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
7075 "TestPrivateFunctionsDomain failed");
7076 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
7078 return ret;
7081 static bool test_RidToSid(struct dcerpc_binding_handle *b,
7082 struct torture_context *tctx,
7083 struct dom_sid *domain_sid,
7084 struct policy_handle *domain_handle)
7086 struct samr_RidToSid r;
7087 bool ret = true;
7088 struct dom_sid *calc_sid, *out_sid;
7089 int rids[] = { 0, 42, 512, 10200 };
7090 int i;
7092 for (i=0;i<ARRAY_SIZE(rids);i++) {
7093 torture_comment(tctx, "Testing RidToSid\n");
7095 calc_sid = dom_sid_dup(tctx, domain_sid);
7096 r.in.domain_handle = domain_handle;
7097 r.in.rid = rids[i];
7098 r.out.sid = &out_sid;
7100 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
7101 "RidToSid failed");
7102 if (!NT_STATUS_IS_OK(r.out.result)) {
7103 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
7104 ret = false;
7105 } else {
7106 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
7108 if (!dom_sid_equal(calc_sid, out_sid)) {
7109 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
7110 dom_sid_string(tctx, out_sid),
7111 dom_sid_string(tctx, calc_sid));
7112 ret = false;
7117 return ret;
7120 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
7121 struct torture_context *tctx,
7122 struct policy_handle *domain_handle)
7124 struct samr_GetBootKeyInformation r;
7125 bool ret = true;
7126 uint32_t unknown = 0;
7127 NTSTATUS status;
7129 torture_comment(tctx, "Testing GetBootKeyInformation\n");
7131 r.in.domain_handle = domain_handle;
7132 r.out.unknown = &unknown;
7134 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
7135 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
7136 status = r.out.result;
7138 if (!NT_STATUS_IS_OK(status)) {
7139 /* w2k3 seems to fail this sometimes and pass it sometimes */
7140 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7143 return ret;
7146 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7147 struct torture_context *tctx,
7148 struct policy_handle *domain_handle,
7149 struct policy_handle *group_handle)
7151 NTSTATUS status;
7152 struct samr_AddGroupMember r;
7153 struct samr_DeleteGroupMember d;
7154 struct samr_QueryGroupMember q;
7155 struct samr_RidAttrArray *rids = NULL;
7156 struct samr_SetMemberAttributesOfGroup s;
7157 uint32_t rid;
7158 bool found_member = false;
7159 int i;
7161 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7162 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7164 r.in.group_handle = group_handle;
7165 r.in.rid = rid;
7166 r.in.flags = 0; /* ??? */
7168 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7170 d.in.group_handle = group_handle;
7171 d.in.rid = rid;
7173 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7174 "DeleteGroupMember failed");
7175 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7177 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7178 "AddGroupMember failed");
7179 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7181 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7182 "AddGroupMember failed");
7183 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7185 if (torture_setting_bool(tctx, "samba4", false) ||
7186 torture_setting_bool(tctx, "samba3", false)) {
7187 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7188 } else {
7189 /* this one is quite strange. I am using random inputs in the
7190 hope of triggering an error that might give us a clue */
7192 s.in.group_handle = group_handle;
7193 s.in.unknown1 = random();
7194 s.in.unknown2 = random();
7196 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7197 "SetMemberAttributesOfGroup failed");
7198 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7201 q.in.group_handle = group_handle;
7202 q.out.rids = &rids;
7204 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7205 "QueryGroupMember failed");
7206 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7207 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7209 for (i=0; i < rids->count; i++) {
7210 if (rids->rids[i] == rid) {
7211 found_member = true;
7215 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7217 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7218 "DeleteGroupMember failed");
7219 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7221 rids = NULL;
7222 found_member = false;
7224 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7225 "QueryGroupMember failed");
7226 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7227 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7229 for (i=0; i < rids->count; i++) {
7230 if (rids->rids[i] == rid) {
7231 found_member = true;
7235 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7237 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7238 "AddGroupMember failed");
7239 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7241 return true;
7245 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7246 struct torture_context *tctx,
7247 struct policy_handle *domain_handle,
7248 const char *group_name,
7249 struct policy_handle *group_handle,
7250 struct dom_sid *domain_sid,
7251 bool test_group)
7253 struct samr_CreateDomainGroup r;
7254 uint32_t rid;
7255 struct lsa_String name;
7256 bool ret = true;
7258 init_lsa_String(&name, group_name);
7260 r.in.domain_handle = domain_handle;
7261 r.in.name = &name;
7262 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7263 r.out.group_handle = group_handle;
7264 r.out.rid = &rid;
7266 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7268 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7269 "CreateDomainGroup failed");
7271 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7272 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7273 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7274 return true;
7275 } else {
7276 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7277 nt_errstr(r.out.result));
7278 return false;
7282 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7283 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7284 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7285 nt_errstr(r.out.result));
7286 return false;
7288 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7289 "CreateDomainGroup failed");
7291 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7292 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7294 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7295 nt_errstr(r.out.result));
7296 return false;
7298 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7299 "CreateDomainGroup failed");
7301 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7303 if (!test_group) {
7304 return ret;
7307 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7308 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7309 ret = false;
7312 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7313 ret = false;
7316 return ret;
7321 its not totally clear what this does. It seems to accept any sid you like.
7323 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7324 struct torture_context *tctx,
7325 struct policy_handle *domain_handle)
7327 struct samr_RemoveMemberFromForeignDomain r;
7329 r.in.domain_handle = domain_handle;
7330 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7332 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7333 "RemoveMemberFromForeignDomain failed");
7334 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7336 return true;
7339 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7340 struct torture_context *tctx,
7341 struct policy_handle *domain_handle,
7342 uint32_t *total_num_entries_p)
7344 NTSTATUS status;
7345 struct samr_EnumDomainUsers r;
7346 uint32_t resume_handle = 0;
7347 uint32_t num_entries = 0;
7348 uint32_t total_num_entries = 0;
7349 struct samr_SamArray *sam;
7351 r.in.domain_handle = domain_handle;
7352 r.in.acct_flags = 0;
7353 r.in.max_size = (uint32_t)-1;
7354 r.in.resume_handle = &resume_handle;
7356 r.out.sam = &sam;
7357 r.out.num_entries = &num_entries;
7358 r.out.resume_handle = &resume_handle;
7360 torture_comment(tctx, "Testing EnumDomainUsers\n");
7362 do {
7363 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7364 "EnumDomainUsers failed");
7365 if (NT_STATUS_IS_ERR(r.out.result)) {
7366 torture_assert_ntstatus_ok(tctx, r.out.result,
7367 "failed to enumerate users");
7369 status = r.out.result;
7371 total_num_entries += num_entries;
7372 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7374 if (total_num_entries_p) {
7375 *total_num_entries_p = total_num_entries;
7378 return true;
7381 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7382 struct torture_context *tctx,
7383 struct policy_handle *domain_handle,
7384 uint32_t *total_num_entries_p)
7386 NTSTATUS status;
7387 struct samr_EnumDomainGroups r;
7388 uint32_t resume_handle = 0;
7389 uint32_t num_entries = 0;
7390 uint32_t total_num_entries = 0;
7391 struct samr_SamArray *sam;
7393 r.in.domain_handle = domain_handle;
7394 r.in.max_size = (uint32_t)-1;
7395 r.in.resume_handle = &resume_handle;
7397 r.out.sam = &sam;
7398 r.out.num_entries = &num_entries;
7399 r.out.resume_handle = &resume_handle;
7401 torture_comment(tctx, "Testing EnumDomainGroups\n");
7403 do {
7404 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7405 "EnumDomainGroups failed");
7406 if (NT_STATUS_IS_ERR(r.out.result)) {
7407 torture_assert_ntstatus_ok(tctx, r.out.result,
7408 "failed to enumerate groups");
7410 status = r.out.result;
7412 total_num_entries += num_entries;
7413 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7415 if (total_num_entries_p) {
7416 *total_num_entries_p = total_num_entries;
7419 return true;
7422 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7423 struct torture_context *tctx,
7424 struct policy_handle *domain_handle,
7425 uint32_t *total_num_entries_p)
7427 NTSTATUS status;
7428 struct samr_EnumDomainAliases r;
7429 uint32_t resume_handle = 0;
7430 uint32_t num_entries = 0;
7431 uint32_t total_num_entries = 0;
7432 struct samr_SamArray *sam;
7434 r.in.domain_handle = domain_handle;
7435 r.in.max_size = (uint32_t)-1;
7436 r.in.resume_handle = &resume_handle;
7438 r.out.sam = &sam;
7439 r.out.num_entries = &num_entries;
7440 r.out.resume_handle = &resume_handle;
7442 torture_comment(tctx, "Testing EnumDomainAliases\n");
7444 do {
7445 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7446 "EnumDomainAliases failed");
7447 if (NT_STATUS_IS_ERR(r.out.result)) {
7448 torture_assert_ntstatus_ok(tctx, r.out.result,
7449 "failed to enumerate aliases");
7451 status = r.out.result;
7453 total_num_entries += num_entries;
7454 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7456 if (total_num_entries_p) {
7457 *total_num_entries_p = total_num_entries;
7460 return true;
7463 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7464 struct torture_context *tctx,
7465 struct policy_handle *handle,
7466 uint16_t level,
7467 uint32_t *total_num_entries_p)
7469 NTSTATUS status;
7470 struct samr_QueryDisplayInfo r;
7471 uint32_t total_num_entries = 0;
7473 r.in.domain_handle = handle;
7474 r.in.level = level;
7475 r.in.start_idx = 0;
7476 r.in.max_entries = (uint32_t)-1;
7477 r.in.buf_size = (uint32_t)-1;
7479 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7481 do {
7482 uint32_t total_size;
7483 uint32_t returned_size;
7484 union samr_DispInfo info;
7486 r.out.total_size = &total_size;
7487 r.out.returned_size = &returned_size;
7488 r.out.info = &info;
7490 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7491 "failed to query displayinfo");
7492 if (NT_STATUS_IS_ERR(r.out.result)) {
7493 torture_assert_ntstatus_ok(tctx, r.out.result,
7494 "failed to query displayinfo");
7496 status = r.out.result;
7498 if (*r.out.returned_size == 0) {
7499 break;
7502 switch (r.in.level) {
7503 case 1:
7504 total_num_entries += info.info1.count;
7505 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7506 break;
7507 case 2:
7508 total_num_entries += info.info2.count;
7509 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7510 break;
7511 case 3:
7512 total_num_entries += info.info3.count;
7513 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7514 break;
7515 case 4:
7516 total_num_entries += info.info4.count;
7517 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7518 break;
7519 case 5:
7520 total_num_entries += info.info5.count;
7521 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7522 break;
7523 default:
7524 return false;
7527 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7529 if (total_num_entries_p) {
7530 *total_num_entries_p = total_num_entries;
7533 return true;
7536 static bool test_ManyObjects(struct dcerpc_pipe *p,
7537 struct torture_context *tctx,
7538 struct policy_handle *domain_handle,
7539 struct dom_sid *domain_sid,
7540 struct torture_samr_context *ctx)
7542 uint32_t num_total = ctx->num_objects_large_dc;
7543 uint32_t num_enum = 0;
7544 uint32_t num_disp = 0;
7545 uint32_t num_created = 0;
7546 uint32_t num_anounced = 0;
7547 uint32_t i;
7548 struct dcerpc_binding_handle *b = p->binding_handle;
7550 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7552 /* query */
7555 struct samr_QueryDomainInfo2 r;
7556 union samr_DomainInfo *info;
7557 r.in.domain_handle = domain_handle;
7558 r.in.level = 2;
7559 r.out.info = &info;
7561 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7562 "QueryDomainInfo2 failed");
7563 torture_assert_ntstatus_ok(tctx, r.out.result,
7564 "failed to query domain info");
7566 switch (ctx->choice) {
7567 case TORTURE_SAMR_MANY_ACCOUNTS:
7568 num_anounced = info->general.num_users;
7569 break;
7570 case TORTURE_SAMR_MANY_GROUPS:
7571 num_anounced = info->general.num_groups;
7572 break;
7573 case TORTURE_SAMR_MANY_ALIASES:
7574 num_anounced = info->general.num_aliases;
7575 break;
7576 default:
7577 return false;
7581 /* create */
7583 for (i=0; i < num_total; i++) {
7585 const char *name = NULL;
7587 switch (ctx->choice) {
7588 case TORTURE_SAMR_MANY_ACCOUNTS:
7589 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7590 torture_assert(tctx,
7591 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
7592 "failed to create user");
7593 break;
7594 case TORTURE_SAMR_MANY_GROUPS:
7595 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7596 torture_assert(tctx,
7597 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7598 "failed to create group");
7599 break;
7600 case TORTURE_SAMR_MANY_ALIASES:
7601 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7602 torture_assert(tctx,
7603 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
7604 "failed to create alias");
7605 break;
7606 default:
7607 return false;
7609 if (!ndr_policy_handle_empty(&handles[i])) {
7610 num_created++;
7614 /* enum */
7616 switch (ctx->choice) {
7617 case TORTURE_SAMR_MANY_ACCOUNTS:
7618 torture_assert(tctx,
7619 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
7620 "failed to enum users");
7621 break;
7622 case TORTURE_SAMR_MANY_GROUPS:
7623 torture_assert(tctx,
7624 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
7625 "failed to enum groups");
7626 break;
7627 case TORTURE_SAMR_MANY_ALIASES:
7628 torture_assert(tctx,
7629 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
7630 "failed to enum aliases");
7631 break;
7632 default:
7633 return false;
7636 /* dispinfo */
7638 switch (ctx->choice) {
7639 case TORTURE_SAMR_MANY_ACCOUNTS:
7640 torture_assert(tctx,
7641 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
7642 "failed to query display info");
7643 break;
7644 case TORTURE_SAMR_MANY_GROUPS:
7645 torture_assert(tctx,
7646 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
7647 "failed to query display info");
7648 break;
7649 case TORTURE_SAMR_MANY_ALIASES:
7650 /* no aliases in dispinfo */
7651 break;
7652 default:
7653 return false;
7656 /* close or delete */
7658 for (i=0; i < num_total; i++) {
7660 if (ndr_policy_handle_empty(&handles[i])) {
7661 continue;
7664 if (torture_setting_bool(tctx, "samba3", false)) {
7665 torture_assert(tctx,
7666 test_samr_handle_Close(b, tctx, &handles[i]),
7667 "failed to close handle");
7668 } else {
7669 switch (ctx->choice) {
7670 case TORTURE_SAMR_MANY_ACCOUNTS:
7671 torture_assert(tctx,
7672 test_DeleteUser(b, tctx, &handles[i]),
7673 "failed to delete user");
7674 break;
7675 case TORTURE_SAMR_MANY_GROUPS:
7676 torture_assert(tctx,
7677 test_DeleteDomainGroup(b, tctx, &handles[i]),
7678 "failed to delete group");
7679 break;
7680 case TORTURE_SAMR_MANY_ALIASES:
7681 torture_assert(tctx,
7682 test_DeleteAlias(b, tctx, &handles[i]),
7683 "failed to delete alias");
7684 break;
7685 default:
7686 return false;
7691 talloc_free(handles);
7693 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7694 torture_comment(tctx,
7695 "unexpected number of results (%u) returned in enum call, expected %u\n",
7696 num_enum, num_anounced + num_created);
7698 torture_comment(tctx,
7699 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7700 num_disp, num_anounced + num_created);
7703 return true;
7706 static bool test_Connect(struct dcerpc_binding_handle *b,
7707 struct torture_context *tctx,
7708 struct policy_handle *handle);
7710 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7711 struct torture_samr_context *ctx, struct dom_sid *sid)
7713 struct samr_OpenDomain r;
7714 struct policy_handle domain_handle;
7715 struct policy_handle alias_handle;
7716 struct policy_handle user_handle;
7717 struct policy_handle group_handle;
7718 bool ret = true;
7719 struct dcerpc_binding_handle *b = p->binding_handle;
7721 ZERO_STRUCT(alias_handle);
7722 ZERO_STRUCT(user_handle);
7723 ZERO_STRUCT(group_handle);
7724 ZERO_STRUCT(domain_handle);
7726 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7728 r.in.connect_handle = &ctx->handle;
7729 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7730 r.in.sid = sid;
7731 r.out.domain_handle = &domain_handle;
7733 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7734 "OpenDomain failed");
7735 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7737 /* run the domain tests with the main handle closed - this tests
7738 the servers reference counting */
7739 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7741 switch (ctx->choice) {
7742 case TORTURE_SAMR_PASSWORDS:
7743 case TORTURE_SAMR_USER_PRIVILEGES:
7744 if (!torture_setting_bool(tctx, "samba3", false)) {
7745 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7747 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7748 if (!ret) {
7749 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7751 break;
7752 case TORTURE_SAMR_USER_ATTRIBUTES:
7753 if (!torture_setting_bool(tctx, "samba3", false)) {
7754 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7756 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7757 /* This test needs 'complex' users to validate */
7758 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7759 if (!ret) {
7760 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7762 break;
7763 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7764 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7765 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7766 if (!torture_setting_bool(tctx, "samba3", false)) {
7767 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7769 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7770 if (!ret) {
7771 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7773 break;
7774 case TORTURE_SAMR_MANY_ACCOUNTS:
7775 case TORTURE_SAMR_MANY_GROUPS:
7776 case TORTURE_SAMR_MANY_ALIASES:
7777 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7778 if (!ret) {
7779 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7781 break;
7782 case TORTURE_SAMR_OTHER:
7783 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7784 if (!ret) {
7785 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7787 if (!torture_setting_bool(tctx, "samba3", false)) {
7788 ret &= test_QuerySecurity(b, tctx, &domain_handle);
7790 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7791 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7792 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7793 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7794 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7795 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7796 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7797 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7798 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7799 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7800 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7801 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7802 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7804 if (torture_setting_bool(tctx, "samba4", false)) {
7805 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7806 } else {
7807 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7808 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7810 ret &= test_GroupList(b, tctx, sid, &domain_handle);
7811 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7812 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7813 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7814 if (!ret) {
7815 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7817 break;
7820 if (!ndr_policy_handle_empty(&user_handle) &&
7821 !test_DeleteUser(b, tctx, &user_handle)) {
7822 ret = false;
7825 if (!ndr_policy_handle_empty(&alias_handle) &&
7826 !test_DeleteAlias(b, tctx, &alias_handle)) {
7827 ret = false;
7830 if (!ndr_policy_handle_empty(&group_handle) &&
7831 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7832 ret = false;
7835 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7837 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7838 /* reconnect the main handle */
7840 if (!ret) {
7841 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7844 return ret;
7847 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7848 struct torture_samr_context *ctx, const char *domain)
7850 struct samr_LookupDomain r;
7851 struct dom_sid2 *sid = NULL;
7852 struct lsa_String n1;
7853 struct lsa_String n2;
7854 bool ret = true;
7855 struct dcerpc_binding_handle *b = p->binding_handle;
7857 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7859 /* check for correct error codes */
7860 r.in.connect_handle = &ctx->handle;
7861 r.in.domain_name = &n2;
7862 r.out.sid = &sid;
7863 n2.string = NULL;
7865 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7866 "LookupDomain failed");
7867 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7869 init_lsa_String(&n2, "xxNODOMAINxx");
7871 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7872 "LookupDomain failed");
7873 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7875 r.in.connect_handle = &ctx->handle;
7877 init_lsa_String(&n1, domain);
7878 r.in.domain_name = &n1;
7880 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7881 "LookupDomain failed");
7882 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7884 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7885 ret = false;
7888 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7889 ret = false;
7892 return ret;
7896 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7897 struct torture_samr_context *ctx)
7899 struct samr_EnumDomains r;
7900 uint32_t resume_handle = 0;
7901 uint32_t num_entries = 0;
7902 struct samr_SamArray *sam = NULL;
7903 int i;
7904 bool ret = true;
7905 struct dcerpc_binding_handle *b = p->binding_handle;
7907 r.in.connect_handle = &ctx->handle;
7908 r.in.resume_handle = &resume_handle;
7909 r.in.buf_size = (uint32_t)-1;
7910 r.out.resume_handle = &resume_handle;
7911 r.out.num_entries = &num_entries;
7912 r.out.sam = &sam;
7914 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7915 "EnumDomains failed");
7916 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7918 if (!*r.out.sam) {
7919 return false;
7922 for (i=0;i<sam->count;i++) {
7923 if (!test_LookupDomain(p, tctx, ctx,
7924 sam->entries[i].name.string)) {
7925 ret = false;
7929 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7930 "EnumDomains failed");
7931 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7933 return ret;
7937 static bool test_Connect(struct dcerpc_binding_handle *b,
7938 struct torture_context *tctx,
7939 struct policy_handle *handle)
7941 struct samr_Connect r;
7942 struct samr_Connect2 r2;
7943 struct samr_Connect3 r3;
7944 struct samr_Connect4 r4;
7945 struct samr_Connect5 r5;
7946 union samr_ConnectInfo info;
7947 struct policy_handle h;
7948 uint32_t level_out = 0;
7949 bool ret = true, got_handle = false;
7951 torture_comment(tctx, "Testing samr_Connect\n");
7953 r.in.system_name = NULL;
7954 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7955 r.out.connect_handle = &h;
7957 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7958 "Connect failed");
7959 if (!NT_STATUS_IS_OK(r.out.result)) {
7960 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7961 ret = false;
7962 } else {
7963 got_handle = true;
7964 *handle = h;
7967 torture_comment(tctx, "Testing samr_Connect2\n");
7969 r2.in.system_name = NULL;
7970 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7971 r2.out.connect_handle = &h;
7973 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7974 "Connect2 failed");
7975 if (!NT_STATUS_IS_OK(r2.out.result)) {
7976 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7977 ret = false;
7978 } else {
7979 if (got_handle) {
7980 test_samr_handle_Close(b, tctx, handle);
7982 got_handle = true;
7983 *handle = h;
7986 torture_comment(tctx, "Testing samr_Connect3\n");
7988 r3.in.system_name = NULL;
7989 r3.in.unknown = 0;
7990 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7991 r3.out.connect_handle = &h;
7993 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
7994 "Connect3 failed");
7995 if (!NT_STATUS_IS_OK(r3.out.result)) {
7996 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
7997 ret = false;
7998 } else {
7999 if (got_handle) {
8000 test_samr_handle_Close(b, tctx, handle);
8002 got_handle = true;
8003 *handle = h;
8006 torture_comment(tctx, "Testing samr_Connect4\n");
8008 r4.in.system_name = "";
8009 r4.in.client_version = 0;
8010 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8011 r4.out.connect_handle = &h;
8013 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8014 "Connect4 failed");
8015 if (!NT_STATUS_IS_OK(r4.out.result)) {
8016 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8017 ret = false;
8018 } else {
8019 if (got_handle) {
8020 test_samr_handle_Close(b, tctx, handle);
8022 got_handle = true;
8023 *handle = h;
8026 torture_comment(tctx, "Testing samr_Connect5\n");
8028 info.info1.client_version = 0;
8029 info.info1.unknown2 = 0;
8031 r5.in.system_name = "";
8032 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8033 r5.in.level_in = 1;
8034 r5.out.level_out = &level_out;
8035 r5.in.info_in = &info;
8036 r5.out.info_out = &info;
8037 r5.out.connect_handle = &h;
8039 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
8040 "Connect5 failed");
8041 if (!NT_STATUS_IS_OK(r5.out.result)) {
8042 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
8043 ret = false;
8044 } else {
8045 if (got_handle) {
8046 test_samr_handle_Close(b, tctx, handle);
8048 got_handle = true;
8049 *handle = h;
8052 return ret;
8056 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
8057 struct torture_context *tctx)
8059 struct samr_ValidatePassword r;
8060 union samr_ValidatePasswordReq req;
8061 union samr_ValidatePasswordRep *repp = NULL;
8062 NTSTATUS status;
8063 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
8064 int i;
8065 struct dcerpc_binding_handle *b = p->binding_handle;
8067 torture_comment(tctx, "Testing samr_ValidatePassword\n");
8069 ZERO_STRUCT(r);
8070 r.in.level = NetValidatePasswordReset;
8071 r.in.req = &req;
8072 r.out.rep = &repp;
8074 ZERO_STRUCT(req);
8075 req.req3.account.string = "non-existent-account-aklsdji";
8077 for (i=0; passwords[i]; i++) {
8078 req.req3.password.string = passwords[i];
8080 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
8081 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
8082 torture_skip(tctx, "ValidatePassword not supported by server\n");
8084 torture_assert_ntstatus_ok(tctx, status,
8085 "samr_ValidatePassword failed");
8086 torture_assert_ntstatus_ok(tctx, r.out.result,
8087 "samr_ValidatePassword failed");
8088 torture_comment(tctx, "Server %s password '%s' with code %i\n",
8089 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
8090 req.req3.password.string, repp->ctr3.status);
8093 return true;
8096 bool torture_rpc_samr(struct torture_context *torture)
8098 NTSTATUS status;
8099 struct dcerpc_pipe *p;
8100 bool ret = true;
8101 struct torture_samr_context *ctx;
8102 struct dcerpc_binding_handle *b;
8104 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8105 if (!NT_STATUS_IS_OK(status)) {
8106 return false;
8108 b = p->binding_handle;
8110 ctx = talloc_zero(torture, struct torture_samr_context);
8112 ctx->choice = TORTURE_SAMR_OTHER;
8114 ret &= test_Connect(b, torture, &ctx->handle);
8116 if (!torture_setting_bool(torture, "samba3", false)) {
8117 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8120 ret &= test_EnumDomains(p, torture, ctx);
8122 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8124 ret &= test_Shutdown(b, torture, &ctx->handle);
8126 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8128 return ret;
8132 bool torture_rpc_samr_users(struct torture_context *torture)
8134 NTSTATUS status;
8135 struct dcerpc_pipe *p;
8136 bool ret = true;
8137 struct torture_samr_context *ctx;
8138 struct dcerpc_binding_handle *b;
8140 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8141 if (!NT_STATUS_IS_OK(status)) {
8142 return false;
8144 b = p->binding_handle;
8146 ctx = talloc_zero(torture, struct torture_samr_context);
8148 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
8150 ret &= test_Connect(b, torture, &ctx->handle);
8152 if (!torture_setting_bool(torture, "samba3", false)) {
8153 ret &= test_QuerySecurity(b, torture, &ctx->handle);
8156 ret &= test_EnumDomains(p, torture, ctx);
8158 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
8160 ret &= test_Shutdown(b, torture, &ctx->handle);
8162 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8164 return ret;
8168 bool torture_rpc_samr_passwords(struct torture_context *torture)
8170 NTSTATUS status;
8171 struct dcerpc_pipe *p;
8172 bool ret = true;
8173 struct torture_samr_context *ctx;
8174 struct dcerpc_binding_handle *b;
8176 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8177 if (!NT_STATUS_IS_OK(status)) {
8178 return false;
8180 b = p->binding_handle;
8182 ctx = talloc_zero(torture, struct torture_samr_context);
8184 ctx->choice = TORTURE_SAMR_PASSWORDS;
8186 ret &= test_Connect(b, torture, &ctx->handle);
8188 ret &= test_EnumDomains(p, torture, ctx);
8190 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8192 ret &= test_samr_ValidatePassword(p, torture);
8194 return ret;
8197 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8198 struct dcerpc_pipe *p2,
8199 struct cli_credentials *machine_credentials)
8201 NTSTATUS status;
8202 struct dcerpc_pipe *p;
8203 bool ret = true;
8204 struct torture_samr_context *ctx;
8205 struct dcerpc_binding_handle *b;
8207 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8208 if (!NT_STATUS_IS_OK(status)) {
8209 return false;
8211 b = p->binding_handle;
8213 ctx = talloc_zero(torture, struct torture_samr_context);
8215 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8216 ctx->machine_credentials = machine_credentials;
8218 ret &= test_Connect(b, torture, &ctx->handle);
8220 ret &= test_EnumDomains(p, torture, ctx);
8222 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8224 return ret;
8227 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8229 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8230 struct torture_rpc_tcase *tcase;
8232 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8233 &ndr_table_samr,
8234 TEST_ACCOUNT_NAME_PWD);
8236 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8237 torture_rpc_samr_pwdlastset);
8239 return suite;
8242 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8243 struct dcerpc_pipe *p2,
8244 struct cli_credentials *machine_credentials)
8246 NTSTATUS status;
8247 struct dcerpc_pipe *p;
8248 bool ret = true;
8249 struct torture_samr_context *ctx;
8250 struct dcerpc_binding_handle *b;
8252 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8253 if (!NT_STATUS_IS_OK(status)) {
8254 return false;
8256 b = p->binding_handle;
8258 ctx = talloc_zero(torture, struct torture_samr_context);
8260 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8261 ctx->machine_credentials = machine_credentials;
8263 ret &= test_Connect(b, torture, &ctx->handle);
8265 ret &= test_EnumDomains(p, torture, ctx);
8267 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8269 return ret;
8272 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8274 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8275 struct torture_rpc_tcase *tcase;
8277 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8278 &ndr_table_samr,
8279 TEST_ACCOUNT_NAME_PWD);
8281 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8282 torture_rpc_samr_users_privileges_delete_user);
8284 return suite;
8287 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8288 struct dcerpc_pipe *p2,
8289 void *data)
8291 NTSTATUS status;
8292 struct dcerpc_pipe *p;
8293 bool ret = true;
8294 struct torture_samr_context *ctx =
8295 talloc_get_type_abort(data, struct torture_samr_context);
8296 struct dcerpc_binding_handle *b;
8298 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8299 if (!NT_STATUS_IS_OK(status)) {
8300 return false;
8302 b = p->binding_handle;
8304 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8305 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8306 ctx->num_objects_large_dc);
8308 ret &= test_Connect(b, torture, &ctx->handle);
8310 ret &= test_EnumDomains(p, torture, ctx);
8312 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8314 return ret;
8317 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8318 struct dcerpc_pipe *p2,
8319 void *data)
8321 NTSTATUS status;
8322 struct dcerpc_pipe *p;
8323 bool ret = true;
8324 struct torture_samr_context *ctx =
8325 talloc_get_type_abort(data, struct torture_samr_context);
8326 struct dcerpc_binding_handle *b;
8328 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8329 if (!NT_STATUS_IS_OK(status)) {
8330 return false;
8332 b = p->binding_handle;
8334 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8335 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8336 ctx->num_objects_large_dc);
8338 ret &= test_Connect(b, torture, &ctx->handle);
8340 ret &= test_EnumDomains(p, torture, ctx);
8342 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8344 return ret;
8347 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8348 struct dcerpc_pipe *p2,
8349 void *data)
8351 NTSTATUS status;
8352 struct dcerpc_pipe *p;
8353 bool ret = true;
8354 struct torture_samr_context *ctx =
8355 talloc_get_type_abort(data, struct torture_samr_context);
8356 struct dcerpc_binding_handle *b;
8358 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8359 if (!NT_STATUS_IS_OK(status)) {
8360 return false;
8362 b = p->binding_handle;
8364 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8365 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8366 ctx->num_objects_large_dc);
8368 ret &= test_Connect(b, torture, &ctx->handle);
8370 ret &= test_EnumDomains(p, torture, ctx);
8372 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8374 return ret;
8377 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8379 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8380 struct torture_rpc_tcase *tcase;
8381 struct torture_samr_context *ctx;
8383 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8385 ctx = talloc_zero(suite, struct torture_samr_context);
8386 ctx->num_objects_large_dc = 150;
8388 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8389 torture_rpc_samr_many_aliases, ctx);
8390 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8391 torture_rpc_samr_many_groups, ctx);
8392 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8393 torture_rpc_samr_many_accounts, ctx);
8395 return suite;
8398 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8399 struct dcerpc_pipe *p2,
8400 struct cli_credentials *machine_credentials)
8402 NTSTATUS status;
8403 struct dcerpc_pipe *p;
8404 bool ret = true;
8405 struct torture_samr_context *ctx;
8406 struct dcerpc_binding_handle *b;
8408 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8409 if (!NT_STATUS_IS_OK(status)) {
8410 return false;
8412 b = p->binding_handle;
8414 ctx = talloc_zero(torture, struct torture_samr_context);
8416 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8417 ctx->machine_credentials = machine_credentials;
8419 ret &= test_Connect(b, torture, &ctx->handle);
8421 ret &= test_EnumDomains(p, torture, ctx);
8423 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8425 return ret;
8428 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8430 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8431 struct torture_rpc_tcase *tcase;
8433 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8434 &ndr_table_samr,
8435 TEST_ACCOUNT_NAME_PWD);
8437 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8438 torture_rpc_samr_badpwdcount);
8440 return suite;
8443 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8444 struct dcerpc_pipe *p2,
8445 struct cli_credentials *machine_credentials)
8447 NTSTATUS status;
8448 struct dcerpc_pipe *p;
8449 bool ret = true;
8450 struct torture_samr_context *ctx;
8451 struct dcerpc_binding_handle *b;
8453 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8454 if (!NT_STATUS_IS_OK(status)) {
8455 return false;
8457 b = p->binding_handle;
8459 ctx = talloc_zero(torture, struct torture_samr_context);
8461 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8462 ctx->machine_credentials = machine_credentials;
8464 ret &= test_Connect(b, torture, &ctx->handle);
8466 ret &= test_EnumDomains(p, torture, ctx);
8468 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8470 return ret;
8473 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8475 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8476 struct torture_rpc_tcase *tcase;
8478 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8479 &ndr_table_samr,
8480 TEST_ACCOUNT_NAME_PWD);
8482 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8483 torture_rpc_samr_lockout);
8485 return suite;