s4-smbtorture: Fix order of assert args in test_TestPrivateFunctionsDomain() in RPC...
[Samba.git] / source4 / torture / rpc / samr.c
blob4025372732484b24e7b8ffd0a0835fa6e072ba37
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
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "system/time.h"
25 #include "librpc/gen_ndr/lsa.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "librpc/gen_ndr/ndr_netlogon_c.h"
28 #include "librpc/gen_ndr/ndr_samr_c.h"
29 #include "../lib/crypto/crypto.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/rpc.h"
33 #include "param/param.h"
35 #include <unistd.h>
37 #define TEST_ACCOUNT_NAME "samrtorturetest"
38 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
39 #define TEST_ALIASNAME "samrtorturetestalias"
40 #define TEST_GROUPNAME "samrtorturetestgroup"
41 #define TEST_MACHINENAME "samrtestmach$"
42 #define TEST_DOMAINNAME "samrtestdom$"
44 enum torture_samr_choice {
45 TORTURE_SAMR_PASSWORDS,
46 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
47 TORTURE_SAMR_USER_ATTRIBUTES,
48 TORTURE_SAMR_OTHER
51 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
52 struct torture_context *tctx,
53 struct policy_handle *handle);
55 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
56 struct torture_context *tctx,
57 struct policy_handle *handle);
59 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
60 struct torture_context *tctx,
61 struct policy_handle *handle);
63 static bool test_ChangePassword(struct dcerpc_pipe *p,
64 struct torture_context *tctx,
65 const char *acct_name,
66 struct policy_handle *domain_handle, char **password);
68 static void init_lsa_String(struct lsa_String *string, const char *s)
70 string->string = s;
73 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
75 string->length = length;
76 string->size = length;
77 string->array = (uint16_t *)discard_const(s);
80 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
81 struct policy_handle *handle)
83 NTSTATUS status;
84 struct samr_Close r;
86 r.in.handle = handle;
87 r.out.handle = handle;
89 status = dcerpc_samr_Close(p, tctx, &r);
90 torture_assert_ntstatus_ok(tctx, status, "Close");
92 return true;
95 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
96 struct policy_handle *handle)
98 NTSTATUS status;
99 struct samr_Shutdown r;
101 if (!torture_setting_bool(tctx, "dangerous", false)) {
102 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
103 return true;
106 r.in.connect_handle = handle;
108 torture_comment(tctx, "testing samr_Shutdown\n");
110 status = dcerpc_samr_Shutdown(p, tctx, &r);
111 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
113 return true;
116 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
117 struct policy_handle *handle)
119 NTSTATUS status;
120 struct samr_SetDsrmPassword r;
121 struct lsa_String string;
122 struct samr_Password hash;
124 if (!torture_setting_bool(tctx, "dangerous", false)) {
125 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
128 E_md4hash("TeSTDSRM123", hash.hash);
130 init_lsa_String(&string, "Administrator");
132 r.in.name = &string;
133 r.in.unknown = 0;
134 r.in.hash = &hash;
136 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
138 status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
139 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
141 return true;
145 static bool test_QuerySecurity(struct dcerpc_pipe *p,
146 struct torture_context *tctx,
147 struct policy_handle *handle)
149 NTSTATUS status;
150 struct samr_QuerySecurity r;
151 struct samr_SetSecurity s;
152 struct sec_desc_buf *sdbuf = NULL;
154 r.in.handle = handle;
155 r.in.sec_info = 7;
156 r.out.sdbuf = &sdbuf;
158 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
159 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
161 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
163 s.in.handle = handle;
164 s.in.sec_info = 7;
165 s.in.sdbuf = sdbuf;
167 if (torture_setting_bool(tctx, "samba4", false)) {
168 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
171 status = dcerpc_samr_SetSecurity(p, tctx, &s);
172 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
174 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
175 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
177 return true;
181 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
182 struct policy_handle *handle, uint32_t base_acct_flags,
183 const char *base_account_name)
185 NTSTATUS status;
186 struct samr_SetUserInfo s;
187 struct samr_SetUserInfo2 s2;
188 struct samr_QueryUserInfo q;
189 struct samr_QueryUserInfo q0;
190 union samr_UserInfo u;
191 union samr_UserInfo *info;
192 bool ret = true;
193 const char *test_account_name;
195 uint32_t user_extra_flags = 0;
197 if (!torture_setting_bool(tctx, "samba3", false)) {
198 if (base_acct_flags == ACB_NORMAL) {
199 /* When created, accounts are expired by default */
200 user_extra_flags = ACB_PW_EXPIRED;
204 s.in.user_handle = handle;
205 s.in.info = &u;
207 s2.in.user_handle = handle;
208 s2.in.info = &u;
210 q.in.user_handle = handle;
211 q.out.info = &info;
212 q0 = q;
214 #define TESTCALL(call, r) \
215 status = dcerpc_samr_ ##call(p, tctx, &r); \
216 if (!NT_STATUS_IS_OK(status)) { \
217 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
218 r.in.level, nt_errstr(status), __location__); \
219 ret = false; \
220 break; \
223 #define STRING_EQUAL(s1, s2, field) \
224 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
225 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
226 #field, s2, __location__); \
227 ret = false; \
228 break; \
231 #define MEM_EQUAL(s1, s2, length, field) \
232 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
233 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
234 #field, (const char *)s2, __location__); \
235 ret = false; \
236 break; \
239 #define INT_EQUAL(i1, i2, field) \
240 if (i1 != i2) { \
241 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
242 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
243 ret = false; \
244 break; \
247 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
248 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
249 q.in.level = lvl1; \
250 TESTCALL(QueryUserInfo, q) \
251 s.in.level = lvl1; \
252 s2.in.level = lvl1; \
253 u = *info; \
254 if (lvl1 == 21) { \
255 ZERO_STRUCT(u.info21); \
256 u.info21.fields_present = fpval; \
258 init_lsa_String(&u.info ## lvl1.field1, value); \
259 TESTCALL(SetUserInfo, s) \
260 TESTCALL(SetUserInfo2, s2) \
261 init_lsa_String(&u.info ## lvl1.field1, ""); \
262 TESTCALL(QueryUserInfo, q); \
263 u = *info; \
264 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
265 q.in.level = lvl2; \
266 TESTCALL(QueryUserInfo, q) \
267 u = *info; \
268 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
269 } while (0)
271 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
272 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
273 q.in.level = lvl1; \
274 TESTCALL(QueryUserInfo, q) \
275 s.in.level = lvl1; \
276 s2.in.level = lvl1; \
277 u = *info; \
278 if (lvl1 == 21) { \
279 ZERO_STRUCT(u.info21); \
280 u.info21.fields_present = fpval; \
282 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
283 TESTCALL(SetUserInfo, s) \
284 TESTCALL(SetUserInfo2, s2) \
285 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
286 TESTCALL(QueryUserInfo, q); \
287 u = *info; \
288 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
289 q.in.level = lvl2; \
290 TESTCALL(QueryUserInfo, q) \
291 u = *info; \
292 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
293 } while (0)
295 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
296 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
297 q.in.level = lvl1; \
298 TESTCALL(QueryUserInfo, q) \
299 s.in.level = lvl1; \
300 s2.in.level = lvl1; \
301 u = *info; \
302 if (lvl1 == 21) { \
303 uint8_t *bits = u.info21.logon_hours.bits; \
304 ZERO_STRUCT(u.info21); \
305 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
306 u.info21.logon_hours.units_per_week = 168; \
307 u.info21.logon_hours.bits = bits; \
309 u.info21.fields_present = fpval; \
311 u.info ## lvl1.field1 = value; \
312 TESTCALL(SetUserInfo, s) \
313 TESTCALL(SetUserInfo2, s2) \
314 u.info ## lvl1.field1 = 0; \
315 TESTCALL(QueryUserInfo, q); \
316 u = *info; \
317 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
318 q.in.level = lvl2; \
319 TESTCALL(QueryUserInfo, q) \
320 u = *info; \
321 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
322 } while (0)
324 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
325 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
326 } while (0)
328 q0.in.level = 12;
329 do { TESTCALL(QueryUserInfo, q0) } while (0);
331 /* Samba 3 cannot store comment fields atm. - gd */
332 if (!torture_setting_bool(tctx, "samba3", false)) {
333 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
334 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
335 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
336 SAMR_FIELD_COMMENT);
339 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
340 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
341 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
342 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
343 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
344 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
345 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
346 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
347 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
348 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
349 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
350 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
351 test_account_name = base_account_name;
352 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
353 SAMR_FIELD_ACCOUNT_NAME);
355 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
356 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
357 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
358 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
359 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
360 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
361 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
362 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
363 SAMR_FIELD_FULL_NAME);
365 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
366 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
367 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
368 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
369 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
370 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
371 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
372 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
373 SAMR_FIELD_FULL_NAME);
375 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
376 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
377 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
378 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
379 SAMR_FIELD_LOGON_SCRIPT);
381 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
382 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
383 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
384 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
385 SAMR_FIELD_PROFILE_PATH);
387 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
388 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
389 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
390 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
391 SAMR_FIELD_HOME_DIRECTORY);
392 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
393 SAMR_FIELD_HOME_DIRECTORY);
395 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
396 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
397 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
398 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
399 SAMR_FIELD_HOME_DRIVE);
400 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
401 SAMR_FIELD_HOME_DRIVE);
403 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
404 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
405 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
406 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
407 SAMR_FIELD_DESCRIPTION);
409 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
410 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
411 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
412 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
413 SAMR_FIELD_WORKSTATIONS);
414 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
415 SAMR_FIELD_WORKSTATIONS);
416 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
417 SAMR_FIELD_WORKSTATIONS);
418 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
419 SAMR_FIELD_WORKSTATIONS);
421 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
422 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
423 SAMR_FIELD_PARAMETERS);
424 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
425 SAMR_FIELD_PARAMETERS);
426 /* also empty user parameters are allowed */
427 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
428 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
429 SAMR_FIELD_PARAMETERS);
430 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
431 SAMR_FIELD_PARAMETERS);
433 /* Samba 3 cannot store country_code and copy_page atm. - gd */
434 if (!torture_setting_bool(tctx, "samba3", false)) {
435 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
436 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
437 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
438 SAMR_FIELD_COUNTRY_CODE);
439 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
440 SAMR_FIELD_COUNTRY_CODE);
442 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
443 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
444 SAMR_FIELD_CODE_PAGE);
445 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
446 SAMR_FIELD_CODE_PAGE);
449 if (!torture_setting_bool(tctx, "samba3", false)) {
450 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
451 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
452 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
453 SAMR_FIELD_ACCT_EXPIRY);
454 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
455 SAMR_FIELD_ACCT_EXPIRY);
456 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
457 SAMR_FIELD_ACCT_EXPIRY);
458 } else {
459 /* Samba 3 can only store seconds / time_t in passdb - gd */
460 NTTIME nt;
461 unix_to_nt_time(&nt, time(NULL) + __LINE__);
462 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
463 unix_to_nt_time(&nt, time(NULL) + __LINE__);
464 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
465 unix_to_nt_time(&nt, time(NULL) + __LINE__);
466 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
467 unix_to_nt_time(&nt, time(NULL) + __LINE__);
468 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
469 unix_to_nt_time(&nt, time(NULL) + __LINE__);
470 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
473 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
474 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
475 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
476 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
477 SAMR_FIELD_LOGON_HOURS);
479 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
480 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
481 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
483 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
484 (base_acct_flags | ACB_DISABLED),
485 (base_acct_flags | ACB_DISABLED | user_extra_flags),
488 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
489 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
490 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
491 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
493 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
494 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
495 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
499 /* The 'autolock' flag doesn't stick - check this */
500 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
501 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
502 (base_acct_flags | ACB_DISABLED | user_extra_flags),
504 #if 0
505 /* Removing the 'disabled' flag doesn't stick - check this */
506 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
507 (base_acct_flags),
508 (base_acct_flags | ACB_DISABLED | user_extra_flags),
510 #endif
512 /* Samba3 cannot store these atm */
513 if (!torture_setting_bool(tctx, "samba3", false)) {
514 /* The 'store plaintext' flag does stick */
515 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
516 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
517 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
519 /* The 'use DES' flag does stick */
520 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
521 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
522 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
524 /* The 'don't require kerberos pre-authentication flag does stick */
525 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
526 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
527 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
529 /* The 'no kerberos PAC required' flag sticks */
530 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
531 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
532 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
535 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
536 (base_acct_flags | ACB_DISABLED),
537 (base_acct_flags | ACB_DISABLED | user_extra_flags),
538 SAMR_FIELD_ACCT_FLAGS);
540 #if 0
541 /* these fail with win2003 - it appears you can't set the primary gid?
542 the set succeeds, but the gid isn't changed. Very weird! */
543 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
544 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
545 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
546 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
547 #endif
549 return ret;
553 generate a random password for password change tests
555 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
557 size_t len = MAX(8, min_len) + (random() % 6);
558 char *s = generate_random_str(mem_ctx, len);
559 return s;
562 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
564 char *s = samr_rand_pass_silent(mem_ctx, min_len);
565 printf("Generated password '%s'\n", s);
566 return s;
571 generate a random password for password change tests
573 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
575 int i;
576 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
577 generate_random_buffer(password.data, password.length);
579 for (i=0; i < len; i++) {
580 if (((uint16_t *)password.data)[i] == 0) {
581 ((uint16_t *)password.data)[i] = 1;
585 return password;
589 generate a random password for password change tests (fixed length)
591 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
593 char *s = generate_random_str(mem_ctx, len);
594 printf("Generated password '%s'\n", s);
595 return s;
598 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
599 struct policy_handle *handle, char **password)
601 NTSTATUS status;
602 struct samr_SetUserInfo s;
603 union samr_UserInfo u;
604 bool ret = true;
605 DATA_BLOB session_key;
606 char *newpass;
607 struct samr_GetUserPwInfo pwp;
608 struct samr_PwInfo info;
609 int policy_min_pw_len = 0;
610 pwp.in.user_handle = handle;
611 pwp.out.info = &info;
613 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
614 if (NT_STATUS_IS_OK(status)) {
615 policy_min_pw_len = pwp.out.info->min_password_length;
617 newpass = samr_rand_pass(tctx, policy_min_pw_len);
619 s.in.user_handle = handle;
620 s.in.info = &u;
621 s.in.level = 24;
623 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
624 u.info24.password_expired = 0;
626 status = dcerpc_fetch_session_key(p, &session_key);
627 if (!NT_STATUS_IS_OK(status)) {
628 printf("SetUserInfo level %u - no session key - %s\n",
629 s.in.level, nt_errstr(status));
630 return false;
633 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
635 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
637 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
638 if (!NT_STATUS_IS_OK(status)) {
639 printf("SetUserInfo level %u failed - %s\n",
640 s.in.level, nt_errstr(status));
641 ret = false;
642 } else {
643 *password = newpass;
646 return ret;
650 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
651 struct policy_handle *handle, uint32_t fields_present,
652 char **password)
654 NTSTATUS status;
655 struct samr_SetUserInfo s;
656 union samr_UserInfo u;
657 bool ret = true;
658 DATA_BLOB session_key;
659 char *newpass;
660 struct samr_GetUserPwInfo pwp;
661 struct samr_PwInfo info;
662 int policy_min_pw_len = 0;
663 pwp.in.user_handle = handle;
664 pwp.out.info = &info;
666 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
667 if (NT_STATUS_IS_OK(status)) {
668 policy_min_pw_len = pwp.out.info->min_password_length;
670 newpass = samr_rand_pass(tctx, policy_min_pw_len);
672 s.in.user_handle = handle;
673 s.in.info = &u;
674 s.in.level = 23;
676 ZERO_STRUCT(u);
678 u.info23.info.fields_present = fields_present;
680 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
682 status = dcerpc_fetch_session_key(p, &session_key);
683 if (!NT_STATUS_IS_OK(status)) {
684 printf("SetUserInfo level %u - no session key - %s\n",
685 s.in.level, nt_errstr(status));
686 return false;
689 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
691 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
693 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
694 if (!NT_STATUS_IS_OK(status)) {
695 printf("SetUserInfo level %u failed - %s\n",
696 s.in.level, nt_errstr(status));
697 ret = false;
698 } else {
699 *password = newpass;
702 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
704 status = dcerpc_fetch_session_key(p, &session_key);
705 if (!NT_STATUS_IS_OK(status)) {
706 printf("SetUserInfo level %u - no session key - %s\n",
707 s.in.level, nt_errstr(status));
708 return false;
711 /* This should break the key nicely */
712 session_key.length--;
713 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
715 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
717 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
718 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
719 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
720 s.in.level, nt_errstr(status));
721 ret = false;
724 return ret;
728 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
729 struct policy_handle *handle, bool makeshort,
730 char **password)
732 NTSTATUS status;
733 struct samr_SetUserInfo s;
734 union samr_UserInfo u;
735 bool ret = true;
736 DATA_BLOB session_key;
737 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
738 uint8_t confounder[16];
739 char *newpass;
740 struct MD5Context ctx;
741 struct samr_GetUserPwInfo pwp;
742 struct samr_PwInfo info;
743 int policy_min_pw_len = 0;
744 pwp.in.user_handle = handle;
745 pwp.out.info = &info;
747 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
748 if (NT_STATUS_IS_OK(status)) {
749 policy_min_pw_len = pwp.out.info->min_password_length;
751 if (makeshort && policy_min_pw_len) {
752 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
753 } else {
754 newpass = samr_rand_pass(tctx, policy_min_pw_len);
757 s.in.user_handle = handle;
758 s.in.info = &u;
759 s.in.level = 26;
761 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
762 u.info26.password_expired = 0;
764 status = dcerpc_fetch_session_key(p, &session_key);
765 if (!NT_STATUS_IS_OK(status)) {
766 printf("SetUserInfo level %u - no session key - %s\n",
767 s.in.level, nt_errstr(status));
768 return false;
771 generate_random_buffer((uint8_t *)confounder, 16);
773 MD5Init(&ctx);
774 MD5Update(&ctx, confounder, 16);
775 MD5Update(&ctx, session_key.data, session_key.length);
776 MD5Final(confounded_session_key.data, &ctx);
778 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
779 memcpy(&u.info26.password.data[516], confounder, 16);
781 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
783 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
784 if (!NT_STATUS_IS_OK(status)) {
785 printf("SetUserInfo level %u failed - %s\n",
786 s.in.level, nt_errstr(status));
787 ret = false;
788 } else {
789 *password = newpass;
792 /* This should break the key nicely */
793 confounded_session_key.data[0]++;
795 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
796 memcpy(&u.info26.password.data[516], confounder, 16);
798 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
800 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
801 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
802 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
803 s.in.level, nt_errstr(status));
804 ret = false;
805 } else {
806 *password = newpass;
809 return ret;
812 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
813 struct policy_handle *handle, uint32_t fields_present,
814 char **password)
816 NTSTATUS status;
817 struct samr_SetUserInfo s;
818 union samr_UserInfo u;
819 bool ret = true;
820 DATA_BLOB session_key;
821 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
822 struct MD5Context ctx;
823 uint8_t confounder[16];
824 char *newpass;
825 struct samr_GetUserPwInfo pwp;
826 struct samr_PwInfo info;
827 int policy_min_pw_len = 0;
828 pwp.in.user_handle = handle;
829 pwp.out.info = &info;
831 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
832 if (NT_STATUS_IS_OK(status)) {
833 policy_min_pw_len = pwp.out.info->min_password_length;
835 newpass = samr_rand_pass(tctx, policy_min_pw_len);
837 s.in.user_handle = handle;
838 s.in.info = &u;
839 s.in.level = 25;
841 ZERO_STRUCT(u);
843 u.info25.info.fields_present = fields_present;
845 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
847 status = dcerpc_fetch_session_key(p, &session_key);
848 if (!NT_STATUS_IS_OK(status)) {
849 printf("SetUserInfo level %u - no session key - %s\n",
850 s.in.level, nt_errstr(status));
851 return false;
854 generate_random_buffer((uint8_t *)confounder, 16);
856 MD5Init(&ctx);
857 MD5Update(&ctx, confounder, 16);
858 MD5Update(&ctx, session_key.data, session_key.length);
859 MD5Final(confounded_session_key.data, &ctx);
861 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
862 memcpy(&u.info25.password.data[516], confounder, 16);
864 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
866 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
867 if (!NT_STATUS_IS_OK(status)) {
868 printf("SetUserInfo level %u failed - %s\n",
869 s.in.level, nt_errstr(status));
870 ret = false;
871 } else {
872 *password = newpass;
875 /* This should break the key nicely */
876 confounded_session_key.data[0]++;
878 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
879 memcpy(&u.info25.password.data[516], confounder, 16);
881 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
883 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
884 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
885 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
886 s.in.level, nt_errstr(status));
887 ret = false;
890 return ret;
893 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
894 struct policy_handle *handle, char **password)
896 NTSTATUS status;
897 struct samr_SetUserInfo s;
898 union samr_UserInfo u;
899 bool ret = true;
900 DATA_BLOB session_key;
901 char *newpass;
902 struct samr_GetUserPwInfo pwp;
903 struct samr_PwInfo info;
904 int policy_min_pw_len = 0;
905 uint8_t lm_hash[16], nt_hash[16];
907 pwp.in.user_handle = handle;
908 pwp.out.info = &info;
910 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
911 if (NT_STATUS_IS_OK(status)) {
912 policy_min_pw_len = pwp.out.info->min_password_length;
914 newpass = samr_rand_pass(tctx, policy_min_pw_len);
916 s.in.user_handle = handle;
917 s.in.info = &u;
918 s.in.level = 18;
920 ZERO_STRUCT(u);
922 u.info18.nt_pwd_active = true;
923 u.info18.lm_pwd_active = true;
925 E_md4hash(newpass, nt_hash);
926 E_deshash(newpass, lm_hash);
928 status = dcerpc_fetch_session_key(p, &session_key);
929 if (!NT_STATUS_IS_OK(status)) {
930 printf("SetUserInfo level %u - no session key - %s\n",
931 s.in.level, nt_errstr(status));
932 return false;
936 DATA_BLOB in,out;
937 in = data_blob_const(nt_hash, 16);
938 out = data_blob_talloc_zero(tctx, 16);
939 sess_crypt_blob(&out, &in, &session_key, true);
940 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
943 DATA_BLOB in,out;
944 in = data_blob_const(lm_hash, 16);
945 out = data_blob_talloc_zero(tctx, 16);
946 sess_crypt_blob(&out, &in, &session_key, true);
947 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
950 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
952 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
953 if (!NT_STATUS_IS_OK(status)) {
954 printf("SetUserInfo level %u failed - %s\n",
955 s.in.level, nt_errstr(status));
956 ret = false;
957 } else {
958 *password = newpass;
961 return ret;
964 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
965 struct policy_handle *handle, uint32_t fields_present,
966 char **password)
968 NTSTATUS status;
969 struct samr_SetUserInfo s;
970 union samr_UserInfo u;
971 bool ret = true;
972 DATA_BLOB session_key;
973 char *newpass;
974 struct samr_GetUserPwInfo pwp;
975 struct samr_PwInfo info;
976 int policy_min_pw_len = 0;
977 uint8_t lm_hash[16], nt_hash[16];
979 pwp.in.user_handle = handle;
980 pwp.out.info = &info;
982 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
983 if (NT_STATUS_IS_OK(status)) {
984 policy_min_pw_len = pwp.out.info->min_password_length;
986 newpass = samr_rand_pass(tctx, policy_min_pw_len);
988 s.in.user_handle = handle;
989 s.in.info = &u;
990 s.in.level = 21;
992 E_md4hash(newpass, nt_hash);
993 E_deshash(newpass, lm_hash);
995 ZERO_STRUCT(u);
997 u.info21.fields_present = fields_present;
999 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1000 u.info21.lm_owf_password.length = 16;
1001 u.info21.lm_owf_password.size = 16;
1002 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1003 u.info21.lm_password_set = true;
1006 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1007 u.info21.nt_owf_password.length = 16;
1008 u.info21.nt_owf_password.size = 16;
1009 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1010 u.info21.nt_password_set = true;
1013 status = dcerpc_fetch_session_key(p, &session_key);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 printf("SetUserInfo level %u - no session key - %s\n",
1016 s.in.level, nt_errstr(status));
1017 return false;
1020 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1021 DATA_BLOB in,out;
1022 in = data_blob_const(u.info21.lm_owf_password.array,
1023 u.info21.lm_owf_password.length);
1024 out = data_blob_talloc_zero(tctx, 16);
1025 sess_crypt_blob(&out, &in, &session_key, true);
1026 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1029 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1030 DATA_BLOB in,out;
1031 in = data_blob_const(u.info21.nt_owf_password.array,
1032 u.info21.nt_owf_password.length);
1033 out = data_blob_talloc_zero(tctx, 16);
1034 sess_crypt_blob(&out, &in, &session_key, true);
1035 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1038 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1040 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1041 if (!NT_STATUS_IS_OK(status)) {
1042 printf("SetUserInfo level %u failed - %s\n",
1043 s.in.level, nt_errstr(status));
1044 ret = false;
1045 } else {
1046 *password = newpass;
1049 /* try invalid length */
1050 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1052 u.info21.nt_owf_password.length++;
1054 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1056 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1057 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1058 s.in.level, nt_errstr(status));
1059 ret = false;
1063 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1065 u.info21.lm_owf_password.length++;
1067 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1069 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1070 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1071 s.in.level, nt_errstr(status));
1072 ret = false;
1076 return ret;
1079 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1080 struct torture_context *tctx,
1081 struct policy_handle *handle,
1082 uint16_t level,
1083 uint32_t fields_present,
1084 char **password, uint8_t password_expired,
1085 bool use_setinfo2,
1086 bool *matched_expected_error)
1088 NTSTATUS status;
1089 NTSTATUS expected_error = NT_STATUS_OK;
1090 struct samr_SetUserInfo s;
1091 struct samr_SetUserInfo2 s2;
1092 union samr_UserInfo u;
1093 bool ret = true;
1094 DATA_BLOB session_key;
1095 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1096 struct MD5Context ctx;
1097 uint8_t confounder[16];
1098 char *newpass;
1099 struct samr_GetUserPwInfo pwp;
1100 struct samr_PwInfo info;
1101 int policy_min_pw_len = 0;
1102 const char *comment = NULL;
1103 uint8_t lm_hash[16], nt_hash[16];
1105 pwp.in.user_handle = handle;
1106 pwp.out.info = &info;
1108 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1109 if (NT_STATUS_IS_OK(status)) {
1110 policy_min_pw_len = pwp.out.info->min_password_length;
1112 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1114 if (use_setinfo2) {
1115 s2.in.user_handle = handle;
1116 s2.in.info = &u;
1117 s2.in.level = level;
1118 } else {
1119 s.in.user_handle = handle;
1120 s.in.info = &u;
1121 s.in.level = level;
1124 if (fields_present & SAMR_FIELD_COMMENT) {
1125 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1128 ZERO_STRUCT(u);
1130 switch (level) {
1131 case 18:
1132 E_md4hash(newpass, nt_hash);
1133 E_deshash(newpass, lm_hash);
1135 u.info18.nt_pwd_active = true;
1136 u.info18.lm_pwd_active = true;
1137 u.info18.password_expired = password_expired;
1139 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1140 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1142 break;
1143 case 21:
1144 E_md4hash(newpass, nt_hash);
1145 E_deshash(newpass, lm_hash);
1147 u.info21.fields_present = fields_present;
1148 u.info21.password_expired = password_expired;
1149 u.info21.comment.string = comment;
1151 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1152 u.info21.lm_owf_password.length = 16;
1153 u.info21.lm_owf_password.size = 16;
1154 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1155 u.info21.lm_password_set = true;
1158 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1159 u.info21.nt_owf_password.length = 16;
1160 u.info21.nt_owf_password.size = 16;
1161 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1162 u.info21.nt_password_set = true;
1165 break;
1166 case 23:
1167 u.info23.info.fields_present = fields_present;
1168 u.info23.info.password_expired = password_expired;
1169 u.info23.info.comment.string = comment;
1171 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1173 break;
1174 case 24:
1175 u.info24.password_expired = password_expired;
1177 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1179 break;
1180 case 25:
1181 u.info25.info.fields_present = fields_present;
1182 u.info25.info.password_expired = password_expired;
1183 u.info25.info.comment.string = comment;
1185 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1187 break;
1188 case 26:
1189 u.info26.password_expired = password_expired;
1191 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1193 break;
1196 status = dcerpc_fetch_session_key(p, &session_key);
1197 if (!NT_STATUS_IS_OK(status)) {
1198 printf("SetUserInfo level %u - no session key - %s\n",
1199 s.in.level, nt_errstr(status));
1200 return false;
1203 generate_random_buffer((uint8_t *)confounder, 16);
1205 MD5Init(&ctx);
1206 MD5Update(&ctx, confounder, 16);
1207 MD5Update(&ctx, session_key.data, session_key.length);
1208 MD5Final(confounded_session_key.data, &ctx);
1210 switch (level) {
1211 case 18:
1213 DATA_BLOB in,out;
1214 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1215 out = data_blob_talloc_zero(tctx, 16);
1216 sess_crypt_blob(&out, &in, &session_key, true);
1217 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1220 DATA_BLOB in,out;
1221 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1222 out = data_blob_talloc_zero(tctx, 16);
1223 sess_crypt_blob(&out, &in, &session_key, true);
1224 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1227 break;
1228 case 21:
1229 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1230 DATA_BLOB in,out;
1231 in = data_blob_const(u.info21.lm_owf_password.array,
1232 u.info21.lm_owf_password.length);
1233 out = data_blob_talloc_zero(tctx, 16);
1234 sess_crypt_blob(&out, &in, &session_key, true);
1235 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1237 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1238 DATA_BLOB in,out;
1239 in = data_blob_const(u.info21.nt_owf_password.array,
1240 u.info21.nt_owf_password.length);
1241 out = data_blob_talloc_zero(tctx, 16);
1242 sess_crypt_blob(&out, &in, &session_key, true);
1243 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1245 break;
1246 case 23:
1247 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1248 break;
1249 case 24:
1250 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1251 break;
1252 case 25:
1253 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1254 memcpy(&u.info25.password.data[516], confounder, 16);
1255 break;
1256 case 26:
1257 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1258 memcpy(&u.info26.password.data[516], confounder, 16);
1259 break;
1262 if (use_setinfo2) {
1263 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1264 } else {
1265 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1268 if (!NT_STATUS_IS_OK(status)) {
1269 if (fields_present == 0) {
1270 expected_error = NT_STATUS_INVALID_PARAMETER;
1272 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1273 expected_error = NT_STATUS_ACCESS_DENIED;
1277 if (!NT_STATUS_IS_OK(expected_error)) {
1278 if (use_setinfo2) {
1279 torture_assert_ntstatus_equal(tctx,
1280 s2.out.result,
1281 expected_error, "SetUserInfo2 failed");
1282 } else {
1283 torture_assert_ntstatus_equal(tctx,
1284 s.out.result,
1285 expected_error, "SetUserInfo failed");
1287 *matched_expected_error = true;
1288 return true;
1291 if (!NT_STATUS_IS_OK(status)) {
1292 printf("SetUserInfo%s level %u failed - %s\n",
1293 use_setinfo2 ? "2":"", level, nt_errstr(status));
1294 ret = false;
1295 } else {
1296 *password = newpass;
1299 return ret;
1302 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1303 struct policy_handle *handle)
1305 NTSTATUS status;
1306 struct samr_SetAliasInfo r;
1307 struct samr_QueryAliasInfo q;
1308 union samr_AliasInfo *info;
1309 uint16_t levels[] = {2, 3};
1310 int i;
1311 bool ret = true;
1313 /* Ignoring switch level 1, as that includes the number of members for the alias
1314 * and setting this to a wrong value might have negative consequences
1317 for (i=0;i<ARRAY_SIZE(levels);i++) {
1318 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1320 r.in.alias_handle = handle;
1321 r.in.level = levels[i];
1322 r.in.info = talloc(tctx, union samr_AliasInfo);
1323 switch (r.in.level) {
1324 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1325 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1326 "Test Description, should test I18N as well"); break;
1327 case ALIASINFOALL: printf("ALIASINFOALL ignored\n"); break;
1330 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1331 if (!NT_STATUS_IS_OK(status)) {
1332 printf("SetAliasInfo level %u failed - %s\n",
1333 levels[i], nt_errstr(status));
1334 ret = false;
1337 q.in.alias_handle = handle;
1338 q.in.level = levels[i];
1339 q.out.info = &info;
1341 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1342 if (!NT_STATUS_IS_OK(status)) {
1343 printf("QueryAliasInfo level %u failed - %s\n",
1344 levels[i], nt_errstr(status));
1345 ret = false;
1349 return ret;
1352 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1353 struct policy_handle *user_handle)
1355 struct samr_GetGroupsForUser r;
1356 struct samr_RidWithAttributeArray *rids = NULL;
1357 NTSTATUS status;
1359 torture_comment(tctx, "testing GetGroupsForUser\n");
1361 r.in.user_handle = user_handle;
1362 r.out.rids = &rids;
1364 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1365 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1367 return true;
1371 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1372 struct lsa_String *domain_name)
1374 NTSTATUS status;
1375 struct samr_GetDomPwInfo r;
1376 struct samr_PwInfo info;
1378 r.in.domain_name = domain_name;
1379 r.out.info = &info;
1381 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1383 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1384 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1386 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1387 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1389 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1390 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1392 r.in.domain_name->string = "\\\\__NONAME__";
1393 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1395 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1396 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1398 r.in.domain_name->string = "\\\\Builtin";
1399 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1401 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1402 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1404 return true;
1407 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1408 struct policy_handle *handle)
1410 NTSTATUS status;
1411 struct samr_GetUserPwInfo r;
1412 struct samr_PwInfo info;
1414 torture_comment(tctx, "Testing GetUserPwInfo\n");
1416 r.in.user_handle = handle;
1417 r.out.info = &info;
1419 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1420 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1422 return true;
1425 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1426 struct policy_handle *domain_handle, const char *name,
1427 uint32_t *rid)
1429 NTSTATUS status;
1430 struct samr_LookupNames n;
1431 struct lsa_String sname[2];
1432 struct samr_Ids rids, types;
1434 init_lsa_String(&sname[0], name);
1436 n.in.domain_handle = domain_handle;
1437 n.in.num_names = 1;
1438 n.in.names = sname;
1439 n.out.rids = &rids;
1440 n.out.types = &types;
1441 status = dcerpc_samr_LookupNames(p, tctx, &n);
1442 if (NT_STATUS_IS_OK(status)) {
1443 *rid = n.out.rids->ids[0];
1444 } else {
1445 return status;
1448 init_lsa_String(&sname[1], "xxNONAMExx");
1449 n.in.num_names = 2;
1450 status = dcerpc_samr_LookupNames(p, tctx, &n);
1451 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1452 printf("LookupNames[2] failed - %s\n", nt_errstr(status));
1453 if (NT_STATUS_IS_OK(status)) {
1454 return NT_STATUS_UNSUCCESSFUL;
1456 return status;
1459 n.in.num_names = 0;
1460 status = dcerpc_samr_LookupNames(p, tctx, &n);
1461 if (!NT_STATUS_IS_OK(status)) {
1462 printf("LookupNames[0] failed - %s\n", nt_errstr(status));
1463 return status;
1466 init_lsa_String(&sname[0], "xxNONAMExx");
1467 n.in.num_names = 1;
1468 status = dcerpc_samr_LookupNames(p, tctx, &n);
1469 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1470 printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1471 if (NT_STATUS_IS_OK(status)) {
1472 return NT_STATUS_UNSUCCESSFUL;
1474 return status;
1477 init_lsa_String(&sname[0], "xxNONAMExx");
1478 init_lsa_String(&sname[1], "xxNONAME2xx");
1479 n.in.num_names = 2;
1480 status = dcerpc_samr_LookupNames(p, tctx, &n);
1481 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1482 printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1483 if (NT_STATUS_IS_OK(status)) {
1484 return NT_STATUS_UNSUCCESSFUL;
1486 return status;
1489 return NT_STATUS_OK;
1492 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p,
1493 struct torture_context *tctx,
1494 struct policy_handle *domain_handle,
1495 const char *name, struct policy_handle *user_handle)
1497 NTSTATUS status;
1498 struct samr_OpenUser r;
1499 uint32_t rid;
1501 status = test_LookupName(p, tctx, domain_handle, name, &rid);
1502 if (!NT_STATUS_IS_OK(status)) {
1503 return status;
1506 r.in.domain_handle = domain_handle;
1507 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1508 r.in.rid = rid;
1509 r.out.user_handle = user_handle;
1510 status = dcerpc_samr_OpenUser(p, tctx, &r);
1511 if (!NT_STATUS_IS_OK(status)) {
1512 printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1515 return status;
1518 #if 0
1519 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1520 struct torture_context *tctx,
1521 struct policy_handle *handle)
1523 NTSTATUS status;
1524 struct samr_ChangePasswordUser r;
1525 bool ret = true;
1526 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1527 struct policy_handle user_handle;
1528 char *oldpass = "test";
1529 char *newpass = "test2";
1530 uint8_t old_nt_hash[16], new_nt_hash[16];
1531 uint8_t old_lm_hash[16], new_lm_hash[16];
1533 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1534 if (!NT_STATUS_IS_OK(status)) {
1535 return false;
1538 printf("Testing ChangePasswordUser for user 'testuser'\n");
1540 printf("old password: %s\n", oldpass);
1541 printf("new password: %s\n", newpass);
1543 E_md4hash(oldpass, old_nt_hash);
1544 E_md4hash(newpass, new_nt_hash);
1545 E_deshash(oldpass, old_lm_hash);
1546 E_deshash(newpass, new_lm_hash);
1548 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1549 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1550 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1551 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1552 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1553 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1555 r.in.handle = &user_handle;
1556 r.in.lm_present = 1;
1557 r.in.old_lm_crypted = &hash1;
1558 r.in.new_lm_crypted = &hash2;
1559 r.in.nt_present = 1;
1560 r.in.old_nt_crypted = &hash3;
1561 r.in.new_nt_crypted = &hash4;
1562 r.in.cross1_present = 1;
1563 r.in.nt_cross = &hash5;
1564 r.in.cross2_present = 1;
1565 r.in.lm_cross = &hash6;
1567 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1570 ret = false;
1573 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1574 ret = false;
1577 return ret;
1579 #endif
1581 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1582 const char *acct_name,
1583 struct policy_handle *handle, char **password)
1585 NTSTATUS status;
1586 struct samr_ChangePasswordUser r;
1587 bool ret = true;
1588 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1589 struct policy_handle user_handle;
1590 char *oldpass;
1591 uint8_t old_nt_hash[16], new_nt_hash[16];
1592 uint8_t old_lm_hash[16], new_lm_hash[16];
1593 bool changed = true;
1595 char *newpass;
1596 struct samr_GetUserPwInfo pwp;
1597 struct samr_PwInfo info;
1598 int policy_min_pw_len = 0;
1600 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1601 if (!NT_STATUS_IS_OK(status)) {
1602 return false;
1604 pwp.in.user_handle = &user_handle;
1605 pwp.out.info = &info;
1607 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1608 if (NT_STATUS_IS_OK(status)) {
1609 policy_min_pw_len = pwp.out.info->min_password_length;
1611 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1613 torture_comment(tctx, "Testing ChangePasswordUser\n");
1615 torture_assert(tctx, *password != NULL,
1616 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1618 oldpass = *password;
1620 E_md4hash(oldpass, old_nt_hash);
1621 E_md4hash(newpass, new_nt_hash);
1622 E_deshash(oldpass, old_lm_hash);
1623 E_deshash(newpass, new_lm_hash);
1625 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1626 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1627 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1628 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1629 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1630 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1632 r.in.user_handle = &user_handle;
1633 r.in.lm_present = 1;
1634 /* Break the LM hash */
1635 hash1.hash[0]++;
1636 r.in.old_lm_crypted = &hash1;
1637 r.in.new_lm_crypted = &hash2;
1638 r.in.nt_present = 1;
1639 r.in.old_nt_crypted = &hash3;
1640 r.in.new_nt_crypted = &hash4;
1641 r.in.cross1_present = 1;
1642 r.in.nt_cross = &hash5;
1643 r.in.cross2_present = 1;
1644 r.in.lm_cross = &hash6;
1646 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1647 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1648 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1650 /* Unbreak the LM hash */
1651 hash1.hash[0]--;
1653 r.in.user_handle = &user_handle;
1654 r.in.lm_present = 1;
1655 r.in.old_lm_crypted = &hash1;
1656 r.in.new_lm_crypted = &hash2;
1657 /* Break the NT hash */
1658 hash3.hash[0]--;
1659 r.in.nt_present = 1;
1660 r.in.old_nt_crypted = &hash3;
1661 r.in.new_nt_crypted = &hash4;
1662 r.in.cross1_present = 1;
1663 r.in.nt_cross = &hash5;
1664 r.in.cross2_present = 1;
1665 r.in.lm_cross = &hash6;
1667 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1668 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1669 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1671 /* Unbreak the NT hash */
1672 hash3.hash[0]--;
1674 r.in.user_handle = &user_handle;
1675 r.in.lm_present = 1;
1676 r.in.old_lm_crypted = &hash1;
1677 r.in.new_lm_crypted = &hash2;
1678 r.in.nt_present = 1;
1679 r.in.old_nt_crypted = &hash3;
1680 r.in.new_nt_crypted = &hash4;
1681 r.in.cross1_present = 1;
1682 r.in.nt_cross = &hash5;
1683 r.in.cross2_present = 1;
1684 /* Break the LM cross */
1685 hash6.hash[0]++;
1686 r.in.lm_cross = &hash6;
1688 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1689 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1690 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1691 ret = false;
1694 /* Unbreak the LM cross */
1695 hash6.hash[0]--;
1697 r.in.user_handle = &user_handle;
1698 r.in.lm_present = 1;
1699 r.in.old_lm_crypted = &hash1;
1700 r.in.new_lm_crypted = &hash2;
1701 r.in.nt_present = 1;
1702 r.in.old_nt_crypted = &hash3;
1703 r.in.new_nt_crypted = &hash4;
1704 r.in.cross1_present = 1;
1705 /* Break the NT cross */
1706 hash5.hash[0]++;
1707 r.in.nt_cross = &hash5;
1708 r.in.cross2_present = 1;
1709 r.in.lm_cross = &hash6;
1711 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1712 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1713 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1714 ret = false;
1717 /* Unbreak the NT cross */
1718 hash5.hash[0]--;
1721 /* Reset the hashes to not broken values */
1722 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1723 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1724 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1725 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1726 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1727 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1729 r.in.user_handle = &user_handle;
1730 r.in.lm_present = 1;
1731 r.in.old_lm_crypted = &hash1;
1732 r.in.new_lm_crypted = &hash2;
1733 r.in.nt_present = 1;
1734 r.in.old_nt_crypted = &hash3;
1735 r.in.new_nt_crypted = &hash4;
1736 r.in.cross1_present = 1;
1737 r.in.nt_cross = &hash5;
1738 r.in.cross2_present = 0;
1739 r.in.lm_cross = NULL;
1741 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1742 if (NT_STATUS_IS_OK(status)) {
1743 changed = true;
1744 *password = newpass;
1745 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1746 printf("ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1747 ret = false;
1750 oldpass = newpass;
1751 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1753 E_md4hash(oldpass, old_nt_hash);
1754 E_md4hash(newpass, new_nt_hash);
1755 E_deshash(oldpass, old_lm_hash);
1756 E_deshash(newpass, new_lm_hash);
1759 /* Reset the hashes to not broken values */
1760 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1761 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1762 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1763 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1764 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1765 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1767 r.in.user_handle = &user_handle;
1768 r.in.lm_present = 1;
1769 r.in.old_lm_crypted = &hash1;
1770 r.in.new_lm_crypted = &hash2;
1771 r.in.nt_present = 1;
1772 r.in.old_nt_crypted = &hash3;
1773 r.in.new_nt_crypted = &hash4;
1774 r.in.cross1_present = 0;
1775 r.in.nt_cross = NULL;
1776 r.in.cross2_present = 1;
1777 r.in.lm_cross = &hash6;
1779 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1780 if (NT_STATUS_IS_OK(status)) {
1781 changed = true;
1782 *password = newpass;
1783 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1784 printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1785 ret = false;
1788 oldpass = newpass;
1789 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1791 E_md4hash(oldpass, old_nt_hash);
1792 E_md4hash(newpass, new_nt_hash);
1793 E_deshash(oldpass, old_lm_hash);
1794 E_deshash(newpass, new_lm_hash);
1797 /* Reset the hashes to not broken values */
1798 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1799 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1800 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1801 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1802 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1803 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1805 r.in.user_handle = &user_handle;
1806 r.in.lm_present = 1;
1807 r.in.old_lm_crypted = &hash1;
1808 r.in.new_lm_crypted = &hash2;
1809 r.in.nt_present = 1;
1810 r.in.old_nt_crypted = &hash3;
1811 r.in.new_nt_crypted = &hash4;
1812 r.in.cross1_present = 1;
1813 r.in.nt_cross = &hash5;
1814 r.in.cross2_present = 1;
1815 r.in.lm_cross = &hash6;
1817 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1818 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1819 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1820 } else if (!NT_STATUS_IS_OK(status)) {
1821 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1822 ret = false;
1823 } else {
1824 changed = true;
1825 *password = newpass;
1828 r.in.user_handle = &user_handle;
1829 r.in.lm_present = 1;
1830 r.in.old_lm_crypted = &hash1;
1831 r.in.new_lm_crypted = &hash2;
1832 r.in.nt_present = 1;
1833 r.in.old_nt_crypted = &hash3;
1834 r.in.new_nt_crypted = &hash4;
1835 r.in.cross1_present = 1;
1836 r.in.nt_cross = &hash5;
1837 r.in.cross2_present = 1;
1838 r.in.lm_cross = &hash6;
1840 if (changed) {
1841 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1842 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1843 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1844 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1845 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1846 ret = false;
1851 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1852 ret = false;
1855 return ret;
1859 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1860 const char *acct_name,
1861 struct policy_handle *handle, char **password)
1863 NTSTATUS status;
1864 struct samr_OemChangePasswordUser2 r;
1865 bool ret = true;
1866 struct samr_Password lm_verifier;
1867 struct samr_CryptPassword lm_pass;
1868 struct lsa_AsciiString server, account, account_bad;
1869 char *oldpass;
1870 char *newpass;
1871 uint8_t old_lm_hash[16], new_lm_hash[16];
1873 struct samr_GetDomPwInfo dom_pw_info;
1874 struct samr_PwInfo info;
1875 int policy_min_pw_len = 0;
1877 struct lsa_String domain_name;
1879 domain_name.string = "";
1880 dom_pw_info.in.domain_name = &domain_name;
1881 dom_pw_info.out.info = &info;
1883 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1885 torture_assert(tctx, *password != NULL,
1886 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1888 oldpass = *password;
1890 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1891 if (NT_STATUS_IS_OK(status)) {
1892 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1895 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1897 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1898 account.string = acct_name;
1900 E_deshash(oldpass, old_lm_hash);
1901 E_deshash(newpass, new_lm_hash);
1903 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1904 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1905 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1907 r.in.server = &server;
1908 r.in.account = &account;
1909 r.in.password = &lm_pass;
1910 r.in.hash = &lm_verifier;
1912 /* Break the verification */
1913 lm_verifier.hash[0]++;
1915 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1917 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1918 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1919 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1920 nt_errstr(status));
1921 ret = false;
1924 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1925 /* Break the old password */
1926 old_lm_hash[0]++;
1927 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1928 /* unbreak it for the next operation */
1929 old_lm_hash[0]--;
1930 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1932 r.in.server = &server;
1933 r.in.account = &account;
1934 r.in.password = &lm_pass;
1935 r.in.hash = &lm_verifier;
1937 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1939 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1940 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1941 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1942 nt_errstr(status));
1943 ret = false;
1946 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1947 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1949 r.in.server = &server;
1950 r.in.account = &account;
1951 r.in.password = &lm_pass;
1952 r.in.hash = NULL;
1954 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1956 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1957 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1958 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1959 nt_errstr(status));
1960 ret = false;
1963 /* This shouldn't be a valid name */
1964 account_bad.string = TEST_ACCOUNT_NAME "XX";
1965 r.in.account = &account_bad;
1967 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1969 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1970 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1971 nt_errstr(status));
1972 ret = false;
1975 /* This shouldn't be a valid name */
1976 account_bad.string = TEST_ACCOUNT_NAME "XX";
1977 r.in.account = &account_bad;
1978 r.in.password = &lm_pass;
1979 r.in.hash = &lm_verifier;
1981 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1983 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1984 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1985 nt_errstr(status));
1986 ret = false;
1989 /* This shouldn't be a valid name */
1990 account_bad.string = TEST_ACCOUNT_NAME "XX";
1991 r.in.account = &account_bad;
1992 r.in.password = NULL;
1993 r.in.hash = &lm_verifier;
1995 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1997 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1998 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
1999 nt_errstr(status));
2000 ret = false;
2003 E_deshash(oldpass, old_lm_hash);
2004 E_deshash(newpass, new_lm_hash);
2006 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2007 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2008 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2010 r.in.server = &server;
2011 r.in.account = &account;
2012 r.in.password = &lm_pass;
2013 r.in.hash = &lm_verifier;
2015 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2016 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2017 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2018 } else if (!NT_STATUS_IS_OK(status)) {
2019 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
2020 ret = false;
2021 } else {
2022 *password = newpass;
2025 return ret;
2029 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2030 const char *acct_name,
2031 char **password,
2032 char *newpass, bool allow_password_restriction)
2034 NTSTATUS status;
2035 struct samr_ChangePasswordUser2 r;
2036 bool ret = true;
2037 struct lsa_String server, account;
2038 struct samr_CryptPassword nt_pass, lm_pass;
2039 struct samr_Password nt_verifier, lm_verifier;
2040 char *oldpass;
2041 uint8_t old_nt_hash[16], new_nt_hash[16];
2042 uint8_t old_lm_hash[16], new_lm_hash[16];
2044 struct samr_GetDomPwInfo dom_pw_info;
2045 struct samr_PwInfo info;
2047 struct lsa_String domain_name;
2049 domain_name.string = "";
2050 dom_pw_info.in.domain_name = &domain_name;
2051 dom_pw_info.out.info = &info;
2053 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2055 torture_assert(tctx, *password != NULL,
2056 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2057 oldpass = *password;
2059 if (!newpass) {
2060 int policy_min_pw_len = 0;
2061 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
2062 if (NT_STATUS_IS_OK(status)) {
2063 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2066 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2069 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2070 init_lsa_String(&account, acct_name);
2072 E_md4hash(oldpass, old_nt_hash);
2073 E_md4hash(newpass, new_nt_hash);
2075 E_deshash(oldpass, old_lm_hash);
2076 E_deshash(newpass, new_lm_hash);
2078 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2079 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2080 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2082 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2083 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2084 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2086 r.in.server = &server;
2087 r.in.account = &account;
2088 r.in.nt_password = &nt_pass;
2089 r.in.nt_verifier = &nt_verifier;
2090 r.in.lm_change = 1;
2091 r.in.lm_password = &lm_pass;
2092 r.in.lm_verifier = &lm_verifier;
2094 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
2095 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2096 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2097 } else if (!NT_STATUS_IS_OK(status)) {
2098 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2099 ret = false;
2100 } else {
2101 *password = newpass;
2104 return ret;
2108 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2109 const char *account_string,
2110 int policy_min_pw_len,
2111 char **password,
2112 const char *newpass,
2113 NTTIME last_password_change,
2114 bool handle_reject_reason)
2116 NTSTATUS status;
2117 struct samr_ChangePasswordUser3 r;
2118 bool ret = true;
2119 struct lsa_String server, account, account_bad;
2120 struct samr_CryptPassword nt_pass, lm_pass;
2121 struct samr_Password nt_verifier, lm_verifier;
2122 char *oldpass;
2123 uint8_t old_nt_hash[16], new_nt_hash[16];
2124 uint8_t old_lm_hash[16], new_lm_hash[16];
2125 NTTIME t;
2126 struct samr_DomInfo1 *dominfo = NULL;
2127 struct samr_ChangeReject *reject = NULL;
2129 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2131 if (newpass == NULL) {
2132 do {
2133 if (policy_min_pw_len == 0) {
2134 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2135 } else {
2136 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2138 } while (check_password_quality(newpass) == false);
2139 } else {
2140 torture_comment(tctx, "Using password '%s'\n", newpass);
2143 torture_assert(tctx, *password != NULL,
2144 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2146 oldpass = *password;
2147 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2148 init_lsa_String(&account, account_string);
2150 E_md4hash(oldpass, old_nt_hash);
2151 E_md4hash(newpass, new_nt_hash);
2153 E_deshash(oldpass, old_lm_hash);
2154 E_deshash(newpass, new_lm_hash);
2156 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2157 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2158 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2160 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2161 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2162 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2164 /* Break the verification */
2165 nt_verifier.hash[0]++;
2167 r.in.server = &server;
2168 r.in.account = &account;
2169 r.in.nt_password = &nt_pass;
2170 r.in.nt_verifier = &nt_verifier;
2171 r.in.lm_change = 1;
2172 r.in.lm_password = &lm_pass;
2173 r.in.lm_verifier = &lm_verifier;
2174 r.in.password3 = NULL;
2175 r.out.dominfo = &dominfo;
2176 r.out.reject = &reject;
2178 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2179 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2180 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2181 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2182 nt_errstr(status));
2183 ret = false;
2186 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2187 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2188 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2190 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2191 /* Break the NT hash */
2192 old_nt_hash[0]++;
2193 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2194 /* Unbreak it again */
2195 old_nt_hash[0]--;
2196 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2198 r.in.server = &server;
2199 r.in.account = &account;
2200 r.in.nt_password = &nt_pass;
2201 r.in.nt_verifier = &nt_verifier;
2202 r.in.lm_change = 1;
2203 r.in.lm_password = &lm_pass;
2204 r.in.lm_verifier = &lm_verifier;
2205 r.in.password3 = NULL;
2206 r.out.dominfo = &dominfo;
2207 r.out.reject = &reject;
2209 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2210 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2211 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2212 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2213 nt_errstr(status));
2214 ret = false;
2217 /* This shouldn't be a valid name */
2218 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2220 r.in.account = &account_bad;
2221 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2222 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2223 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2224 nt_errstr(status));
2225 ret = false;
2228 E_md4hash(oldpass, old_nt_hash);
2229 E_md4hash(newpass, new_nt_hash);
2231 E_deshash(oldpass, old_lm_hash);
2232 E_deshash(newpass, new_lm_hash);
2234 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2235 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2236 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2238 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2239 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2240 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2242 r.in.server = &server;
2243 r.in.account = &account;
2244 r.in.nt_password = &nt_pass;
2245 r.in.nt_verifier = &nt_verifier;
2246 r.in.lm_change = 1;
2247 r.in.lm_password = &lm_pass;
2248 r.in.lm_verifier = &lm_verifier;
2249 r.in.password3 = NULL;
2250 r.out.dominfo = &dominfo;
2251 r.out.reject = &reject;
2253 unix_to_nt_time(&t, time(NULL));
2255 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2257 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2258 && dominfo
2259 && reject
2260 && handle_reject_reason
2261 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2262 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2264 if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
2265 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2266 SAMR_REJECT_OTHER, reject->reason);
2267 return false;
2271 /* We tested the order of precendence which is as follows:
2273 * pwd min_age
2274 * pwd length
2275 * pwd complexity
2276 * pwd history
2278 Guenther */
2280 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2281 (last_password_change + dominfo->min_password_age > t)) {
2283 if (reject->reason != SAMR_REJECT_OTHER) {
2284 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2285 SAMR_REJECT_OTHER, reject->reason);
2286 return false;
2289 } else if ((dominfo->min_password_length > 0) &&
2290 (strlen(newpass) < dominfo->min_password_length)) {
2292 if (reject->reason != SAMR_REJECT_TOO_SHORT) {
2293 printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
2294 SAMR_REJECT_TOO_SHORT, reject->reason);
2295 return false;
2298 } else if ((dominfo->password_history_length > 0) &&
2299 strequal(oldpass, newpass)) {
2301 if (reject->reason != SAMR_REJECT_IN_HISTORY) {
2302 printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
2303 SAMR_REJECT_IN_HISTORY, reject->reason);
2304 return false;
2306 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2308 if (reject->reason != SAMR_REJECT_COMPLEXITY) {
2309 printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
2310 SAMR_REJECT_COMPLEXITY, reject->reason);
2311 return false;
2316 if (reject->reason == SAMR_REJECT_TOO_SHORT) {
2317 /* retry with adjusted size */
2318 return test_ChangePasswordUser3(p, tctx, account_string,
2319 dominfo->min_password_length,
2320 password, NULL, 0, false);
2324 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2325 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2326 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2327 SAMR_REJECT_OTHER, reject->reason);
2328 return false;
2330 /* Perhaps the server has a 'min password age' set? */
2332 } else {
2333 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2334 *password = talloc_strdup(tctx, newpass);
2337 return ret;
2340 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2341 const char *account_string,
2342 struct policy_handle *handle,
2343 char **password)
2345 NTSTATUS status;
2346 struct samr_ChangePasswordUser3 r;
2347 struct samr_SetUserInfo s;
2348 union samr_UserInfo u;
2349 DATA_BLOB session_key;
2350 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2351 uint8_t confounder[16];
2352 struct MD5Context ctx;
2354 bool ret = true;
2355 struct lsa_String server, account;
2356 struct samr_CryptPassword nt_pass;
2357 struct samr_Password nt_verifier;
2358 DATA_BLOB new_random_pass;
2359 char *newpass;
2360 char *oldpass;
2361 uint8_t old_nt_hash[16], new_nt_hash[16];
2362 NTTIME t;
2363 struct samr_DomInfo1 *dominfo = NULL;
2364 struct samr_ChangeReject *reject = NULL;
2366 new_random_pass = samr_very_rand_pass(tctx, 128);
2368 torture_assert(tctx, *password != NULL,
2369 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2371 oldpass = *password;
2372 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2373 init_lsa_String(&account, account_string);
2375 s.in.user_handle = handle;
2376 s.in.info = &u;
2377 s.in.level = 25;
2379 ZERO_STRUCT(u);
2381 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2383 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2385 status = dcerpc_fetch_session_key(p, &session_key);
2386 if (!NT_STATUS_IS_OK(status)) {
2387 printf("SetUserInfo level %u - no session key - %s\n",
2388 s.in.level, nt_errstr(status));
2389 return false;
2392 generate_random_buffer((uint8_t *)confounder, 16);
2394 MD5Init(&ctx);
2395 MD5Update(&ctx, confounder, 16);
2396 MD5Update(&ctx, session_key.data, session_key.length);
2397 MD5Final(confounded_session_key.data, &ctx);
2399 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2400 memcpy(&u.info25.password.data[516], confounder, 16);
2402 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2404 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2405 if (!NT_STATUS_IS_OK(status)) {
2406 printf("SetUserInfo level %u failed - %s\n",
2407 s.in.level, nt_errstr(status));
2408 ret = false;
2411 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2413 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2415 new_random_pass = samr_very_rand_pass(tctx, 128);
2417 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2419 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2420 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2421 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2423 r.in.server = &server;
2424 r.in.account = &account;
2425 r.in.nt_password = &nt_pass;
2426 r.in.nt_verifier = &nt_verifier;
2427 r.in.lm_change = 0;
2428 r.in.lm_password = NULL;
2429 r.in.lm_verifier = NULL;
2430 r.in.password3 = NULL;
2431 r.out.dominfo = &dominfo;
2432 r.out.reject = &reject;
2434 unix_to_nt_time(&t, time(NULL));
2436 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2438 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2439 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2440 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2441 SAMR_REJECT_OTHER, reject->reason);
2442 return false;
2444 /* Perhaps the server has a 'min password age' set? */
2446 } else if (!NT_STATUS_IS_OK(status)) {
2447 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2448 ret = false;
2451 newpass = samr_rand_pass(tctx, 128);
2453 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2455 E_md4hash(newpass, new_nt_hash);
2457 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2458 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2459 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2461 r.in.server = &server;
2462 r.in.account = &account;
2463 r.in.nt_password = &nt_pass;
2464 r.in.nt_verifier = &nt_verifier;
2465 r.in.lm_change = 0;
2466 r.in.lm_password = NULL;
2467 r.in.lm_verifier = NULL;
2468 r.in.password3 = NULL;
2469 r.out.dominfo = &dominfo;
2470 r.out.reject = &reject;
2472 unix_to_nt_time(&t, time(NULL));
2474 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2476 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2477 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2478 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2479 SAMR_REJECT_OTHER, reject->reason);
2480 return false;
2482 /* Perhaps the server has a 'min password age' set? */
2484 } else {
2485 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2486 *password = talloc_strdup(tctx, newpass);
2489 return ret;
2493 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2494 struct policy_handle *alias_handle)
2496 struct samr_GetMembersInAlias r;
2497 struct lsa_SidArray sids;
2498 NTSTATUS status;
2500 torture_comment(tctx, "Testing GetMembersInAlias\n");
2502 r.in.alias_handle = alias_handle;
2503 r.out.sids = &sids;
2505 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2506 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2508 return true;
2511 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2512 struct policy_handle *alias_handle,
2513 const struct dom_sid *domain_sid)
2515 struct samr_AddAliasMember r;
2516 struct samr_DeleteAliasMember d;
2517 NTSTATUS status;
2518 struct dom_sid *sid;
2520 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2522 torture_comment(tctx, "testing AddAliasMember\n");
2523 r.in.alias_handle = alias_handle;
2524 r.in.sid = sid;
2526 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2527 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2529 d.in.alias_handle = alias_handle;
2530 d.in.sid = sid;
2532 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2533 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2535 return true;
2538 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2539 struct policy_handle *alias_handle)
2541 struct samr_AddMultipleMembersToAlias a;
2542 struct samr_RemoveMultipleMembersFromAlias r;
2543 NTSTATUS status;
2544 struct lsa_SidArray sids;
2546 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2547 a.in.alias_handle = alias_handle;
2548 a.in.sids = &sids;
2550 sids.num_sids = 3;
2551 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2553 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2554 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2555 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2557 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2558 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2561 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2562 r.in.alias_handle = alias_handle;
2563 r.in.sids = &sids;
2565 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2566 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2568 /* strange! removing twice doesn't give any error */
2569 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2570 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2572 /* but removing an alias that isn't there does */
2573 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2575 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2576 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2578 return true;
2581 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2582 struct policy_handle *user_handle)
2584 struct samr_TestPrivateFunctionsUser r;
2585 NTSTATUS status;
2587 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2589 r.in.user_handle = user_handle;
2591 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2592 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2594 return true;
2597 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2598 struct torture_context *tctx,
2599 struct policy_handle *handle,
2600 bool use_info2,
2601 NTTIME *pwdlastset)
2603 NTSTATUS status;
2604 uint16_t levels[] = { /* 3, */ 5, 21 };
2605 int i;
2606 NTTIME pwdlastset3 = 0;
2607 NTTIME pwdlastset5 = 0;
2608 NTTIME pwdlastset21 = 0;
2610 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2611 use_info2 ? "2":"");
2613 for (i=0; i<ARRAY_SIZE(levels); i++) {
2615 struct samr_QueryUserInfo r;
2616 struct samr_QueryUserInfo2 r2;
2617 union samr_UserInfo *info;
2619 if (use_info2) {
2620 r2.in.user_handle = handle;
2621 r2.in.level = levels[i];
2622 r2.out.info = &info;
2623 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2625 } else {
2626 r.in.user_handle = handle;
2627 r.in.level = levels[i];
2628 r.out.info = &info;
2629 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2632 if (!NT_STATUS_IS_OK(status) &&
2633 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2634 printf("QueryUserInfo%s level %u failed - %s\n",
2635 use_info2 ? "2":"", levels[i], nt_errstr(status));
2636 return false;
2639 switch (levels[i]) {
2640 case 3:
2641 pwdlastset3 = info->info3.last_password_change;
2642 break;
2643 case 5:
2644 pwdlastset5 = info->info5.last_password_change;
2645 break;
2646 case 21:
2647 pwdlastset21 = info->info21.last_password_change;
2648 break;
2649 default:
2650 return false;
2653 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2654 "pwdlastset mixup"); */
2655 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2656 "pwdlastset mixup");
2658 *pwdlastset = pwdlastset21;
2660 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2662 return true;
2665 static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *tctx,
2666 struct cli_credentials *machine_credentials,
2667 struct cli_credentials *test_credentials,
2668 struct creds_CredentialState *creds,
2669 NTSTATUS expected_result)
2671 NTSTATUS status;
2672 struct netr_LogonSamLogon r;
2673 struct netr_Authenticator auth, auth2;
2674 union netr_LogonLevel logon;
2675 union netr_Validation validation;
2676 uint8_t authoritative;
2677 struct netr_NetworkInfo ninfo;
2678 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2679 int flags = CLI_CRED_NTLM_AUTH;
2681 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2682 flags |= CLI_CRED_LANMAN_AUTH;
2685 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2686 flags |= CLI_CRED_NTLMv2_AUTH;
2689 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2690 &ninfo.identity_info.account_name.string,
2691 &ninfo.identity_info.domain_name.string);
2693 generate_random_buffer(ninfo.challenge,
2694 sizeof(ninfo.challenge));
2695 chal = data_blob_const(ninfo.challenge,
2696 sizeof(ninfo.challenge));
2698 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(machine_credentials),
2699 cli_credentials_get_domain(machine_credentials));
2701 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2702 &flags,
2703 chal,
2704 names_blob,
2705 &lm_resp, &nt_resp,
2706 NULL, NULL);
2707 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2709 ninfo.lm.data = lm_resp.data;
2710 ninfo.lm.length = lm_resp.length;
2712 ninfo.nt.data = nt_resp.data;
2713 ninfo.nt.length = nt_resp.length;
2715 ninfo.identity_info.parameter_control =
2716 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2717 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2718 ninfo.identity_info.logon_id_low = 0;
2719 ninfo.identity_info.logon_id_high = 0;
2720 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(machine_credentials);
2722 logon.network = &ninfo;
2724 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2725 r.in.computer_name = cli_credentials_get_workstation(machine_credentials);
2726 r.in.credential = &auth;
2727 r.in.return_authenticator = &auth2;
2728 r.in.logon_level = 2;
2729 r.in.logon = &logon;
2730 r.out.validation = &validation;
2731 r.out.authoritative = &authoritative;
2733 d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
2735 ZERO_STRUCT(auth2);
2736 creds_client_authenticator(creds, &auth);
2738 r.in.validation_level = 2;
2740 status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
2741 if (!NT_STATUS_IS_OK(status)) {
2742 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogon failed");
2743 return true;
2744 } else {
2745 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
2748 torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred),
2749 "Credential chaining failed");
2751 return true;
2754 static bool test_SamLogon(struct torture_context *tctx,
2755 struct dcerpc_pipe *p,
2756 struct cli_credentials *machine_credentials,
2757 struct cli_credentials *test_credentials,
2758 NTSTATUS expected_result)
2760 struct creds_CredentialState *creds;
2762 if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
2763 return false;
2766 return test_SamLogon_Creds(p, tctx, machine_credentials, test_credentials,
2767 creds, expected_result);
2770 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2771 struct dcerpc_pipe *p,
2772 struct cli_credentials *machine_creds,
2773 const char *acct_name,
2774 char *password,
2775 NTSTATUS expected_samlogon_result)
2777 bool ret = true;
2778 struct cli_credentials *test_credentials;
2780 test_credentials = cli_credentials_init(tctx);
2782 cli_credentials_set_workstation(test_credentials,
2783 TEST_ACCOUNT_NAME_PWD, CRED_SPECIFIED);
2784 cli_credentials_set_domain(test_credentials,
2785 lp_workgroup(tctx->lp_ctx), CRED_SPECIFIED);
2786 cli_credentials_set_username(test_credentials,
2787 acct_name, CRED_SPECIFIED);
2788 cli_credentials_set_password(test_credentials,
2789 password, CRED_SPECIFIED);
2790 cli_credentials_set_secure_channel_type(test_credentials, SEC_CHAN_BDC);
2792 printf("testing samlogon as %s@%s password: %s\n",
2793 acct_name, TEST_ACCOUNT_NAME_PWD, password);
2795 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
2796 expected_samlogon_result)) {
2797 torture_warning(tctx, "new password did not work\n");
2798 ret = false;
2801 return ret;
2804 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2805 struct dcerpc_pipe *np,
2806 struct torture_context *tctx,
2807 struct policy_handle *handle,
2808 uint16_t level,
2809 uint32_t fields_present,
2810 uint8_t password_expired,
2811 bool *matched_expected_error,
2812 bool use_setinfo2,
2813 const char *acct_name,
2814 char **password,
2815 struct cli_credentials *machine_creds,
2816 bool use_queryinfo2,
2817 NTTIME *pwdlastset,
2818 NTSTATUS expected_samlogon_result)
2820 const char *fields = NULL;
2821 bool ret = true;
2823 switch (level) {
2824 case 21:
2825 case 23:
2826 case 25:
2827 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2828 fields_present);
2829 break;
2830 default:
2831 break;
2834 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2835 "(password_expired: %d) %s\n",
2836 use_setinfo2 ? "2":"", level, password_expired,
2837 fields ? fields : "");
2839 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2840 fields_present,
2841 password,
2842 password_expired,
2843 use_setinfo2,
2844 matched_expected_error)) {
2845 ret = false;
2848 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2849 use_queryinfo2,
2850 pwdlastset)) {
2851 ret = false;
2854 if (*matched_expected_error == true) {
2855 return ret;
2858 if (!test_SamLogon_with_creds(tctx, np,
2859 machine_creds,
2860 acct_name,
2861 *password,
2862 expected_samlogon_result)) {
2863 ret = false;
2866 return ret;
2869 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2870 struct torture_context *tctx,
2871 uint32_t acct_flags,
2872 const char *acct_name,
2873 struct policy_handle *handle,
2874 char **password,
2875 struct cli_credentials *machine_credentials)
2877 int s = 0, q = 0, f = 0, l = 0, z = 0;
2878 bool ret = true;
2879 int delay = 500000;
2880 bool set_levels[] = { false, true };
2881 bool query_levels[] = { false, true };
2882 uint32_t levels[] = { 18, 21, 23, 24, 25, 26 };
2883 uint32_t nonzeros[] = { 1, 24 };
2884 uint32_t fields_present[] = {
2886 SAMR_FIELD_EXPIRED_FLAG,
2887 SAMR_FIELD_LAST_PWD_CHANGE,
2888 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2889 SAMR_FIELD_COMMENT,
2890 SAMR_FIELD_NT_PASSWORD_PRESENT,
2891 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2892 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2893 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2894 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2895 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2896 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2898 NTSTATUS status;
2899 struct dcerpc_pipe *np = NULL;
2901 if (torture_setting_bool(tctx, "samba3", false)) {
2902 delay = 1000000;
2903 printf("Samba3 has second granularity, setting delay to: %d\n",
2904 delay);
2907 status = torture_rpc_connection(tctx, &np, &ndr_table_netlogon);
2908 if (!NT_STATUS_IS_OK(status)) {
2909 return false;
2912 /* set to 1 to enable testing for all possible opcode
2913 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2914 combinations */
2915 #if 0
2916 #define TEST_SET_LEVELS 1
2917 #define TEST_QUERY_LEVELS 1
2918 #endif
2919 for (l=0; l<ARRAY_SIZE(levels); l++) {
2920 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
2921 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2922 #ifdef TEST_SET_LEVELS
2923 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2924 #endif
2925 #ifdef TEST_QUERY_LEVELS
2926 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2927 #endif
2928 NTTIME pwdlastset_old = 0;
2929 NTTIME pwdlastset_new = 0;
2930 bool matched_expected_error = false;
2931 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
2933 torture_comment(tctx, "------------------------------\n"
2934 "Testing pwdLastSet attribute for flags: 0x%08x "
2935 "(s: %d (l: %d), q: %d)\n",
2936 acct_flags, s, levels[l], q);
2938 switch (levels[l]) {
2939 case 21:
2940 case 23:
2941 case 25:
2942 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2943 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
2944 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
2946 break;
2950 /* set #1 */
2952 /* set a password and force password change (pwdlastset 0) by
2953 * setting the password expired flag to a non-0 value */
2955 if (!test_SetPassword_level(p, np, tctx, handle,
2956 levels[l],
2957 fields_present[f],
2958 nonzeros[z],
2959 &matched_expected_error,
2960 set_levels[s],
2961 acct_name,
2962 password,
2963 machine_credentials,
2964 query_levels[q],
2965 &pwdlastset_old,
2966 expected_samlogon_result)) {
2967 ret = false;
2970 if (matched_expected_error == true) {
2971 /* skipping on expected failure */
2972 continue;
2975 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2976 * set without the SAMR_FIELD_EXPIRED_FLAG */
2978 switch (levels[l]) {
2979 case 21:
2980 case 23:
2981 case 25:
2982 if ((pwdlastset_new != 0) &&
2983 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
2984 torture_comment(tctx, "not considering a non-0 "
2985 "pwdLastSet as a an error as the "
2986 "SAMR_FIELD_EXPIRED_FLAG has not "
2987 "been set\n");
2988 break;
2990 default:
2991 if (pwdlastset_new != 0) {
2992 torture_warning(tctx, "pwdLastSet test failed: "
2993 "expected pwdLastSet 0 but got %lld\n",
2994 pwdlastset_old);
2995 ret = false;
2997 break;
3000 switch (levels[l]) {
3001 case 21:
3002 case 23:
3003 case 25:
3004 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3005 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3006 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3007 (pwdlastset_old >= pwdlastset_new)) {
3008 torture_warning(tctx, "pwdlastset not increasing\n");
3009 ret = false;
3011 break;
3012 default:
3013 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3014 (pwdlastset_old >= pwdlastset_new)) {
3015 torture_warning(tctx, "pwdlastset not increasing\n");
3016 ret = false;
3018 break;
3021 usleep(delay);
3023 /* set #2 */
3025 /* set a password, pwdlastset needs to get updated (increased
3026 * value), password_expired value used here is 0 */
3028 if (!test_SetPassword_level(p, np, tctx, handle,
3029 levels[l],
3030 fields_present[f],
3032 &matched_expected_error,
3033 set_levels[s],
3034 acct_name,
3035 password,
3036 machine_credentials,
3037 query_levels[q],
3038 &pwdlastset_new,
3039 expected_samlogon_result)) {
3040 ret = false;
3043 /* when a password has been changed, pwdlastset must not be 0 afterwards
3044 * and must be larger then the old value */
3046 switch (levels[l]) {
3047 case 21:
3048 case 23:
3049 case 25:
3051 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3052 * password has been changed, old and new pwdlastset
3053 * need to be the same value */
3055 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3056 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3057 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3059 torture_assert_int_equal(tctx, pwdlastset_old,
3060 pwdlastset_new, "pwdlastset must be equal");
3061 break;
3063 default:
3064 if (pwdlastset_old >= pwdlastset_new) {
3065 torture_warning(tctx, "pwdLastSet test failed: "
3066 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3067 pwdlastset_old, pwdlastset_new);
3068 ret = false;
3070 if (pwdlastset_new == 0) {
3071 torture_warning(tctx, "pwdLastSet test failed: "
3072 "expected non-0 pwdlastset, got: %lld\n",
3073 pwdlastset_new);
3074 ret = false;
3078 switch (levels[l]) {
3079 case 21:
3080 case 23:
3081 case 25:
3082 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3083 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3084 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3085 (pwdlastset_old >= pwdlastset_new)) {
3086 torture_warning(tctx, "pwdlastset not increasing\n");
3087 ret = false;
3089 break;
3090 default:
3091 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3092 (pwdlastset_old >= pwdlastset_new)) {
3093 torture_warning(tctx, "pwdlastset not increasing\n");
3094 ret = false;
3096 break;
3099 pwdlastset_old = pwdlastset_new;
3101 usleep(delay);
3103 /* set #2b */
3105 /* set a password, pwdlastset needs to get updated (increased
3106 * value), password_expired value used here is 0 */
3108 if (!test_SetPassword_level(p, np, tctx, handle,
3109 levels[l],
3110 fields_present[f],
3112 &matched_expected_error,
3113 set_levels[s],
3114 acct_name,
3115 password,
3116 machine_credentials,
3117 query_levels[q],
3118 &pwdlastset_new,
3119 expected_samlogon_result)) {
3120 ret = false;
3123 /* when a password has been changed, pwdlastset must not be 0 afterwards
3124 * and must be larger then the old value */
3126 switch (levels[l]) {
3127 case 21:
3128 case 23:
3129 case 25:
3131 /* if no password has been changed, old and new pwdlastset
3132 * need to be the same value */
3134 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3135 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3137 torture_assert_int_equal(tctx, pwdlastset_old,
3138 pwdlastset_new, "pwdlastset must be equal");
3139 break;
3141 default:
3142 if (pwdlastset_old >= pwdlastset_new) {
3143 torture_warning(tctx, "pwdLastSet test failed: "
3144 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3145 pwdlastset_old, pwdlastset_new);
3146 ret = false;
3148 if (pwdlastset_new == 0) {
3149 torture_warning(tctx, "pwdLastSet test failed: "
3150 "expected non-0 pwdlastset, got: %lld\n",
3151 pwdlastset_new);
3152 ret = false;
3156 /* set #3 */
3158 /* set a password and force password change (pwdlastset 0) by
3159 * setting the password expired flag to a non-0 value */
3161 if (!test_SetPassword_level(p, np, tctx, handle,
3162 levels[l],
3163 fields_present[f],
3164 nonzeros[z],
3165 &matched_expected_error,
3166 set_levels[s],
3167 acct_name,
3168 password,
3169 machine_credentials,
3170 query_levels[q],
3171 &pwdlastset_new,
3172 expected_samlogon_result)) {
3173 ret = false;
3176 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3177 * set without the SAMR_FIELD_EXPIRED_FLAG */
3179 switch (levels[l]) {
3180 case 21:
3181 case 23:
3182 case 25:
3183 if ((pwdlastset_new != 0) &&
3184 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3185 torture_comment(tctx, "not considering a non-0 "
3186 "pwdLastSet as a an error as the "
3187 "SAMR_FIELD_EXPIRED_FLAG has not "
3188 "been set\n");
3189 break;
3192 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3193 * password has been changed, old and new pwdlastset
3194 * need to be the same value */
3196 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3197 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3198 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3200 torture_assert_int_equal(tctx, pwdlastset_old,
3201 pwdlastset_new, "pwdlastset must be equal");
3202 break;
3204 default:
3206 if (pwdlastset_old == pwdlastset_new) {
3207 torture_warning(tctx, "pwdLastSet test failed: "
3208 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3209 pwdlastset_old, pwdlastset_new);
3210 ret = false;
3213 if (pwdlastset_new != 0) {
3214 torture_warning(tctx, "pwdLastSet test failed: "
3215 "expected pwdLastSet 0, got %lld\n",
3216 pwdlastset_old);
3217 ret = false;
3219 break;
3222 switch (levels[l]) {
3223 case 21:
3224 case 23:
3225 case 25:
3226 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3227 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3228 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3229 (pwdlastset_old >= pwdlastset_new)) {
3230 torture_warning(tctx, "pwdlastset not increasing\n");
3231 ret = false;
3233 break;
3234 default:
3235 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3236 (pwdlastset_old >= pwdlastset_new)) {
3237 torture_warning(tctx, "pwdlastset not increasing\n");
3238 ret = false;
3240 break;
3243 /* if the level we are testing does not have a fields_present
3244 * field, skip all fields present tests by setting f to to
3245 * arraysize */
3246 switch (levels[l]) {
3247 case 18:
3248 case 24:
3249 case 26:
3250 f = ARRAY_SIZE(fields_present);
3251 break;
3254 #ifdef TEST_QUERY_LEVELS
3256 #endif
3257 #ifdef TEST_SET_LEVELS
3259 #endif
3260 } /* fields present */
3261 } /* nonzeros */
3262 } /* levels */
3264 #undef TEST_SET_LEVELS
3265 #undef TEST_QUERY_LEVELS
3267 return ret;
3270 static bool test_user_ops(struct dcerpc_pipe *p,
3271 struct torture_context *tctx,
3272 struct policy_handle *user_handle,
3273 struct policy_handle *domain_handle,
3274 uint32_t base_acct_flags,
3275 const char *base_acct_name, enum torture_samr_choice which_ops,
3276 struct cli_credentials *machine_credentials)
3278 char *password = NULL;
3279 struct samr_QueryUserInfo q;
3280 union samr_UserInfo *info;
3281 NTSTATUS status;
3283 bool ret = true;
3284 int i;
3285 uint32_t rid;
3286 const uint32_t password_fields[] = {
3287 SAMR_FIELD_NT_PASSWORD_PRESENT,
3288 SAMR_FIELD_LM_PASSWORD_PRESENT,
3289 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3293 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3294 if (!NT_STATUS_IS_OK(status)) {
3295 ret = false;
3298 switch (which_ops) {
3299 case TORTURE_SAMR_USER_ATTRIBUTES:
3300 if (!test_QuerySecurity(p, tctx, user_handle)) {
3301 ret = false;
3304 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3305 ret = false;
3308 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3309 ret = false;
3312 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3313 base_acct_name)) {
3314 ret = false;
3317 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3318 ret = false;
3321 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3322 ret = false;
3325 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3326 ret = false;
3328 break;
3329 case TORTURE_SAMR_PASSWORDS:
3330 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3331 char simple_pass[9];
3332 char *v = generate_random_str(tctx, 1);
3334 ZERO_STRUCT(simple_pass);
3335 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3337 printf("Testing machine account password policy rules\n");
3339 /* Workstation trust accounts don't seem to need to honour password quality policy */
3340 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3341 ret = false;
3344 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3345 ret = false;
3348 /* reset again, to allow another 'user' password change */
3349 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3350 ret = false;
3353 /* Try a 'short' password */
3354 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3355 ret = false;
3358 /* Try a compleatly random password */
3359 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3360 ret = false;
3364 for (i = 0; password_fields[i]; i++) {
3365 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3366 ret = false;
3369 /* check it was set right */
3370 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3371 ret = false;
3375 for (i = 0; password_fields[i]; i++) {
3376 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3377 ret = false;
3380 /* check it was set right */
3381 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3382 ret = false;
3386 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
3387 ret = false;
3390 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
3391 ret = false;
3394 if (torture_setting_bool(tctx, "samba4", false)) {
3395 printf("skipping Set Password level 18 and 21 against Samba4\n");
3396 } else {
3398 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
3399 ret = false;
3402 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3403 ret = false;
3406 for (i = 0; password_fields[i]; i++) {
3408 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
3409 /* we need to skip as that would break
3410 * the ChangePasswordUser3 verify */
3411 continue;
3414 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
3415 ret = false;
3418 /* check it was set right */
3419 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3420 ret = false;
3425 q.in.user_handle = user_handle;
3426 q.in.level = 5;
3427 q.out.info = &info;
3429 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3430 if (!NT_STATUS_IS_OK(status)) {
3431 printf("QueryUserInfo level %u failed - %s\n",
3432 q.in.level, nt_errstr(status));
3433 ret = false;
3434 } else {
3435 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
3436 if ((info->info5.acct_flags) != expected_flags) {
3437 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3438 info->info5.acct_flags,
3439 expected_flags);
3440 /* FIXME: GD */
3441 if (!torture_setting_bool(tctx, "samba3", false)) {
3442 ret = false;
3445 if (info->info5.rid != rid) {
3446 printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3447 info->info5.rid, rid);
3452 break;
3454 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
3456 /* test last password change timestamp behaviour */
3457 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
3458 base_acct_name,
3459 user_handle, &password,
3460 machine_credentials)) {
3461 ret = false;
3464 if (ret == true) {
3465 torture_comment(tctx, "pwdLastSet test succeeded\n");
3466 } else {
3467 torture_warning(tctx, "pwdLastSet test failed\n");
3470 break;
3472 case TORTURE_SAMR_OTHER:
3473 /* We just need the account to exist */
3474 break;
3476 return ret;
3479 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
3480 struct policy_handle *alias_handle,
3481 const struct dom_sid *domain_sid)
3483 bool ret = true;
3485 if (!test_QuerySecurity(p, tctx, alias_handle)) {
3486 ret = false;
3489 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
3490 ret = false;
3493 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
3494 ret = false;
3497 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
3498 ret = false;
3501 if (torture_setting_bool(tctx, "samba4", false)) {
3502 printf("skipping MultipleMembers Alias tests against Samba4\n");
3503 return ret;
3506 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
3507 ret = false;
3510 return ret;
3514 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3515 struct policy_handle *user_handle)
3517 struct samr_DeleteUser d;
3518 NTSTATUS status;
3519 torture_comment(tctx, "Testing DeleteUser\n");
3521 d.in.user_handle = user_handle;
3522 d.out.user_handle = user_handle;
3524 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3525 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
3527 return true;
3530 bool test_DeleteUser_byname(struct dcerpc_pipe *p,
3531 struct torture_context *tctx,
3532 struct policy_handle *handle, const char *name)
3534 NTSTATUS status;
3535 struct samr_DeleteUser d;
3536 struct policy_handle user_handle;
3537 uint32_t rid;
3539 status = test_LookupName(p, tctx, handle, name, &rid);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 goto failed;
3544 status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
3545 if (!NT_STATUS_IS_OK(status)) {
3546 goto failed;
3549 d.in.user_handle = &user_handle;
3550 d.out.user_handle = &user_handle;
3551 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3552 if (!NT_STATUS_IS_OK(status)) {
3553 goto failed;
3556 return true;
3558 failed:
3559 printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
3560 return false;
3564 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
3565 struct torture_context *tctx,
3566 struct policy_handle *handle, const char *name)
3568 NTSTATUS status;
3569 struct samr_OpenGroup r;
3570 struct samr_DeleteDomainGroup d;
3571 struct policy_handle group_handle;
3572 uint32_t rid;
3574 status = test_LookupName(p, tctx, handle, name, &rid);
3575 if (!NT_STATUS_IS_OK(status)) {
3576 goto failed;
3579 r.in.domain_handle = handle;
3580 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3581 r.in.rid = rid;
3582 r.out.group_handle = &group_handle;
3583 status = dcerpc_samr_OpenGroup(p, tctx, &r);
3584 if (!NT_STATUS_IS_OK(status)) {
3585 goto failed;
3588 d.in.group_handle = &group_handle;
3589 d.out.group_handle = &group_handle;
3590 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
3591 if (!NT_STATUS_IS_OK(status)) {
3592 goto failed;
3595 return true;
3597 failed:
3598 printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
3599 return false;
3603 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
3604 struct torture_context *tctx,
3605 struct policy_handle *domain_handle,
3606 const char *name)
3608 NTSTATUS status;
3609 struct samr_OpenAlias r;
3610 struct samr_DeleteDomAlias d;
3611 struct policy_handle alias_handle;
3612 uint32_t rid;
3614 printf("testing DeleteAlias_byname\n");
3616 status = test_LookupName(p, tctx, domain_handle, name, &rid);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 goto failed;
3621 r.in.domain_handle = domain_handle;
3622 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3623 r.in.rid = rid;
3624 r.out.alias_handle = &alias_handle;
3625 status = dcerpc_samr_OpenAlias(p, tctx, &r);
3626 if (!NT_STATUS_IS_OK(status)) {
3627 goto failed;
3630 d.in.alias_handle = &alias_handle;
3631 d.out.alias_handle = &alias_handle;
3632 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
3633 if (!NT_STATUS_IS_OK(status)) {
3634 goto failed;
3637 return true;
3639 failed:
3640 printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
3641 return false;
3644 static bool test_DeleteAlias(struct dcerpc_pipe *p,
3645 struct torture_context *tctx,
3646 struct policy_handle *alias_handle)
3648 struct samr_DeleteDomAlias d;
3649 NTSTATUS status;
3650 bool ret = true;
3651 printf("Testing DeleteAlias\n");
3653 d.in.alias_handle = alias_handle;
3654 d.out.alias_handle = alias_handle;
3656 status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
3657 if (!NT_STATUS_IS_OK(status)) {
3658 printf("DeleteAlias failed - %s\n", nt_errstr(status));
3659 ret = false;
3662 return ret;
3665 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
3666 struct policy_handle *domain_handle,
3667 struct policy_handle *alias_handle,
3668 const struct dom_sid *domain_sid)
3670 NTSTATUS status;
3671 struct samr_CreateDomAlias r;
3672 struct lsa_String name;
3673 uint32_t rid;
3674 bool ret = true;
3676 init_lsa_String(&name, TEST_ALIASNAME);
3677 r.in.domain_handle = domain_handle;
3678 r.in.alias_name = &name;
3679 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3680 r.out.alias_handle = alias_handle;
3681 r.out.rid = &rid;
3683 printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
3685 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
3687 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
3688 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3689 printf("Server correctly refused create of '%s'\n", r.in.alias_name->string);
3690 return true;
3691 } else {
3692 printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
3693 nt_errstr(status));
3694 return false;
3698 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
3699 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
3700 return false;
3702 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
3705 if (!NT_STATUS_IS_OK(status)) {
3706 printf("CreateAlias failed - %s\n", nt_errstr(status));
3707 return false;
3710 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
3711 ret = false;
3714 return ret;
3717 static bool test_ChangePassword(struct dcerpc_pipe *p,
3718 struct torture_context *tctx,
3719 const char *acct_name,
3720 struct policy_handle *domain_handle, char **password)
3722 bool ret = true;
3724 if (!*password) {
3725 return false;
3728 if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
3729 ret = false;
3732 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
3733 ret = false;
3736 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
3737 ret = false;
3740 /* test what happens when setting the old password again */
3741 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
3742 ret = false;
3746 char simple_pass[9];
3747 char *v = generate_random_str(tctx, 1);
3749 ZERO_STRUCT(simple_pass);
3750 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3752 /* test what happens when picking a simple password */
3753 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
3754 ret = false;
3758 /* set samr_SetDomainInfo level 1 with min_length 5 */
3760 struct samr_QueryDomainInfo r;
3761 union samr_DomainInfo *info = NULL;
3762 struct samr_SetDomainInfo s;
3763 uint16_t len_old, len;
3764 uint32_t pwd_prop_old;
3765 int64_t min_pwd_age_old;
3766 NTSTATUS status;
3768 len = 5;
3770 r.in.domain_handle = domain_handle;
3771 r.in.level = 1;
3772 r.out.info = &info;
3774 printf("testing samr_QueryDomainInfo level 1\n");
3775 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
3776 if (!NT_STATUS_IS_OK(status)) {
3777 return false;
3780 s.in.domain_handle = domain_handle;
3781 s.in.level = 1;
3782 s.in.info = info;
3784 /* remember the old min length, so we can reset it */
3785 len_old = s.in.info->info1.min_password_length;
3786 s.in.info->info1.min_password_length = len;
3787 pwd_prop_old = s.in.info->info1.password_properties;
3788 /* turn off password complexity checks for this test */
3789 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
3791 min_pwd_age_old = s.in.info->info1.min_password_age;
3792 s.in.info->info1.min_password_age = 0;
3794 printf("testing samr_SetDomainInfo level 1\n");
3795 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
3796 if (!NT_STATUS_IS_OK(status)) {
3797 return false;
3800 printf("calling test_ChangePasswordUser3 with too short password\n");
3802 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
3803 ret = false;
3806 s.in.info->info1.min_password_length = len_old;
3807 s.in.info->info1.password_properties = pwd_prop_old;
3808 s.in.info->info1.min_password_age = min_pwd_age_old;
3810 printf("testing samr_SetDomainInfo level 1\n");
3811 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
3812 if (!NT_STATUS_IS_OK(status)) {
3813 return false;
3819 NTSTATUS status;
3820 struct samr_OpenUser r;
3821 struct samr_QueryUserInfo q;
3822 union samr_UserInfo *info;
3823 struct samr_LookupNames n;
3824 struct policy_handle user_handle;
3825 struct samr_Ids rids, types;
3827 n.in.domain_handle = domain_handle;
3828 n.in.num_names = 1;
3829 n.in.names = talloc_array(tctx, struct lsa_String, 1);
3830 n.in.names[0].string = acct_name;
3831 n.out.rids = &rids;
3832 n.out.types = &types;
3834 status = dcerpc_samr_LookupNames(p, tctx, &n);
3835 if (!NT_STATUS_IS_OK(status)) {
3836 printf("LookupNames failed - %s\n", nt_errstr(status));
3837 return false;
3840 r.in.domain_handle = domain_handle;
3841 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3842 r.in.rid = n.out.rids->ids[0];
3843 r.out.user_handle = &user_handle;
3845 status = dcerpc_samr_OpenUser(p, tctx, &r);
3846 if (!NT_STATUS_IS_OK(status)) {
3847 printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
3848 return false;
3851 q.in.user_handle = &user_handle;
3852 q.in.level = 5;
3853 q.out.info = &info;
3855 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3856 if (!NT_STATUS_IS_OK(status)) {
3857 printf("QueryUserInfo failed - %s\n", nt_errstr(status));
3858 return false;
3861 printf("calling test_ChangePasswordUser3 with too early password change\n");
3863 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
3864 info->info5.last_password_change, true)) {
3865 ret = false;
3869 /* we change passwords twice - this has the effect of verifying
3870 they were changed correctly for the final call */
3871 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
3872 ret = false;
3875 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
3876 ret = false;
3879 return ret;
3882 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3883 struct policy_handle *domain_handle,
3884 struct policy_handle *user_handle_out,
3885 struct dom_sid *domain_sid,
3886 enum torture_samr_choice which_ops,
3887 struct cli_credentials *machine_credentials)
3890 TALLOC_CTX *user_ctx;
3892 NTSTATUS status;
3893 struct samr_CreateUser r;
3894 struct samr_QueryUserInfo q;
3895 union samr_UserInfo *info;
3896 struct samr_DeleteUser d;
3897 uint32_t rid;
3899 /* This call creates a 'normal' account - check that it really does */
3900 const uint32_t acct_flags = ACB_NORMAL;
3901 struct lsa_String name;
3902 bool ret = true;
3904 struct policy_handle user_handle;
3905 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
3906 init_lsa_String(&name, TEST_ACCOUNT_NAME);
3908 r.in.domain_handle = domain_handle;
3909 r.in.account_name = &name;
3910 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3911 r.out.user_handle = &user_handle;
3912 r.out.rid = &rid;
3914 printf("Testing CreateUser(%s)\n", r.in.account_name->string);
3916 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
3918 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
3919 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3920 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
3921 return true;
3922 } else {
3923 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
3924 nt_errstr(status));
3925 return false;
3929 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
3930 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
3931 talloc_free(user_ctx);
3932 return false;
3934 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
3936 if (!NT_STATUS_IS_OK(status)) {
3937 talloc_free(user_ctx);
3938 printf("CreateUser failed - %s\n", nt_errstr(status));
3939 return false;
3940 } else {
3941 q.in.user_handle = &user_handle;
3942 q.in.level = 16;
3943 q.out.info = &info;
3945 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
3946 if (!NT_STATUS_IS_OK(status)) {
3947 printf("QueryUserInfo level %u failed - %s\n",
3948 q.in.level, nt_errstr(status));
3949 ret = false;
3950 } else {
3951 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
3952 printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3953 info->info16.acct_flags,
3954 acct_flags);
3955 ret = false;
3959 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
3960 acct_flags, name.string, which_ops,
3961 machine_credentials)) {
3962 ret = false;
3965 if (user_handle_out) {
3966 *user_handle_out = user_handle;
3967 } else {
3968 printf("Testing DeleteUser (createuser test)\n");
3970 d.in.user_handle = &user_handle;
3971 d.out.user_handle = &user_handle;
3973 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
3974 if (!NT_STATUS_IS_OK(status)) {
3975 printf("DeleteUser failed - %s\n", nt_errstr(status));
3976 ret = false;
3982 talloc_free(user_ctx);
3984 return ret;
3988 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
3989 struct policy_handle *domain_handle,
3990 struct dom_sid *domain_sid,
3991 enum torture_samr_choice which_ops,
3992 struct cli_credentials *machine_credentials)
3994 NTSTATUS status;
3995 struct samr_CreateUser2 r;
3996 struct samr_QueryUserInfo q;
3997 union samr_UserInfo *info;
3998 struct samr_DeleteUser d;
3999 struct policy_handle user_handle;
4000 uint32_t rid;
4001 struct lsa_String name;
4002 bool ret = true;
4003 int i;
4005 struct {
4006 uint32_t acct_flags;
4007 const char *account_name;
4008 NTSTATUS nt_status;
4009 } account_types[] = {
4010 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
4011 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4012 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4013 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4014 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4015 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4016 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4017 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4018 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4019 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
4020 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4021 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4022 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4023 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4024 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
4027 for (i = 0; account_types[i].account_name; i++) {
4028 TALLOC_CTX *user_ctx;
4029 uint32_t acct_flags = account_types[i].acct_flags;
4030 uint32_t access_granted;
4031 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4032 init_lsa_String(&name, account_types[i].account_name);
4034 r.in.domain_handle = domain_handle;
4035 r.in.account_name = &name;
4036 r.in.acct_flags = acct_flags;
4037 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4038 r.out.user_handle = &user_handle;
4039 r.out.access_granted = &access_granted;
4040 r.out.rid = &rid;
4042 printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
4044 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4046 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4047 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4048 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
4049 continue;
4050 } else {
4051 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4052 nt_errstr(status));
4053 ret = false;
4054 continue;
4058 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4059 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4060 talloc_free(user_ctx);
4061 ret = false;
4062 continue;
4064 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4067 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
4068 printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4069 nt_errstr(status), nt_errstr(account_types[i].nt_status));
4070 ret = false;
4073 if (NT_STATUS_IS_OK(status)) {
4074 q.in.user_handle = &user_handle;
4075 q.in.level = 5;
4076 q.out.info = &info;
4078 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4079 if (!NT_STATUS_IS_OK(status)) {
4080 printf("QueryUserInfo level %u failed - %s\n",
4081 q.in.level, nt_errstr(status));
4082 ret = false;
4083 } else {
4084 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4085 if (acct_flags == ACB_NORMAL) {
4086 expected_flags |= ACB_PW_EXPIRED;
4088 if ((info->info5.acct_flags) != expected_flags) {
4089 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4090 info->info5.acct_flags,
4091 expected_flags);
4092 ret = false;
4094 switch (acct_flags) {
4095 case ACB_SVRTRUST:
4096 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
4097 printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4098 DOMAIN_RID_DCS, info->info5.primary_gid);
4099 ret = false;
4101 break;
4102 case ACB_WSTRUST:
4103 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
4104 printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4105 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
4106 ret = false;
4108 break;
4109 case ACB_NORMAL:
4110 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
4111 printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4112 DOMAIN_RID_USERS, info->info5.primary_gid);
4113 ret = false;
4115 break;
4119 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4120 acct_flags, name.string, which_ops,
4121 machine_credentials)) {
4122 ret = false;
4125 printf("Testing DeleteUser (createuser2 test)\n");
4127 d.in.user_handle = &user_handle;
4128 d.out.user_handle = &user_handle;
4130 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4131 if (!NT_STATUS_IS_OK(status)) {
4132 printf("DeleteUser failed - %s\n", nt_errstr(status));
4133 ret = false;
4136 talloc_free(user_ctx);
4139 return ret;
4142 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
4143 struct torture_context *tctx,
4144 struct policy_handle *handle)
4146 NTSTATUS status;
4147 struct samr_QueryAliasInfo r;
4148 union samr_AliasInfo *info;
4149 uint16_t levels[] = {1, 2, 3};
4150 int i;
4151 bool ret = true;
4153 for (i=0;i<ARRAY_SIZE(levels);i++) {
4154 printf("Testing QueryAliasInfo level %u\n", levels[i]);
4156 r.in.alias_handle = handle;
4157 r.in.level = levels[i];
4158 r.out.info = &info;
4160 status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
4161 if (!NT_STATUS_IS_OK(status)) {
4162 printf("QueryAliasInfo level %u failed - %s\n",
4163 levels[i], nt_errstr(status));
4164 ret = false;
4168 return ret;
4171 static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
4172 struct torture_context *tctx,
4173 struct policy_handle *handle)
4175 NTSTATUS status;
4176 struct samr_QueryGroupInfo r;
4177 union samr_GroupInfo *info;
4178 uint16_t levels[] = {1, 2, 3, 4, 5};
4179 int i;
4180 bool ret = true;
4182 for (i=0;i<ARRAY_SIZE(levels);i++) {
4183 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4185 r.in.group_handle = handle;
4186 r.in.level = levels[i];
4187 r.out.info = &info;
4189 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4190 if (!NT_STATUS_IS_OK(status)) {
4191 printf("QueryGroupInfo level %u failed - %s\n",
4192 levels[i], nt_errstr(status));
4193 ret = false;
4197 return ret;
4200 static bool test_QueryGroupMember(struct dcerpc_pipe *p,
4201 struct torture_context *tctx,
4202 struct policy_handle *handle)
4204 NTSTATUS status;
4205 struct samr_QueryGroupMember r;
4206 struct samr_RidTypeArray *rids = NULL;
4207 bool ret = true;
4209 printf("Testing QueryGroupMember\n");
4211 r.in.group_handle = handle;
4212 r.out.rids = &rids;
4214 status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
4215 if (!NT_STATUS_IS_OK(status)) {
4216 printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
4217 ret = false;
4220 return ret;
4224 static bool test_SetGroupInfo(struct dcerpc_pipe *p,
4225 struct torture_context *tctx,
4226 struct policy_handle *handle)
4228 NTSTATUS status;
4229 struct samr_QueryGroupInfo r;
4230 union samr_GroupInfo *info;
4231 struct samr_SetGroupInfo s;
4232 uint16_t levels[] = {1, 2, 3, 4};
4233 uint16_t set_ok[] = {0, 1, 1, 1};
4234 int i;
4235 bool ret = true;
4237 for (i=0;i<ARRAY_SIZE(levels);i++) {
4238 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4240 r.in.group_handle = handle;
4241 r.in.level = levels[i];
4242 r.out.info = &info;
4244 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
4245 if (!NT_STATUS_IS_OK(status)) {
4246 printf("QueryGroupInfo level %u failed - %s\n",
4247 levels[i], nt_errstr(status));
4248 ret = false;
4251 printf("Testing SetGroupInfo level %u\n", levels[i]);
4253 s.in.group_handle = handle;
4254 s.in.level = levels[i];
4255 s.in.info = *r.out.info;
4257 #if 0
4258 /* disabled this, as it changes the name only from the point of view of samr,
4259 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4260 the name is still reserved, so creating the old name fails, but deleting by the old name
4261 also fails */
4262 if (s.in.level == 2) {
4263 init_lsa_String(&s.in.info->string, "NewName");
4265 #endif
4267 if (s.in.level == 4) {
4268 init_lsa_String(&s.in.info->description, "test description");
4271 status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
4272 if (set_ok[i]) {
4273 if (!NT_STATUS_IS_OK(status)) {
4274 printf("SetGroupInfo level %u failed - %s\n",
4275 r.in.level, nt_errstr(status));
4276 ret = false;
4277 continue;
4279 } else {
4280 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4281 printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4282 r.in.level, nt_errstr(status));
4283 ret = false;
4284 continue;
4289 return ret;
4292 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
4293 struct torture_context *tctx,
4294 struct policy_handle *handle)
4296 NTSTATUS status;
4297 struct samr_QueryUserInfo r;
4298 union samr_UserInfo *info;
4299 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4300 11, 12, 13, 14, 16, 17, 20, 21};
4301 int i;
4302 bool ret = true;
4304 for (i=0;i<ARRAY_SIZE(levels);i++) {
4305 printf("Testing QueryUserInfo level %u\n", levels[i]);
4307 r.in.user_handle = handle;
4308 r.in.level = levels[i];
4309 r.out.info = &info;
4311 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
4312 if (!NT_STATUS_IS_OK(status)) {
4313 printf("QueryUserInfo level %u failed - %s\n",
4314 levels[i], nt_errstr(status));
4315 ret = false;
4319 return ret;
4322 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
4323 struct torture_context *tctx,
4324 struct policy_handle *handle)
4326 NTSTATUS status;
4327 struct samr_QueryUserInfo2 r;
4328 union samr_UserInfo *info;
4329 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4330 11, 12, 13, 14, 16, 17, 20, 21};
4331 int i;
4332 bool ret = true;
4334 for (i=0;i<ARRAY_SIZE(levels);i++) {
4335 printf("Testing QueryUserInfo2 level %u\n", levels[i]);
4337 r.in.user_handle = handle;
4338 r.in.level = levels[i];
4339 r.out.info = &info;
4341 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
4342 if (!NT_STATUS_IS_OK(status)) {
4343 printf("QueryUserInfo2 level %u failed - %s\n",
4344 levels[i], nt_errstr(status));
4345 ret = false;
4349 return ret;
4352 static bool test_OpenUser(struct dcerpc_pipe *p,
4353 struct torture_context *tctx,
4354 struct policy_handle *handle, uint32_t rid)
4356 NTSTATUS status;
4357 struct samr_OpenUser r;
4358 struct policy_handle user_handle;
4359 bool ret = true;
4361 printf("Testing OpenUser(%u)\n", rid);
4363 r.in.domain_handle = handle;
4364 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4365 r.in.rid = rid;
4366 r.out.user_handle = &user_handle;
4368 status = dcerpc_samr_OpenUser(p, tctx, &r);
4369 if (!NT_STATUS_IS_OK(status)) {
4370 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4371 return false;
4374 if (!test_QuerySecurity(p, tctx, &user_handle)) {
4375 ret = false;
4378 if (!test_QueryUserInfo(p, tctx, &user_handle)) {
4379 ret = false;
4382 if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
4383 ret = false;
4386 if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
4387 ret = false;
4390 if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
4391 ret = false;
4394 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4395 ret = false;
4398 return ret;
4401 static bool test_OpenGroup(struct dcerpc_pipe *p,
4402 struct torture_context *tctx,
4403 struct policy_handle *handle, uint32_t rid)
4405 NTSTATUS status;
4406 struct samr_OpenGroup r;
4407 struct policy_handle group_handle;
4408 bool ret = true;
4410 printf("Testing OpenGroup(%u)\n", rid);
4412 r.in.domain_handle = handle;
4413 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4414 r.in.rid = rid;
4415 r.out.group_handle = &group_handle;
4417 status = dcerpc_samr_OpenGroup(p, tctx, &r);
4418 if (!NT_STATUS_IS_OK(status)) {
4419 printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
4420 return false;
4423 if (!test_QuerySecurity(p, tctx, &group_handle)) {
4424 ret = false;
4427 if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
4428 ret = false;
4431 if (!test_QueryGroupMember(p, tctx, &group_handle)) {
4432 ret = false;
4435 if (!test_samr_handle_Close(p, tctx, &group_handle)) {
4436 ret = false;
4439 return ret;
4442 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4443 struct policy_handle *handle, uint32_t rid)
4445 NTSTATUS status;
4446 struct samr_OpenAlias r;
4447 struct policy_handle alias_handle;
4448 bool ret = true;
4450 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
4452 r.in.domain_handle = handle;
4453 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4454 r.in.rid = rid;
4455 r.out.alias_handle = &alias_handle;
4457 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4458 if (!NT_STATUS_IS_OK(status)) {
4459 printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
4460 return false;
4463 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
4464 ret = false;
4467 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
4468 ret = false;
4471 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
4472 ret = false;
4475 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
4476 ret = false;
4479 return ret;
4482 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
4483 struct policy_handle *handle, uint32_t rid,
4484 uint32_t acct_flag_mask)
4486 NTSTATUS status;
4487 struct samr_OpenUser r;
4488 struct samr_QueryUserInfo q;
4489 union samr_UserInfo *info;
4490 struct policy_handle user_handle;
4491 bool ret = true;
4493 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4495 r.in.domain_handle = handle;
4496 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4497 r.in.rid = rid;
4498 r.out.user_handle = &user_handle;
4500 status = dcerpc_samr_OpenUser(p, tctx, &r);
4501 if (!NT_STATUS_IS_OK(status)) {
4502 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4503 return false;
4506 q.in.user_handle = &user_handle;
4507 q.in.level = 16;
4508 q.out.info = &info;
4510 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 printf("QueryUserInfo level 16 failed - %s\n",
4513 nt_errstr(status));
4514 ret = false;
4515 } else {
4516 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
4517 printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4518 acct_flag_mask, info->info16.acct_flags, rid);
4519 ret = false;
4523 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4524 ret = false;
4527 return ret;
4530 static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *tctx,
4531 struct policy_handle *handle)
4533 NTSTATUS status = STATUS_MORE_ENTRIES;
4534 struct samr_EnumDomainUsers r;
4535 uint32_t mask, resume_handle=0;
4536 int i, mask_idx;
4537 bool ret = true;
4538 struct samr_LookupNames n;
4539 struct samr_LookupRids lr ;
4540 struct lsa_Strings names;
4541 struct samr_Ids rids, types;
4542 struct samr_SamArray *sam = NULL;
4543 uint32_t num_entries = 0;
4545 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
4546 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
4547 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
4548 ACB_PWNOEXP, 0};
4550 printf("Testing EnumDomainUsers\n");
4552 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
4553 r.in.domain_handle = handle;
4554 r.in.resume_handle = &resume_handle;
4555 r.in.acct_flags = mask = masks[mask_idx];
4556 r.in.max_size = (uint32_t)-1;
4557 r.out.resume_handle = &resume_handle;
4558 r.out.num_entries = &num_entries;
4559 r.out.sam = &sam;
4561 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
4562 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
4563 !NT_STATUS_IS_OK(status)) {
4564 printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
4565 return false;
4568 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4570 if (sam->count == 0) {
4571 continue;
4574 for (i=0;i<sam->count;i++) {
4575 if (mask) {
4576 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
4577 ret = false;
4579 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
4580 ret = false;
4585 printf("Testing LookupNames\n");
4586 n.in.domain_handle = handle;
4587 n.in.num_names = sam->count;
4588 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
4589 n.out.rids = &rids;
4590 n.out.types = &types;
4591 for (i=0;i<sam->count;i++) {
4592 n.in.names[i].string = sam->entries[i].name.string;
4594 status = dcerpc_samr_LookupNames(p, tctx, &n);
4595 if (!NT_STATUS_IS_OK(status)) {
4596 printf("LookupNames failed - %s\n", nt_errstr(status));
4597 ret = false;
4601 printf("Testing LookupRids\n");
4602 lr.in.domain_handle = handle;
4603 lr.in.num_rids = sam->count;
4604 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
4605 lr.out.names = &names;
4606 lr.out.types = &types;
4607 for (i=0;i<sam->count;i++) {
4608 lr.in.rids[i] = sam->entries[i].idx;
4610 status = dcerpc_samr_LookupRids(p, tctx, &lr);
4611 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
4613 return ret;
4617 try blasting the server with a bunch of sync requests
4619 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
4620 struct policy_handle *handle)
4622 NTSTATUS status;
4623 struct samr_EnumDomainUsers r;
4624 uint32_t resume_handle=0;
4625 int i;
4626 #define ASYNC_COUNT 100
4627 struct rpc_request *req[ASYNC_COUNT];
4629 if (!torture_setting_bool(tctx, "dangerous", false)) {
4630 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
4633 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
4635 r.in.domain_handle = handle;
4636 r.in.resume_handle = &resume_handle;
4637 r.in.acct_flags = 0;
4638 r.in.max_size = (uint32_t)-1;
4639 r.out.resume_handle = &resume_handle;
4641 for (i=0;i<ASYNC_COUNT;i++) {
4642 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
4645 for (i=0;i<ASYNC_COUNT;i++) {
4646 status = dcerpc_ndr_request_recv(req[i]);
4647 if (!NT_STATUS_IS_OK(status)) {
4648 printf("EnumDomainUsers[%d] failed - %s\n",
4649 i, nt_errstr(status));
4650 return false;
4654 torture_comment(tctx, "%d async requests OK\n", i);
4656 return true;
4659 static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
4660 struct torture_context *tctx,
4661 struct policy_handle *handle)
4663 NTSTATUS status;
4664 struct samr_EnumDomainGroups r;
4665 uint32_t resume_handle=0;
4666 struct samr_SamArray *sam = NULL;
4667 uint32_t num_entries = 0;
4668 int i;
4669 bool ret = true;
4671 printf("Testing EnumDomainGroups\n");
4673 r.in.domain_handle = handle;
4674 r.in.resume_handle = &resume_handle;
4675 r.in.max_size = (uint32_t)-1;
4676 r.out.resume_handle = &resume_handle;
4677 r.out.num_entries = &num_entries;
4678 r.out.sam = &sam;
4680 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
4681 if (!NT_STATUS_IS_OK(status)) {
4682 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
4683 return false;
4686 if (!sam) {
4687 return false;
4690 for (i=0;i<sam->count;i++) {
4691 if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
4692 ret = false;
4696 return ret;
4699 static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
4700 struct torture_context *tctx,
4701 struct policy_handle *handle)
4703 NTSTATUS status;
4704 struct samr_EnumDomainAliases r;
4705 uint32_t resume_handle=0;
4706 struct samr_SamArray *sam = NULL;
4707 uint32_t num_entries = 0;
4708 int i;
4709 bool ret = true;
4711 printf("Testing EnumDomainAliases\n");
4713 r.in.domain_handle = handle;
4714 r.in.resume_handle = &resume_handle;
4715 r.in.max_size = (uint32_t)-1;
4716 r.out.sam = &sam;
4717 r.out.num_entries = &num_entries;
4718 r.out.resume_handle = &resume_handle;
4720 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
4721 if (!NT_STATUS_IS_OK(status)) {
4722 printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
4723 return false;
4726 if (!sam) {
4727 return false;
4730 for (i=0;i<sam->count;i++) {
4731 if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
4732 ret = false;
4736 return ret;
4739 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
4740 struct torture_context *tctx,
4741 struct policy_handle *handle)
4743 NTSTATUS status;
4744 struct samr_GetDisplayEnumerationIndex r;
4745 bool ret = true;
4746 uint16_t levels[] = {1, 2, 3, 4, 5};
4747 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
4748 struct lsa_String name;
4749 uint32_t idx = 0;
4750 int i;
4752 for (i=0;i<ARRAY_SIZE(levels);i++) {
4753 printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
4755 init_lsa_String(&name, TEST_ACCOUNT_NAME);
4757 r.in.domain_handle = handle;
4758 r.in.level = levels[i];
4759 r.in.name = &name;
4760 r.out.idx = &idx;
4762 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
4764 if (ok_lvl[i] &&
4765 !NT_STATUS_IS_OK(status) &&
4766 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4767 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
4768 levels[i], nt_errstr(status));
4769 ret = false;
4772 init_lsa_String(&name, "zzzzzzzz");
4774 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
4776 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4777 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
4778 levels[i], nt_errstr(status));
4779 ret = false;
4783 return ret;
4786 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
4787 struct torture_context *tctx,
4788 struct policy_handle *handle)
4790 NTSTATUS status;
4791 struct samr_GetDisplayEnumerationIndex2 r;
4792 bool ret = true;
4793 uint16_t levels[] = {1, 2, 3, 4, 5};
4794 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
4795 struct lsa_String name;
4796 uint32_t idx = 0;
4797 int i;
4799 for (i=0;i<ARRAY_SIZE(levels);i++) {
4800 printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
4802 init_lsa_String(&name, TEST_ACCOUNT_NAME);
4804 r.in.domain_handle = handle;
4805 r.in.level = levels[i];
4806 r.in.name = &name;
4807 r.out.idx = &idx;
4809 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
4810 if (ok_lvl[i] &&
4811 !NT_STATUS_IS_OK(status) &&
4812 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4813 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
4814 levels[i], nt_errstr(status));
4815 ret = false;
4818 init_lsa_String(&name, "zzzzzzzz");
4820 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
4821 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4822 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
4823 levels[i], nt_errstr(status));
4824 ret = false;
4828 return ret;
4831 #define STRING_EQUAL_QUERY(s1, s2, user) \
4832 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
4833 /* odd, but valid */ \
4834 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
4835 printf("%s mismatch for %s: %s != %s (%s)\n", \
4836 #s1, user.string, s1.string, s2.string, __location__); \
4837 ret = false; \
4839 #define INT_EQUAL_QUERY(s1, s2, user) \
4840 if (s1 != s2) { \
4841 printf("%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
4842 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
4843 ret = false; \
4846 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
4847 struct torture_context *tctx,
4848 struct samr_QueryDisplayInfo *querydisplayinfo,
4849 bool *seen_testuser)
4851 struct samr_OpenUser r;
4852 struct samr_QueryUserInfo q;
4853 union samr_UserInfo *info;
4854 struct policy_handle user_handle;
4855 int i, ret = true;
4856 NTSTATUS status;
4857 r.in.domain_handle = querydisplayinfo->in.domain_handle;
4858 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4859 for (i = 0; ; i++) {
4860 switch (querydisplayinfo->in.level) {
4861 case 1:
4862 if (i >= querydisplayinfo->out.info->info1.count) {
4863 return ret;
4865 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
4866 break;
4867 case 2:
4868 if (i >= querydisplayinfo->out.info->info2.count) {
4869 return ret;
4871 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
4872 break;
4873 case 3:
4874 /* Groups */
4875 case 4:
4876 case 5:
4877 /* Not interested in validating just the account name */
4878 return true;
4881 r.out.user_handle = &user_handle;
4883 switch (querydisplayinfo->in.level) {
4884 case 1:
4885 case 2:
4886 status = dcerpc_samr_OpenUser(p, tctx, &r);
4887 if (!NT_STATUS_IS_OK(status)) {
4888 printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
4889 return false;
4893 q.in.user_handle = &user_handle;
4894 q.in.level = 21;
4895 q.out.info = &info;
4896 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4897 if (!NT_STATUS_IS_OK(status)) {
4898 printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
4899 return false;
4902 switch (querydisplayinfo->in.level) {
4903 case 1:
4904 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
4905 *seen_testuser = true;
4907 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
4908 info->info21.full_name, info->info21.account_name);
4909 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
4910 info->info21.account_name, info->info21.account_name);
4911 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
4912 info->info21.description, info->info21.account_name);
4913 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
4914 info->info21.rid, info->info21.account_name);
4915 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
4916 info->info21.acct_flags, info->info21.account_name);
4918 break;
4919 case 2:
4920 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
4921 info->info21.account_name, info->info21.account_name);
4922 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
4923 info->info21.description, info->info21.account_name);
4924 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
4925 info->info21.rid, info->info21.account_name);
4926 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
4927 info->info21.acct_flags, info->info21.account_name);
4929 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
4930 printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
4931 info->info21.account_name.string);
4934 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
4935 printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
4936 info->info21.account_name.string,
4937 querydisplayinfo->out.info->info2.entries[i].acct_flags,
4938 info->info21.acct_flags);
4939 return false;
4942 break;
4945 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4946 return false;
4949 return ret;
4952 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
4953 struct torture_context *tctx,
4954 struct policy_handle *handle)
4956 NTSTATUS status;
4957 struct samr_QueryDisplayInfo r;
4958 struct samr_QueryDomainInfo dom_info;
4959 union samr_DomainInfo *info = NULL;
4960 bool ret = true;
4961 uint16_t levels[] = {1, 2, 3, 4, 5};
4962 int i;
4963 bool seen_testuser = false;
4964 uint32_t total_size;
4965 uint32_t returned_size;
4966 union samr_DispInfo disp_info;
4969 for (i=0;i<ARRAY_SIZE(levels);i++) {
4970 printf("Testing QueryDisplayInfo level %u\n", levels[i]);
4972 r.in.start_idx = 0;
4973 status = STATUS_MORE_ENTRIES;
4974 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
4975 r.in.domain_handle = handle;
4976 r.in.level = levels[i];
4977 r.in.max_entries = 2;
4978 r.in.buf_size = (uint32_t)-1;
4979 r.out.total_size = &total_size;
4980 r.out.returned_size = &returned_size;
4981 r.out.info = &disp_info;
4983 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
4984 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
4985 printf("QueryDisplayInfo level %u failed - %s\n",
4986 levels[i], nt_errstr(status));
4987 ret = false;
4989 switch (r.in.level) {
4990 case 1:
4991 if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
4992 ret = false;
4994 r.in.start_idx += r.out.info->info1.count;
4995 break;
4996 case 2:
4997 if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
4998 ret = false;
5000 r.in.start_idx += r.out.info->info2.count;
5001 break;
5002 case 3:
5003 r.in.start_idx += r.out.info->info3.count;
5004 break;
5005 case 4:
5006 r.in.start_idx += r.out.info->info4.count;
5007 break;
5008 case 5:
5009 r.in.start_idx += r.out.info->info5.count;
5010 break;
5013 dom_info.in.domain_handle = handle;
5014 dom_info.in.level = 2;
5015 dom_info.out.info = &info;
5017 /* Check number of users returned is correct */
5018 status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
5019 if (!NT_STATUS_IS_OK(status)) {
5020 printf("QueryDomainInfo level %u failed - %s\n",
5021 r.in.level, nt_errstr(status));
5022 ret = false;
5023 break;
5025 switch (r.in.level) {
5026 case 1:
5027 case 4:
5028 if (info->general.num_users < r.in.start_idx) {
5029 printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
5030 r.in.start_idx, info->general.num_groups,
5031 info->general.domain_name.string);
5032 ret = false;
5034 if (!seen_testuser) {
5035 struct policy_handle user_handle;
5036 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
5037 printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
5038 info->general.domain_name.string);
5039 ret = false;
5040 test_samr_handle_Close(p, tctx, &user_handle);
5043 break;
5044 case 3:
5045 case 5:
5046 if (info->general.num_groups != r.in.start_idx) {
5047 printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
5048 r.in.start_idx, info->general.num_groups,
5049 info->general.domain_name.string);
5050 ret = false;
5053 break;
5058 return ret;
5061 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
5062 struct torture_context *tctx,
5063 struct policy_handle *handle)
5065 NTSTATUS status;
5066 struct samr_QueryDisplayInfo2 r;
5067 bool ret = true;
5068 uint16_t levels[] = {1, 2, 3, 4, 5};
5069 int i;
5070 uint32_t total_size;
5071 uint32_t returned_size;
5072 union samr_DispInfo info;
5074 for (i=0;i<ARRAY_SIZE(levels);i++) {
5075 printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
5077 r.in.domain_handle = handle;
5078 r.in.level = levels[i];
5079 r.in.start_idx = 0;
5080 r.in.max_entries = 1000;
5081 r.in.buf_size = (uint32_t)-1;
5082 r.out.total_size = &total_size;
5083 r.out.returned_size = &returned_size;
5084 r.out.info = &info;
5086 status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
5087 if (!NT_STATUS_IS_OK(status)) {
5088 printf("QueryDisplayInfo2 level %u failed - %s\n",
5089 levels[i], nt_errstr(status));
5090 ret = false;
5094 return ret;
5097 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
5098 struct policy_handle *handle)
5100 NTSTATUS status;
5101 struct samr_QueryDisplayInfo3 r;
5102 bool ret = true;
5103 uint16_t levels[] = {1, 2, 3, 4, 5};
5104 int i;
5105 uint32_t total_size;
5106 uint32_t returned_size;
5107 union samr_DispInfo info;
5109 for (i=0;i<ARRAY_SIZE(levels);i++) {
5110 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
5112 r.in.domain_handle = handle;
5113 r.in.level = levels[i];
5114 r.in.start_idx = 0;
5115 r.in.max_entries = 1000;
5116 r.in.buf_size = (uint32_t)-1;
5117 r.out.total_size = &total_size;
5118 r.out.returned_size = &returned_size;
5119 r.out.info = &info;
5121 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
5122 if (!NT_STATUS_IS_OK(status)) {
5123 printf("QueryDisplayInfo3 level %u failed - %s\n",
5124 levels[i], nt_errstr(status));
5125 ret = false;
5129 return ret;
5133 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
5134 struct torture_context *tctx,
5135 struct policy_handle *handle)
5137 NTSTATUS status;
5138 struct samr_QueryDisplayInfo r;
5139 bool ret = true;
5140 uint32_t total_size;
5141 uint32_t returned_size;
5142 union samr_DispInfo info;
5144 printf("Testing QueryDisplayInfo continuation\n");
5146 r.in.domain_handle = handle;
5147 r.in.level = 1;
5148 r.in.start_idx = 0;
5149 r.in.max_entries = 1;
5150 r.in.buf_size = (uint32_t)-1;
5151 r.out.total_size = &total_size;
5152 r.out.returned_size = &returned_size;
5153 r.out.info = &info;
5155 do {
5156 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
5157 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
5158 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
5159 printf("expected idx %d but got %d\n",
5160 r.in.start_idx + 1,
5161 r.out.info->info1.entries[0].idx);
5162 break;
5165 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5166 !NT_STATUS_IS_OK(status)) {
5167 printf("QueryDisplayInfo level %u failed - %s\n",
5168 r.in.level, nt_errstr(status));
5169 ret = false;
5170 break;
5172 r.in.start_idx++;
5173 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
5174 NT_STATUS_IS_OK(status)) &&
5175 *r.out.returned_size != 0);
5177 return ret;
5180 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
5181 struct policy_handle *handle)
5183 NTSTATUS status;
5184 struct samr_QueryDomainInfo r;
5185 union samr_DomainInfo *info = NULL;
5186 struct samr_SetDomainInfo s;
5187 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5188 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5189 int i;
5190 bool ret = true;
5191 const char *domain_comment = talloc_asprintf(tctx,
5192 "Tortured by Samba4 RPC-SAMR: %s",
5193 timestring(tctx, time(NULL)));
5195 s.in.domain_handle = handle;
5196 s.in.level = 4;
5197 s.in.info = talloc(tctx, union samr_DomainInfo);
5199 s.in.info->oem.oem_information.string = domain_comment;
5200 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5201 if (!NT_STATUS_IS_OK(status)) {
5202 printf("SetDomainInfo level %u (set comment) failed - %s\n",
5203 s.in.level, nt_errstr(status));
5204 return false;
5207 for (i=0;i<ARRAY_SIZE(levels);i++) {
5208 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
5210 r.in.domain_handle = handle;
5211 r.in.level = levels[i];
5212 r.out.info = &info;
5214 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5215 if (!NT_STATUS_IS_OK(status)) {
5216 printf("QueryDomainInfo level %u failed - %s\n",
5217 r.in.level, nt_errstr(status));
5218 ret = false;
5219 continue;
5222 switch (levels[i]) {
5223 case 2:
5224 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
5225 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5226 levels[i], info->general.oem_information.string, domain_comment);
5227 ret = false;
5229 if (!info->general.primary.string) {
5230 printf("QueryDomainInfo level %u returned no PDC name\n",
5231 levels[i]);
5232 ret = false;
5233 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
5234 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
5235 printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5236 levels[i], info->general.primary.string, dcerpc_server_name(p));
5239 break;
5240 case 4:
5241 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
5242 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5243 levels[i], info->oem.oem_information.string, domain_comment);
5244 ret = false;
5246 break;
5247 case 6:
5248 if (!info->info6.primary.string) {
5249 printf("QueryDomainInfo level %u returned no PDC name\n",
5250 levels[i]);
5251 ret = false;
5253 break;
5254 case 11:
5255 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
5256 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5257 levels[i], info->general2.general.oem_information.string, domain_comment);
5258 ret = false;
5260 break;
5263 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
5265 s.in.domain_handle = handle;
5266 s.in.level = levels[i];
5267 s.in.info = info;
5269 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5270 if (set_ok[i]) {
5271 if (!NT_STATUS_IS_OK(status)) {
5272 printf("SetDomainInfo level %u failed - %s\n",
5273 r.in.level, nt_errstr(status));
5274 ret = false;
5275 continue;
5277 } else {
5278 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5279 printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5280 r.in.level, nt_errstr(status));
5281 ret = false;
5282 continue;
5286 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5287 if (!NT_STATUS_IS_OK(status)) {
5288 printf("QueryDomainInfo level %u failed - %s\n",
5289 r.in.level, nt_errstr(status));
5290 ret = false;
5291 continue;
5295 return ret;
5299 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
5300 struct policy_handle *handle)
5302 NTSTATUS status;
5303 struct samr_QueryDomainInfo2 r;
5304 union samr_DomainInfo *info = NULL;
5305 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5306 int i;
5307 bool ret = true;
5309 for (i=0;i<ARRAY_SIZE(levels);i++) {
5310 printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
5312 r.in.domain_handle = handle;
5313 r.in.level = levels[i];
5314 r.out.info = &info;
5316 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
5317 if (!NT_STATUS_IS_OK(status)) {
5318 printf("QueryDomainInfo2 level %u failed - %s\n",
5319 r.in.level, nt_errstr(status));
5320 ret = false;
5321 continue;
5325 return true;
5328 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5329 set of group names. */
5330 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
5331 struct policy_handle *handle)
5333 struct samr_EnumDomainGroups q1;
5334 struct samr_QueryDisplayInfo q2;
5335 NTSTATUS status;
5336 uint32_t resume_handle=0;
5337 struct samr_SamArray *sam = NULL;
5338 uint32_t num_entries = 0;
5339 int i;
5340 bool ret = true;
5341 uint32_t total_size;
5342 uint32_t returned_size;
5343 union samr_DispInfo info;
5345 int num_names = 0;
5346 const char **names = NULL;
5348 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
5350 q1.in.domain_handle = handle;
5351 q1.in.resume_handle = &resume_handle;
5352 q1.in.max_size = 5;
5353 q1.out.resume_handle = &resume_handle;
5354 q1.out.num_entries = &num_entries;
5355 q1.out.sam = &sam;
5357 status = STATUS_MORE_ENTRIES;
5358 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5359 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
5361 if (!NT_STATUS_IS_OK(status) &&
5362 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5363 break;
5365 for (i=0; i<*q1.out.num_entries; i++) {
5366 add_string_to_array(tctx,
5367 sam->entries[i].name.string,
5368 &names, &num_names);
5372 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
5374 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
5376 q2.in.domain_handle = handle;
5377 q2.in.level = 5;
5378 q2.in.start_idx = 0;
5379 q2.in.max_entries = 5;
5380 q2.in.buf_size = (uint32_t)-1;
5381 q2.out.total_size = &total_size;
5382 q2.out.returned_size = &returned_size;
5383 q2.out.info = &info;
5385 status = STATUS_MORE_ENTRIES;
5386 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5387 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
5389 if (!NT_STATUS_IS_OK(status) &&
5390 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5391 break;
5393 for (i=0; i<q2.out.info->info5.count; i++) {
5394 int j;
5395 const char *name = q2.out.info->info5.entries[i].account_name.string;
5396 bool found = false;
5397 for (j=0; j<num_names; j++) {
5398 if (names[j] == NULL)
5399 continue;
5400 if (strequal(names[j], name)) {
5401 names[j] = NULL;
5402 found = true;
5403 break;
5407 if (!found) {
5408 printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5409 name);
5410 ret = false;
5413 q2.in.start_idx += q2.out.info->info5.count;
5416 if (!NT_STATUS_IS_OK(status)) {
5417 printf("QueryDisplayInfo level 5 failed - %s\n",
5418 nt_errstr(status));
5419 ret = false;
5422 for (i=0; i<num_names; i++) {
5423 if (names[i] != NULL) {
5424 printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5425 names[i]);
5426 ret = false;
5430 return ret;
5433 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
5434 struct policy_handle *group_handle)
5436 struct samr_DeleteDomainGroup d;
5437 NTSTATUS status;
5439 torture_comment(tctx, "Testing DeleteDomainGroup\n");
5441 d.in.group_handle = group_handle;
5442 d.out.group_handle = group_handle;
5444 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
5445 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
5447 return true;
5450 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5451 struct policy_handle *domain_handle)
5453 struct samr_TestPrivateFunctionsDomain r;
5454 NTSTATUS status;
5455 bool ret = true;
5457 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
5459 r.in.domain_handle = domain_handle;
5461 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
5462 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
5464 return ret;
5467 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
5468 struct dom_sid *domain_sid,
5469 struct policy_handle *domain_handle)
5471 struct samr_RidToSid r;
5472 NTSTATUS status;
5473 bool ret = true;
5474 struct dom_sid *calc_sid, *out_sid;
5475 int rids[] = { 0, 42, 512, 10200 };
5476 int i;
5478 for (i=0;i<ARRAY_SIZE(rids);i++) {
5479 torture_comment(tctx, "Testing RidToSid\n");
5481 calc_sid = dom_sid_dup(tctx, domain_sid);
5482 r.in.domain_handle = domain_handle;
5483 r.in.rid = rids[i];
5484 r.out.sid = &out_sid;
5486 status = dcerpc_samr_RidToSid(p, tctx, &r);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
5489 ret = false;
5490 } else {
5491 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
5493 if (!dom_sid_equal(calc_sid, out_sid)) {
5494 printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
5495 dom_sid_string(tctx, out_sid),
5496 dom_sid_string(tctx, calc_sid));
5497 ret = false;
5502 return ret;
5505 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
5506 struct policy_handle *domain_handle)
5508 struct samr_GetBootKeyInformation r;
5509 NTSTATUS status;
5510 bool ret = true;
5511 uint32_t unknown = 0;
5513 torture_comment(tctx, "Testing GetBootKeyInformation\n");
5515 r.in.domain_handle = domain_handle;
5516 r.out.unknown = &unknown;
5518 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
5519 if (!NT_STATUS_IS_OK(status)) {
5520 /* w2k3 seems to fail this sometimes and pass it sometimes */
5521 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
5524 return ret;
5527 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
5528 struct policy_handle *domain_handle,
5529 struct policy_handle *group_handle)
5531 NTSTATUS status;
5532 struct samr_AddGroupMember r;
5533 struct samr_DeleteGroupMember d;
5534 struct samr_QueryGroupMember q;
5535 struct samr_RidTypeArray *rids = NULL;
5536 struct samr_SetMemberAttributesOfGroup s;
5537 uint32_t rid;
5539 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
5540 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
5542 r.in.group_handle = group_handle;
5543 r.in.rid = rid;
5544 r.in.flags = 0; /* ??? */
5546 torture_comment(tctx, "Testing AddGroupMember and DeleteGroupMember\n");
5548 d.in.group_handle = group_handle;
5549 d.in.rid = rid;
5551 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5552 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
5554 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5555 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5557 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5558 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
5560 if (torture_setting_bool(tctx, "samba4", false)) {
5561 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba4\n");
5562 } else {
5563 /* this one is quite strange. I am using random inputs in the
5564 hope of triggering an error that might give us a clue */
5566 s.in.group_handle = group_handle;
5567 s.in.unknown1 = random();
5568 s.in.unknown2 = random();
5570 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
5571 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
5574 q.in.group_handle = group_handle;
5575 q.out.rids = &rids;
5577 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5578 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5580 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5581 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
5583 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5584 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5586 return true;
5590 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
5591 struct torture_context *tctx,
5592 struct policy_handle *domain_handle,
5593 struct policy_handle *group_handle,
5594 struct dom_sid *domain_sid)
5596 NTSTATUS status;
5597 struct samr_CreateDomainGroup r;
5598 uint32_t rid;
5599 struct lsa_String name;
5600 bool ret = true;
5602 init_lsa_String(&name, TEST_GROUPNAME);
5604 r.in.domain_handle = domain_handle;
5605 r.in.name = &name;
5606 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5607 r.out.group_handle = group_handle;
5608 r.out.rid = &rid;
5610 printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
5612 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5614 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5615 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5616 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
5617 return true;
5618 } else {
5619 printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
5620 nt_errstr(status));
5621 return false;
5625 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
5626 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
5627 printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
5628 nt_errstr(status));
5629 return false;
5631 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5633 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5634 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
5636 printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
5637 nt_errstr(status));
5638 return false;
5640 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5642 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
5644 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
5645 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
5646 ret = false;
5649 if (!test_SetGroupInfo(p, tctx, group_handle)) {
5650 ret = false;
5653 return ret;
5658 its not totally clear what this does. It seems to accept any sid you like.
5660 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
5661 struct torture_context *tctx,
5662 struct policy_handle *domain_handle)
5664 NTSTATUS status;
5665 struct samr_RemoveMemberFromForeignDomain r;
5667 r.in.domain_handle = domain_handle;
5668 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
5670 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
5671 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
5673 return true;
5678 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
5679 struct policy_handle *handle);
5681 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5682 struct policy_handle *handle, struct dom_sid *sid,
5683 enum torture_samr_choice which_ops,
5684 struct cli_credentials *machine_credentials)
5686 NTSTATUS status;
5687 struct samr_OpenDomain r;
5688 struct policy_handle domain_handle;
5689 struct policy_handle alias_handle;
5690 struct policy_handle user_handle;
5691 struct policy_handle group_handle;
5692 bool ret = true;
5694 ZERO_STRUCT(alias_handle);
5695 ZERO_STRUCT(user_handle);
5696 ZERO_STRUCT(group_handle);
5697 ZERO_STRUCT(domain_handle);
5699 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
5701 r.in.connect_handle = handle;
5702 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5703 r.in.sid = sid;
5704 r.out.domain_handle = &domain_handle;
5706 status = dcerpc_samr_OpenDomain(p, tctx, &r);
5707 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
5709 /* run the domain tests with the main handle closed - this tests
5710 the servers reference counting */
5711 ret &= test_samr_handle_Close(p, tctx, handle);
5713 switch (which_ops) {
5714 case TORTURE_SAMR_USER_ATTRIBUTES:
5715 case TORTURE_SAMR_PASSWORDS:
5716 if (!torture_setting_bool(tctx, "samba3", false)) {
5717 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
5719 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
5720 /* This test needs 'complex' users to validate */
5721 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
5722 if (!ret) {
5723 printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
5725 break;
5726 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
5727 if (!torture_setting_bool(tctx, "samba3", false)) {
5728 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, machine_credentials);
5730 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, machine_credentials);
5731 if (!ret) {
5732 printf("Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
5734 break;
5735 case TORTURE_SAMR_OTHER:
5736 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
5737 if (!ret) {
5738 printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
5740 ret &= test_QuerySecurity(p, tctx, &domain_handle);
5741 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
5742 ret &= test_CreateAlias(p, tctx, &domain_handle, &alias_handle, sid);
5743 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle, sid);
5744 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
5745 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
5746 ret &= test_EnumDomainUsers(p, tctx, &domain_handle);
5747 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
5748 ret &= test_EnumDomainGroups(p, tctx, &domain_handle);
5749 ret &= test_EnumDomainAliases(p, tctx, &domain_handle);
5750 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
5751 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
5752 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
5754 if (torture_setting_bool(tctx, "samba4", false)) {
5755 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
5756 } else {
5757 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
5758 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
5760 ret &= test_GroupList(p, tctx, &domain_handle);
5761 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
5762 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
5763 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
5764 if (!ret) {
5765 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
5767 break;
5770 if (!policy_handle_empty(&user_handle) &&
5771 !test_DeleteUser(p, tctx, &user_handle)) {
5772 ret = false;
5775 if (!policy_handle_empty(&alias_handle) &&
5776 !test_DeleteAlias(p, tctx, &alias_handle)) {
5777 ret = false;
5780 if (!policy_handle_empty(&group_handle) &&
5781 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
5782 ret = false;
5785 ret &= test_samr_handle_Close(p, tctx, &domain_handle);
5787 /* reconnect the main handle */
5788 ret &= test_Connect(p, tctx, handle);
5790 if (!ret) {
5791 printf("Testing domain %s failed!\n", dom_sid_string(tctx, sid));
5794 return ret;
5797 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5798 struct policy_handle *handle, const char *domain,
5799 enum torture_samr_choice which_ops,
5800 struct cli_credentials *machine_credentials)
5802 NTSTATUS status;
5803 struct samr_LookupDomain r;
5804 struct dom_sid2 *sid = NULL;
5805 struct lsa_String n1;
5806 struct lsa_String n2;
5807 bool ret = true;
5809 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
5811 /* check for correct error codes */
5812 r.in.connect_handle = handle;
5813 r.in.domain_name = &n2;
5814 r.out.sid = &sid;
5815 n2.string = NULL;
5817 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5818 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
5820 init_lsa_String(&n2, "xxNODOMAINxx");
5822 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5823 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
5825 r.in.connect_handle = handle;
5827 init_lsa_String(&n1, domain);
5828 r.in.domain_name = &n1;
5830 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5831 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
5833 if (!test_GetDomPwInfo(p, tctx, &n1)) {
5834 ret = false;
5837 if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops,
5838 machine_credentials)) {
5839 ret = false;
5842 return ret;
5846 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
5847 struct policy_handle *handle, enum torture_samr_choice which_ops,
5848 struct cli_credentials *machine_credentials)
5850 NTSTATUS status;
5851 struct samr_EnumDomains r;
5852 uint32_t resume_handle = 0;
5853 uint32_t num_entries = 0;
5854 struct samr_SamArray *sam = NULL;
5855 int i;
5856 bool ret = true;
5858 r.in.connect_handle = handle;
5859 r.in.resume_handle = &resume_handle;
5860 r.in.buf_size = (uint32_t)-1;
5861 r.out.resume_handle = &resume_handle;
5862 r.out.num_entries = &num_entries;
5863 r.out.sam = &sam;
5865 status = dcerpc_samr_EnumDomains(p, tctx, &r);
5866 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
5868 if (!*r.out.sam) {
5869 return false;
5872 for (i=0;i<sam->count;i++) {
5873 if (!test_LookupDomain(p, tctx, handle,
5874 sam->entries[i].name.string, which_ops,
5875 machine_credentials)) {
5876 ret = false;
5880 status = dcerpc_samr_EnumDomains(p, tctx, &r);
5881 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
5883 return ret;
5887 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
5888 struct policy_handle *handle)
5890 NTSTATUS status;
5891 struct samr_Connect r;
5892 struct samr_Connect2 r2;
5893 struct samr_Connect3 r3;
5894 struct samr_Connect4 r4;
5895 struct samr_Connect5 r5;
5896 union samr_ConnectInfo info;
5897 struct policy_handle h;
5898 uint32_t level_out = 0;
5899 bool ret = true, got_handle = false;
5901 torture_comment(tctx, "testing samr_Connect\n");
5903 r.in.system_name = 0;
5904 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5905 r.out.connect_handle = &h;
5907 status = dcerpc_samr_Connect(p, tctx, &r);
5908 if (!NT_STATUS_IS_OK(status)) {
5909 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
5910 ret = false;
5911 } else {
5912 got_handle = true;
5913 *handle = h;
5916 torture_comment(tctx, "testing samr_Connect2\n");
5918 r2.in.system_name = NULL;
5919 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5920 r2.out.connect_handle = &h;
5922 status = dcerpc_samr_Connect2(p, tctx, &r2);
5923 if (!NT_STATUS_IS_OK(status)) {
5924 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
5925 ret = false;
5926 } else {
5927 if (got_handle) {
5928 test_samr_handle_Close(p, tctx, handle);
5930 got_handle = true;
5931 *handle = h;
5934 torture_comment(tctx, "testing samr_Connect3\n");
5936 r3.in.system_name = NULL;
5937 r3.in.unknown = 0;
5938 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5939 r3.out.connect_handle = &h;
5941 status = dcerpc_samr_Connect3(p, tctx, &r3);
5942 if (!NT_STATUS_IS_OK(status)) {
5943 printf("Connect3 failed - %s\n", nt_errstr(status));
5944 ret = false;
5945 } else {
5946 if (got_handle) {
5947 test_samr_handle_Close(p, tctx, handle);
5949 got_handle = true;
5950 *handle = h;
5953 torture_comment(tctx, "testing samr_Connect4\n");
5955 r4.in.system_name = "";
5956 r4.in.client_version = 0;
5957 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5958 r4.out.connect_handle = &h;
5960 status = dcerpc_samr_Connect4(p, tctx, &r4);
5961 if (!NT_STATUS_IS_OK(status)) {
5962 printf("Connect4 failed - %s\n", nt_errstr(status));
5963 ret = false;
5964 } else {
5965 if (got_handle) {
5966 test_samr_handle_Close(p, tctx, handle);
5968 got_handle = true;
5969 *handle = h;
5972 torture_comment(tctx, "testing samr_Connect5\n");
5974 info.info1.client_version = 0;
5975 info.info1.unknown2 = 0;
5977 r5.in.system_name = "";
5978 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5979 r5.in.level_in = 1;
5980 r5.out.level_out = &level_out;
5981 r5.in.info_in = &info;
5982 r5.out.info_out = &info;
5983 r5.out.connect_handle = &h;
5985 status = dcerpc_samr_Connect5(p, tctx, &r5);
5986 if (!NT_STATUS_IS_OK(status)) {
5987 printf("Connect5 failed - %s\n", nt_errstr(status));
5988 ret = false;
5989 } else {
5990 if (got_handle) {
5991 test_samr_handle_Close(p, tctx, handle);
5993 got_handle = true;
5994 *handle = h;
5997 return ret;
6001 bool torture_rpc_samr(struct torture_context *torture)
6003 NTSTATUS status;
6004 struct dcerpc_pipe *p;
6005 bool ret = true;
6006 struct policy_handle handle;
6008 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6009 if (!NT_STATUS_IS_OK(status)) {
6010 return false;
6013 ret &= test_Connect(p, torture, &handle);
6015 ret &= test_QuerySecurity(p, torture, &handle);
6017 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
6019 ret &= test_SetDsrmPassword(p, torture, &handle);
6021 ret &= test_Shutdown(p, torture, &handle);
6023 ret &= test_samr_handle_Close(p, torture, &handle);
6025 return ret;
6029 bool torture_rpc_samr_users(struct torture_context *torture)
6031 NTSTATUS status;
6032 struct dcerpc_pipe *p;
6033 bool ret = true;
6034 struct policy_handle handle;
6036 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6037 if (!NT_STATUS_IS_OK(status)) {
6038 return false;
6041 ret &= test_Connect(p, torture, &handle);
6043 if (!torture_setting_bool(torture, "samba3", false)) {
6044 ret &= test_QuerySecurity(p, torture, &handle);
6047 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
6049 ret &= test_SetDsrmPassword(p, torture, &handle);
6051 ret &= test_Shutdown(p, torture, &handle);
6053 ret &= test_samr_handle_Close(p, torture, &handle);
6055 return ret;
6059 bool torture_rpc_samr_passwords(struct torture_context *torture)
6061 NTSTATUS status;
6062 struct dcerpc_pipe *p;
6063 bool ret = true;
6064 struct policy_handle handle;
6066 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6067 if (!NT_STATUS_IS_OK(status)) {
6068 return false;
6071 ret &= test_Connect(p, torture, &handle);
6073 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
6075 ret &= test_samr_handle_Close(p, torture, &handle);
6077 return ret;
6080 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
6081 struct dcerpc_pipe *p2,
6082 struct cli_credentials *machine_credentials)
6084 NTSTATUS status;
6085 struct dcerpc_pipe *p;
6086 bool ret = true;
6087 struct policy_handle handle;
6089 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6090 if (!NT_STATUS_IS_OK(status)) {
6091 return false;
6094 ret &= test_Connect(p, torture, &handle);
6096 ret &= test_EnumDomains(p, torture, &handle,
6097 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
6098 machine_credentials);
6100 ret &= test_samr_handle_Close(p, torture, &handle);
6102 return ret;
6105 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(struct torture_context *tctx)
6107 struct torture_suite *suite = torture_suite_create(tctx, "SAMR-PASSWORDS-PWDLASTSET");
6108 struct torture_rpc_tcase *tcase;
6110 tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
6111 &ndr_table_samr,
6112 TEST_ACCOUNT_NAME_PWD);
6114 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
6115 torture_rpc_samr_pwdlastset);
6117 return suite;