s4-smbtorture: avoid acct_flags check at the end of RPC-SAMR-PASSWORDS for Samba3.
[Samba.git] / source4 / torture / rpc / samr.c
blobfd4e496eb9e80824ed26ba706a471e060aeb77a1
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, TALLOC_CTX *mem_ctx,
52 struct policy_handle *handle);
54 static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
55 struct policy_handle *handle);
57 static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
58 struct policy_handle *handle);
60 static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
61 const char *acct_name,
62 struct policy_handle *domain_handle, char **password);
64 static void init_lsa_String(struct lsa_String *string, const char *s)
66 string->string = s;
69 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
71 string->length = length;
72 string->size = length;
73 string->array = (uint16_t *)discard_const(s);
76 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
77 struct policy_handle *handle)
79 NTSTATUS status;
80 struct samr_Close r;
82 r.in.handle = handle;
83 r.out.handle = handle;
85 status = dcerpc_samr_Close(p, tctx, &r);
86 torture_assert_ntstatus_ok(tctx, status, "Close");
88 return true;
91 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
92 struct policy_handle *handle)
94 NTSTATUS status;
95 struct samr_Shutdown r;
97 if (!torture_setting_bool(tctx, "dangerous", false)) {
98 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
99 return true;
102 r.in.connect_handle = handle;
104 torture_comment(tctx, "testing samr_Shutdown\n");
106 status = dcerpc_samr_Shutdown(p, tctx, &r);
107 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
109 return true;
112 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
113 struct policy_handle *handle)
115 NTSTATUS status;
116 struct samr_SetDsrmPassword r;
117 struct lsa_String string;
118 struct samr_Password hash;
120 if (!torture_setting_bool(tctx, "dangerous", false)) {
121 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
124 E_md4hash("TeSTDSRM123", hash.hash);
126 init_lsa_String(&string, "Administrator");
128 r.in.name = &string;
129 r.in.unknown = 0;
130 r.in.hash = &hash;
132 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
134 status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
135 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
137 return true;
141 static bool test_QuerySecurity(struct dcerpc_pipe *p,
142 struct torture_context *tctx,
143 struct policy_handle *handle)
145 NTSTATUS status;
146 struct samr_QuerySecurity r;
147 struct samr_SetSecurity s;
148 struct sec_desc_buf *sdbuf = NULL;
150 r.in.handle = handle;
151 r.in.sec_info = 7;
152 r.out.sdbuf = &sdbuf;
154 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
155 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
157 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
159 s.in.handle = handle;
160 s.in.sec_info = 7;
161 s.in.sdbuf = sdbuf;
163 if (torture_setting_bool(tctx, "samba4", false)) {
164 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
167 status = dcerpc_samr_SetSecurity(p, tctx, &s);
168 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
170 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
171 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
173 return true;
177 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
178 struct policy_handle *handle, uint32_t base_acct_flags,
179 const char *base_account_name)
181 NTSTATUS status;
182 struct samr_SetUserInfo s;
183 struct samr_SetUserInfo2 s2;
184 struct samr_QueryUserInfo q;
185 struct samr_QueryUserInfo q0;
186 union samr_UserInfo u;
187 union samr_UserInfo *info;
188 bool ret = true;
189 const char *test_account_name;
191 uint32_t user_extra_flags = 0;
192 if (base_acct_flags == ACB_NORMAL) {
193 /* When created, accounts are expired by default */
194 user_extra_flags = ACB_PW_EXPIRED;
197 s.in.user_handle = handle;
198 s.in.info = &u;
200 s2.in.user_handle = handle;
201 s2.in.info = &u;
203 q.in.user_handle = handle;
204 q.out.info = &info;
205 q0 = q;
207 #define TESTCALL(call, r) \
208 status = dcerpc_samr_ ##call(p, tctx, &r); \
209 if (!NT_STATUS_IS_OK(status)) { \
210 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
211 r.in.level, nt_errstr(status), __location__); \
212 ret = false; \
213 break; \
216 #define STRING_EQUAL(s1, s2, field) \
217 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
218 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
219 #field, s2, __location__); \
220 ret = false; \
221 break; \
224 #define MEM_EQUAL(s1, s2, length, field) \
225 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
226 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
227 #field, (const char *)s2, __location__); \
228 ret = false; \
229 break; \
232 #define INT_EQUAL(i1, i2, field) \
233 if (i1 != i2) { \
234 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
235 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
236 ret = false; \
237 break; \
240 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
241 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
242 q.in.level = lvl1; \
243 TESTCALL(QueryUserInfo, q) \
244 s.in.level = lvl1; \
245 s2.in.level = lvl1; \
246 u = *info; \
247 if (lvl1 == 21) { \
248 ZERO_STRUCT(u.info21); \
249 u.info21.fields_present = fpval; \
251 init_lsa_String(&u.info ## lvl1.field1, value); \
252 TESTCALL(SetUserInfo, s) \
253 TESTCALL(SetUserInfo2, s2) \
254 init_lsa_String(&u.info ## lvl1.field1, ""); \
255 TESTCALL(QueryUserInfo, q); \
256 u = *info; \
257 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
258 q.in.level = lvl2; \
259 TESTCALL(QueryUserInfo, q) \
260 u = *info; \
261 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
262 } while (0)
264 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
265 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
266 q.in.level = lvl1; \
267 TESTCALL(QueryUserInfo, q) \
268 s.in.level = lvl1; \
269 s2.in.level = lvl1; \
270 u = *info; \
271 if (lvl1 == 21) { \
272 ZERO_STRUCT(u.info21); \
273 u.info21.fields_present = fpval; \
275 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
276 TESTCALL(SetUserInfo, s) \
277 TESTCALL(SetUserInfo2, s2) \
278 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
279 TESTCALL(QueryUserInfo, q); \
280 u = *info; \
281 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
282 q.in.level = lvl2; \
283 TESTCALL(QueryUserInfo, q) \
284 u = *info; \
285 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
286 } while (0)
288 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
289 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
290 q.in.level = lvl1; \
291 TESTCALL(QueryUserInfo, q) \
292 s.in.level = lvl1; \
293 s2.in.level = lvl1; \
294 u = *info; \
295 if (lvl1 == 21) { \
296 uint8_t *bits = u.info21.logon_hours.bits; \
297 ZERO_STRUCT(u.info21); \
298 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
299 u.info21.logon_hours.units_per_week = 168; \
300 u.info21.logon_hours.bits = bits; \
302 u.info21.fields_present = fpval; \
304 u.info ## lvl1.field1 = value; \
305 TESTCALL(SetUserInfo, s) \
306 TESTCALL(SetUserInfo2, s2) \
307 u.info ## lvl1.field1 = 0; \
308 TESTCALL(QueryUserInfo, q); \
309 u = *info; \
310 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
311 q.in.level = lvl2; \
312 TESTCALL(QueryUserInfo, q) \
313 u = *info; \
314 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
315 } while (0)
317 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
318 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
319 } while (0)
321 q0.in.level = 12;
322 do { TESTCALL(QueryUserInfo, q0) } while (0);
324 /* Samba 3 cannot store comment fields atm. - gd */
325 if (!torture_setting_bool(tctx, "samba3", false)) {
326 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
327 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
328 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
329 SAMR_FIELD_COMMENT);
332 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
333 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
334 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
335 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
336 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
337 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
338 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
339 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
340 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
341 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
342 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
343 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
344 test_account_name = base_account_name;
345 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
346 SAMR_FIELD_ACCOUNT_NAME);
348 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
349 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
350 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
351 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
352 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
353 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
354 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
355 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
356 SAMR_FIELD_FULL_NAME);
358 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
359 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
360 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
361 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
362 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
363 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
364 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
365 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
366 SAMR_FIELD_FULL_NAME);
368 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
369 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
370 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
371 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
372 SAMR_FIELD_LOGON_SCRIPT);
374 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
375 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
376 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
377 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
378 SAMR_FIELD_PROFILE_PATH);
380 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
381 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
382 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
383 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
384 SAMR_FIELD_HOME_DIRECTORY);
385 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
386 SAMR_FIELD_HOME_DIRECTORY);
388 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
389 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
390 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
391 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
392 SAMR_FIELD_HOME_DRIVE);
393 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
394 SAMR_FIELD_HOME_DRIVE);
396 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
397 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
398 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
399 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
400 SAMR_FIELD_DESCRIPTION);
402 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
403 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
404 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
405 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
406 SAMR_FIELD_WORKSTATIONS);
407 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
408 SAMR_FIELD_WORKSTATIONS);
409 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
410 SAMR_FIELD_WORKSTATIONS);
411 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
412 SAMR_FIELD_WORKSTATIONS);
414 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
415 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
416 SAMR_FIELD_PARAMETERS);
417 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
418 SAMR_FIELD_PARAMETERS);
419 /* also empty user parameters are allowed */
420 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
421 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
422 SAMR_FIELD_PARAMETERS);
423 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
424 SAMR_FIELD_PARAMETERS);
426 /* Samba 3 cannot store country_code and copy_page atm. - gd */
427 if (!torture_setting_bool(tctx, "samba3", false)) {
428 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
429 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
430 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
431 SAMR_FIELD_COUNTRY_CODE);
432 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
433 SAMR_FIELD_COUNTRY_CODE);
435 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
436 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
437 SAMR_FIELD_CODE_PAGE);
438 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
439 SAMR_FIELD_CODE_PAGE);
442 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
443 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
444 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
445 SAMR_FIELD_ACCT_EXPIRY);
446 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
447 SAMR_FIELD_ACCT_EXPIRY);
448 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
449 SAMR_FIELD_ACCT_EXPIRY);
451 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
452 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
453 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
454 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
455 SAMR_FIELD_LOGON_HOURS);
457 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
458 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
459 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
461 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
462 (base_acct_flags | ACB_DISABLED),
463 (base_acct_flags | ACB_DISABLED | user_extra_flags),
466 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
467 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
468 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
469 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
471 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
472 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
473 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
477 /* The 'autolock' flag doesn't stick - check this */
478 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
479 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
480 (base_acct_flags | ACB_DISABLED | user_extra_flags),
482 #if 0
483 /* Removing the 'disabled' flag doesn't stick - check this */
484 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
485 (base_acct_flags),
486 (base_acct_flags | ACB_DISABLED | user_extra_flags),
488 #endif
489 /* The 'store plaintext' flag does stick */
490 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
491 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
492 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
494 /* The 'use DES' flag does stick */
495 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
496 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
497 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
499 /* The 'don't require kerberos pre-authentication flag does stick */
500 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
501 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
502 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
504 /* The 'no kerberos PAC required' flag sticks */
505 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
506 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
507 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
510 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
511 (base_acct_flags | ACB_DISABLED),
512 (base_acct_flags | ACB_DISABLED | user_extra_flags),
513 SAMR_FIELD_ACCT_FLAGS);
515 #if 0
516 /* these fail with win2003 - it appears you can't set the primary gid?
517 the set succeeds, but the gid isn't changed. Very weird! */
518 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
519 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
520 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
521 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
522 #endif
524 return ret;
528 generate a random password for password change tests
530 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
532 size_t len = MAX(8, min_len) + (random() % 6);
533 char *s = generate_random_str(mem_ctx, len);
534 return s;
537 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
539 char *s = samr_rand_pass_silent(mem_ctx, min_len);
540 printf("Generated password '%s'\n", s);
541 return s;
546 generate a random password for password change tests
548 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
550 int i;
551 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
552 generate_random_buffer(password.data, password.length);
554 for (i=0; i < len; i++) {
555 if (((uint16_t *)password.data)[i] == 0) {
556 ((uint16_t *)password.data)[i] = 1;
560 return password;
564 generate a random password for password change tests (fixed length)
566 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
568 char *s = generate_random_str(mem_ctx, len);
569 printf("Generated password '%s'\n", s);
570 return s;
573 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
574 struct policy_handle *handle, char **password)
576 NTSTATUS status;
577 struct samr_SetUserInfo s;
578 union samr_UserInfo u;
579 bool ret = true;
580 DATA_BLOB session_key;
581 char *newpass;
582 struct samr_GetUserPwInfo pwp;
583 struct samr_PwInfo info;
584 int policy_min_pw_len = 0;
585 pwp.in.user_handle = handle;
586 pwp.out.info = &info;
588 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
589 if (NT_STATUS_IS_OK(status)) {
590 policy_min_pw_len = pwp.out.info->min_password_length;
592 newpass = samr_rand_pass(tctx, policy_min_pw_len);
594 s.in.user_handle = handle;
595 s.in.info = &u;
596 s.in.level = 24;
598 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
599 u.info24.password_expired = 0;
601 status = dcerpc_fetch_session_key(p, &session_key);
602 if (!NT_STATUS_IS_OK(status)) {
603 printf("SetUserInfo level %u - no session key - %s\n",
604 s.in.level, nt_errstr(status));
605 return false;
608 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
610 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
612 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
613 if (!NT_STATUS_IS_OK(status)) {
614 printf("SetUserInfo level %u failed - %s\n",
615 s.in.level, nt_errstr(status));
616 ret = false;
617 } else {
618 *password = newpass;
621 return ret;
625 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
626 struct policy_handle *handle, uint32_t fields_present,
627 char **password)
629 NTSTATUS status;
630 struct samr_SetUserInfo s;
631 union samr_UserInfo u;
632 bool ret = true;
633 DATA_BLOB session_key;
634 char *newpass;
635 struct samr_GetUserPwInfo pwp;
636 struct samr_PwInfo info;
637 int policy_min_pw_len = 0;
638 pwp.in.user_handle = handle;
639 pwp.out.info = &info;
641 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
642 if (NT_STATUS_IS_OK(status)) {
643 policy_min_pw_len = pwp.out.info->min_password_length;
645 newpass = samr_rand_pass(tctx, policy_min_pw_len);
647 s.in.user_handle = handle;
648 s.in.info = &u;
649 s.in.level = 23;
651 ZERO_STRUCT(u);
653 u.info23.info.fields_present = fields_present;
655 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
657 status = dcerpc_fetch_session_key(p, &session_key);
658 if (!NT_STATUS_IS_OK(status)) {
659 printf("SetUserInfo level %u - no session key - %s\n",
660 s.in.level, nt_errstr(status));
661 return false;
664 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
666 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
668 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
669 if (!NT_STATUS_IS_OK(status)) {
670 printf("SetUserInfo level %u failed - %s\n",
671 s.in.level, nt_errstr(status));
672 ret = false;
673 } else {
674 *password = newpass;
677 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
679 status = dcerpc_fetch_session_key(p, &session_key);
680 if (!NT_STATUS_IS_OK(status)) {
681 printf("SetUserInfo level %u - no session key - %s\n",
682 s.in.level, nt_errstr(status));
683 return false;
686 /* This should break the key nicely */
687 session_key.length--;
688 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
690 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
692 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
693 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
694 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
695 s.in.level, nt_errstr(status));
696 ret = false;
699 return ret;
703 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
704 struct policy_handle *handle, bool makeshort,
705 char **password)
707 NTSTATUS status;
708 struct samr_SetUserInfo s;
709 union samr_UserInfo u;
710 bool ret = true;
711 DATA_BLOB session_key;
712 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
713 uint8_t confounder[16];
714 char *newpass;
715 struct MD5Context ctx;
716 struct samr_GetUserPwInfo pwp;
717 struct samr_PwInfo info;
718 int policy_min_pw_len = 0;
719 pwp.in.user_handle = handle;
720 pwp.out.info = &info;
722 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
723 if (NT_STATUS_IS_OK(status)) {
724 policy_min_pw_len = pwp.out.info->min_password_length;
726 if (makeshort && policy_min_pw_len) {
727 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
728 } else {
729 newpass = samr_rand_pass(tctx, policy_min_pw_len);
732 s.in.user_handle = handle;
733 s.in.info = &u;
734 s.in.level = 26;
736 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
737 u.info26.password_expired = 0;
739 status = dcerpc_fetch_session_key(p, &session_key);
740 if (!NT_STATUS_IS_OK(status)) {
741 printf("SetUserInfo level %u - no session key - %s\n",
742 s.in.level, nt_errstr(status));
743 return false;
746 generate_random_buffer((uint8_t *)confounder, 16);
748 MD5Init(&ctx);
749 MD5Update(&ctx, confounder, 16);
750 MD5Update(&ctx, session_key.data, session_key.length);
751 MD5Final(confounded_session_key.data, &ctx);
753 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
754 memcpy(&u.info26.password.data[516], confounder, 16);
756 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
758 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
759 if (!NT_STATUS_IS_OK(status)) {
760 printf("SetUserInfo level %u failed - %s\n",
761 s.in.level, nt_errstr(status));
762 ret = false;
763 } else {
764 *password = newpass;
767 /* This should break the key nicely */
768 confounded_session_key.data[0]++;
770 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
771 memcpy(&u.info26.password.data[516], confounder, 16);
773 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
775 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
776 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
777 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
778 s.in.level, nt_errstr(status));
779 ret = false;
780 } else {
781 *password = newpass;
784 return ret;
787 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
788 struct policy_handle *handle, uint32_t fields_present,
789 char **password)
791 NTSTATUS status;
792 struct samr_SetUserInfo s;
793 union samr_UserInfo u;
794 bool ret = true;
795 DATA_BLOB session_key;
796 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
797 struct MD5Context ctx;
798 uint8_t confounder[16];
799 char *newpass;
800 struct samr_GetUserPwInfo pwp;
801 struct samr_PwInfo info;
802 int policy_min_pw_len = 0;
803 pwp.in.user_handle = handle;
804 pwp.out.info = &info;
806 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
807 if (NT_STATUS_IS_OK(status)) {
808 policy_min_pw_len = pwp.out.info->min_password_length;
810 newpass = samr_rand_pass(tctx, policy_min_pw_len);
812 s.in.user_handle = handle;
813 s.in.info = &u;
814 s.in.level = 25;
816 ZERO_STRUCT(u);
818 u.info25.info.fields_present = fields_present;
820 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
822 status = dcerpc_fetch_session_key(p, &session_key);
823 if (!NT_STATUS_IS_OK(status)) {
824 printf("SetUserInfo level %u - no session key - %s\n",
825 s.in.level, nt_errstr(status));
826 return false;
829 generate_random_buffer((uint8_t *)confounder, 16);
831 MD5Init(&ctx);
832 MD5Update(&ctx, confounder, 16);
833 MD5Update(&ctx, session_key.data, session_key.length);
834 MD5Final(confounded_session_key.data, &ctx);
836 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
837 memcpy(&u.info25.password.data[516], confounder, 16);
839 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
841 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
842 if (!NT_STATUS_IS_OK(status)) {
843 printf("SetUserInfo level %u failed - %s\n",
844 s.in.level, nt_errstr(status));
845 ret = false;
846 } else {
847 *password = newpass;
850 /* This should break the key nicely */
851 confounded_session_key.data[0]++;
853 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
854 memcpy(&u.info25.password.data[516], confounder, 16);
856 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
858 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
859 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
860 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
861 s.in.level, nt_errstr(status));
862 ret = false;
865 return ret;
868 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
869 struct policy_handle *handle, char **password)
871 NTSTATUS status;
872 struct samr_SetUserInfo s;
873 union samr_UserInfo u;
874 bool ret = true;
875 DATA_BLOB session_key;
876 char *newpass;
877 struct samr_GetUserPwInfo pwp;
878 struct samr_PwInfo info;
879 int policy_min_pw_len = 0;
880 uint8_t lm_hash[16], nt_hash[16];
882 pwp.in.user_handle = handle;
883 pwp.out.info = &info;
885 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
886 if (NT_STATUS_IS_OK(status)) {
887 policy_min_pw_len = pwp.out.info->min_password_length;
889 newpass = samr_rand_pass(tctx, policy_min_pw_len);
891 s.in.user_handle = handle;
892 s.in.info = &u;
893 s.in.level = 18;
895 ZERO_STRUCT(u);
897 u.info18.nt_pwd_active = true;
898 u.info18.lm_pwd_active = true;
900 E_md4hash(newpass, nt_hash);
901 E_deshash(newpass, lm_hash);
903 status = dcerpc_fetch_session_key(p, &session_key);
904 if (!NT_STATUS_IS_OK(status)) {
905 printf("SetUserInfo level %u - no session key - %s\n",
906 s.in.level, nt_errstr(status));
907 return false;
911 DATA_BLOB in,out;
912 in = data_blob_const(nt_hash, 16);
913 out = data_blob_talloc_zero(tctx, 16);
914 sess_crypt_blob(&out, &in, &session_key, true);
915 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
918 DATA_BLOB in,out;
919 in = data_blob_const(lm_hash, 16);
920 out = data_blob_talloc_zero(tctx, 16);
921 sess_crypt_blob(&out, &in, &session_key, true);
922 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
925 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
927 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
928 if (!NT_STATUS_IS_OK(status)) {
929 printf("SetUserInfo level %u failed - %s\n",
930 s.in.level, nt_errstr(status));
931 ret = false;
932 } else {
933 *password = newpass;
936 return ret;
939 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
940 struct policy_handle *handle, uint32_t fields_present,
941 char **password)
943 NTSTATUS status;
944 struct samr_SetUserInfo s;
945 union samr_UserInfo u;
946 bool ret = true;
947 DATA_BLOB session_key;
948 char *newpass;
949 struct samr_GetUserPwInfo pwp;
950 struct samr_PwInfo info;
951 int policy_min_pw_len = 0;
952 uint8_t lm_hash[16], nt_hash[16];
954 pwp.in.user_handle = handle;
955 pwp.out.info = &info;
957 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
958 if (NT_STATUS_IS_OK(status)) {
959 policy_min_pw_len = pwp.out.info->min_password_length;
961 newpass = samr_rand_pass(tctx, policy_min_pw_len);
963 s.in.user_handle = handle;
964 s.in.info = &u;
965 s.in.level = 21;
967 E_md4hash(newpass, nt_hash);
968 E_deshash(newpass, lm_hash);
970 ZERO_STRUCT(u);
972 u.info21.fields_present = fields_present;
974 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
975 u.info21.lm_owf_password.length = 16;
976 u.info21.lm_owf_password.size = 16;
977 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
978 u.info21.lm_password_set = true;
981 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
982 u.info21.nt_owf_password.length = 16;
983 u.info21.nt_owf_password.size = 16;
984 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
985 u.info21.nt_password_set = true;
988 status = dcerpc_fetch_session_key(p, &session_key);
989 if (!NT_STATUS_IS_OK(status)) {
990 printf("SetUserInfo level %u - no session key - %s\n",
991 s.in.level, nt_errstr(status));
992 return false;
995 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
996 DATA_BLOB in,out;
997 in = data_blob_const(u.info21.lm_owf_password.array,
998 u.info21.lm_owf_password.length);
999 out = data_blob_talloc_zero(tctx, 16);
1000 sess_crypt_blob(&out, &in, &session_key, true);
1001 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1004 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1005 DATA_BLOB in,out;
1006 in = data_blob_const(u.info21.nt_owf_password.array,
1007 u.info21.nt_owf_password.length);
1008 out = data_blob_talloc_zero(tctx, 16);
1009 sess_crypt_blob(&out, &in, &session_key, true);
1010 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1013 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1015 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1016 if (!NT_STATUS_IS_OK(status)) {
1017 printf("SetUserInfo level %u failed - %s\n",
1018 s.in.level, nt_errstr(status));
1019 ret = false;
1020 } else {
1021 *password = newpass;
1024 /* try invalid length */
1025 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1027 u.info21.nt_owf_password.length++;
1029 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1031 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1032 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1033 s.in.level, nt_errstr(status));
1034 ret = false;
1038 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1040 u.info21.lm_owf_password.length++;
1042 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1044 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1045 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1046 s.in.level, nt_errstr(status));
1047 ret = false;
1051 return ret;
1054 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1055 struct torture_context *tctx,
1056 struct policy_handle *handle,
1057 uint16_t level,
1058 uint32_t fields_present,
1059 char **password, uint8_t password_expired,
1060 bool use_setinfo2,
1061 bool *matched_expected_error)
1063 NTSTATUS status;
1064 NTSTATUS expected_error = NT_STATUS_OK;
1065 struct samr_SetUserInfo s;
1066 struct samr_SetUserInfo2 s2;
1067 union samr_UserInfo u;
1068 bool ret = true;
1069 DATA_BLOB session_key;
1070 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1071 struct MD5Context ctx;
1072 uint8_t confounder[16];
1073 char *newpass;
1074 struct samr_GetUserPwInfo pwp;
1075 struct samr_PwInfo info;
1076 int policy_min_pw_len = 0;
1077 const char *comment = NULL;
1078 uint8_t lm_hash[16], nt_hash[16];
1080 pwp.in.user_handle = handle;
1081 pwp.out.info = &info;
1083 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1084 if (NT_STATUS_IS_OK(status)) {
1085 policy_min_pw_len = pwp.out.info->min_password_length;
1087 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1089 if (use_setinfo2) {
1090 s2.in.user_handle = handle;
1091 s2.in.info = &u;
1092 s2.in.level = level;
1093 } else {
1094 s.in.user_handle = handle;
1095 s.in.info = &u;
1096 s.in.level = level;
1099 if (fields_present & SAMR_FIELD_COMMENT) {
1100 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1103 ZERO_STRUCT(u);
1105 switch (level) {
1106 case 18:
1107 E_md4hash(newpass, nt_hash);
1108 E_deshash(newpass, lm_hash);
1110 u.info18.nt_pwd_active = true;
1111 u.info18.lm_pwd_active = true;
1112 u.info18.password_expired = password_expired;
1114 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1115 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1117 break;
1118 case 21:
1119 E_md4hash(newpass, nt_hash);
1120 E_deshash(newpass, lm_hash);
1122 u.info21.fields_present = fields_present;
1123 u.info21.password_expired = password_expired;
1124 u.info21.comment.string = comment;
1126 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1127 u.info21.lm_owf_password.length = 16;
1128 u.info21.lm_owf_password.size = 16;
1129 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1130 u.info21.lm_password_set = true;
1133 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1134 u.info21.nt_owf_password.length = 16;
1135 u.info21.nt_owf_password.size = 16;
1136 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1137 u.info21.nt_password_set = true;
1140 break;
1141 case 23:
1142 u.info23.info.fields_present = fields_present;
1143 u.info23.info.password_expired = password_expired;
1144 u.info23.info.comment.string = comment;
1146 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1148 break;
1149 case 24:
1150 u.info24.password_expired = password_expired;
1152 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1154 break;
1155 case 25:
1156 u.info25.info.fields_present = fields_present;
1157 u.info25.info.password_expired = password_expired;
1158 u.info25.info.comment.string = comment;
1160 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1162 break;
1163 case 26:
1164 u.info26.password_expired = password_expired;
1166 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1168 break;
1171 status = dcerpc_fetch_session_key(p, &session_key);
1172 if (!NT_STATUS_IS_OK(status)) {
1173 printf("SetUserInfo level %u - no session key - %s\n",
1174 s.in.level, nt_errstr(status));
1175 return false;
1178 generate_random_buffer((uint8_t *)confounder, 16);
1180 MD5Init(&ctx);
1181 MD5Update(&ctx, confounder, 16);
1182 MD5Update(&ctx, session_key.data, session_key.length);
1183 MD5Final(confounded_session_key.data, &ctx);
1185 switch (level) {
1186 case 18:
1188 DATA_BLOB in,out;
1189 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1190 out = data_blob_talloc_zero(tctx, 16);
1191 sess_crypt_blob(&out, &in, &session_key, true);
1192 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1195 DATA_BLOB in,out;
1196 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1197 out = data_blob_talloc_zero(tctx, 16);
1198 sess_crypt_blob(&out, &in, &session_key, true);
1199 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1202 break;
1203 case 21:
1204 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1205 DATA_BLOB in,out;
1206 in = data_blob_const(u.info21.lm_owf_password.array,
1207 u.info21.lm_owf_password.length);
1208 out = data_blob_talloc_zero(tctx, 16);
1209 sess_crypt_blob(&out, &in, &session_key, true);
1210 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1212 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1213 DATA_BLOB in,out;
1214 in = data_blob_const(u.info21.nt_owf_password.array,
1215 u.info21.nt_owf_password.length);
1216 out = data_blob_talloc_zero(tctx, 16);
1217 sess_crypt_blob(&out, &in, &session_key, true);
1218 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1220 break;
1221 case 23:
1222 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1223 break;
1224 case 24:
1225 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1226 break;
1227 case 25:
1228 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1229 memcpy(&u.info25.password.data[516], confounder, 16);
1230 break;
1231 case 26:
1232 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1233 memcpy(&u.info26.password.data[516], confounder, 16);
1234 break;
1237 if (use_setinfo2) {
1238 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1239 } else {
1240 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1243 if (!NT_STATUS_IS_OK(status)) {
1244 if (fields_present == 0) {
1245 expected_error = NT_STATUS_INVALID_PARAMETER;
1247 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1248 expected_error = NT_STATUS_ACCESS_DENIED;
1252 if (!NT_STATUS_IS_OK(expected_error)) {
1253 if (use_setinfo2) {
1254 torture_assert_ntstatus_equal(tctx,
1255 s2.out.result,
1256 expected_error, "SetUserInfo2 failed");
1257 } else {
1258 torture_assert_ntstatus_equal(tctx,
1259 s.out.result,
1260 expected_error, "SetUserInfo failed");
1262 *matched_expected_error = true;
1263 return true;
1266 if (!NT_STATUS_IS_OK(status)) {
1267 printf("SetUserInfo%s level %u failed - %s\n",
1268 use_setinfo2 ? "2":"", level, nt_errstr(status));
1269 ret = false;
1270 } else {
1271 *password = newpass;
1274 return ret;
1277 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1278 struct policy_handle *handle)
1280 NTSTATUS status;
1281 struct samr_SetAliasInfo r;
1282 struct samr_QueryAliasInfo q;
1283 union samr_AliasInfo *info;
1284 uint16_t levels[] = {2, 3};
1285 int i;
1286 bool ret = true;
1288 /* Ignoring switch level 1, as that includes the number of members for the alias
1289 * and setting this to a wrong value might have negative consequences
1292 for (i=0;i<ARRAY_SIZE(levels);i++) {
1293 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1295 r.in.alias_handle = handle;
1296 r.in.level = levels[i];
1297 r.in.info = talloc(tctx, union samr_AliasInfo);
1298 switch (r.in.level) {
1299 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1300 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1301 "Test Description, should test I18N as well"); break;
1302 case ALIASINFOALL: printf("ALIASINFOALL ignored\n"); break;
1305 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1306 if (!NT_STATUS_IS_OK(status)) {
1307 printf("SetAliasInfo level %u failed - %s\n",
1308 levels[i], nt_errstr(status));
1309 ret = false;
1312 q.in.alias_handle = handle;
1313 q.in.level = levels[i];
1314 q.out.info = &info;
1316 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1317 if (!NT_STATUS_IS_OK(status)) {
1318 printf("QueryAliasInfo level %u failed - %s\n",
1319 levels[i], nt_errstr(status));
1320 ret = false;
1324 return ret;
1327 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1328 struct policy_handle *user_handle)
1330 struct samr_GetGroupsForUser r;
1331 struct samr_RidWithAttributeArray *rids = NULL;
1332 NTSTATUS status;
1334 torture_comment(tctx, "testing GetGroupsForUser\n");
1336 r.in.user_handle = user_handle;
1337 r.out.rids = &rids;
1339 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1340 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1342 return true;
1346 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1347 struct lsa_String *domain_name)
1349 NTSTATUS status;
1350 struct samr_GetDomPwInfo r;
1351 struct samr_PwInfo info;
1353 r.in.domain_name = domain_name;
1354 r.out.info = &info;
1356 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1358 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1359 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1361 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1362 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1364 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1365 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1367 r.in.domain_name->string = "\\\\__NONAME__";
1368 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1370 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1371 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1373 r.in.domain_name->string = "\\\\Builtin";
1374 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1376 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1377 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1379 return true;
1382 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1383 struct policy_handle *handle)
1385 NTSTATUS status;
1386 struct samr_GetUserPwInfo r;
1387 struct samr_PwInfo info;
1389 torture_comment(tctx, "Testing GetUserPwInfo\n");
1391 r.in.user_handle = handle;
1392 r.out.info = &info;
1394 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1395 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1397 return true;
1400 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1401 struct policy_handle *domain_handle, const char *name,
1402 uint32_t *rid)
1404 NTSTATUS status;
1405 struct samr_LookupNames n;
1406 struct lsa_String sname[2];
1407 struct samr_Ids rids, types;
1409 init_lsa_String(&sname[0], name);
1411 n.in.domain_handle = domain_handle;
1412 n.in.num_names = 1;
1413 n.in.names = sname;
1414 n.out.rids = &rids;
1415 n.out.types = &types;
1416 status = dcerpc_samr_LookupNames(p, tctx, &n);
1417 if (NT_STATUS_IS_OK(status)) {
1418 *rid = n.out.rids->ids[0];
1419 } else {
1420 return status;
1423 init_lsa_String(&sname[1], "xxNONAMExx");
1424 n.in.num_names = 2;
1425 status = dcerpc_samr_LookupNames(p, tctx, &n);
1426 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1427 printf("LookupNames[2] failed - %s\n", nt_errstr(status));
1428 if (NT_STATUS_IS_OK(status)) {
1429 return NT_STATUS_UNSUCCESSFUL;
1431 return status;
1434 n.in.num_names = 0;
1435 status = dcerpc_samr_LookupNames(p, tctx, &n);
1436 if (!NT_STATUS_IS_OK(status)) {
1437 printf("LookupNames[0] failed - %s\n", nt_errstr(status));
1438 return status;
1441 init_lsa_String(&sname[0], "xxNONAMExx");
1442 n.in.num_names = 1;
1443 status = dcerpc_samr_LookupNames(p, tctx, &n);
1444 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1445 printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1446 if (NT_STATUS_IS_OK(status)) {
1447 return NT_STATUS_UNSUCCESSFUL;
1449 return status;
1452 init_lsa_String(&sname[0], "xxNONAMExx");
1453 init_lsa_String(&sname[1], "xxNONAME2xx");
1454 n.in.num_names = 2;
1455 status = dcerpc_samr_LookupNames(p, tctx, &n);
1456 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1457 printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1458 if (NT_STATUS_IS_OK(status)) {
1459 return NT_STATUS_UNSUCCESSFUL;
1461 return status;
1464 return NT_STATUS_OK;
1467 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1468 struct policy_handle *domain_handle,
1469 const char *name, struct policy_handle *user_handle)
1471 NTSTATUS status;
1472 struct samr_OpenUser r;
1473 uint32_t rid;
1475 status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
1476 if (!NT_STATUS_IS_OK(status)) {
1477 return status;
1480 r.in.domain_handle = domain_handle;
1481 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1482 r.in.rid = rid;
1483 r.out.user_handle = user_handle;
1484 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
1485 if (!NT_STATUS_IS_OK(status)) {
1486 printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1489 return status;
1492 #if 0
1493 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1494 struct policy_handle *handle)
1496 NTSTATUS status;
1497 struct samr_ChangePasswordUser r;
1498 bool ret = true;
1499 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1500 struct policy_handle user_handle;
1501 char *oldpass = "test";
1502 char *newpass = "test2";
1503 uint8_t old_nt_hash[16], new_nt_hash[16];
1504 uint8_t old_lm_hash[16], new_lm_hash[16];
1506 status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
1507 if (!NT_STATUS_IS_OK(status)) {
1508 return false;
1511 printf("Testing ChangePasswordUser for user 'testuser'\n");
1513 printf("old password: %s\n", oldpass);
1514 printf("new password: %s\n", newpass);
1516 E_md4hash(oldpass, old_nt_hash);
1517 E_md4hash(newpass, new_nt_hash);
1518 E_deshash(oldpass, old_lm_hash);
1519 E_deshash(newpass, new_lm_hash);
1521 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1522 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1523 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1524 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1525 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1526 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1528 r.in.handle = &user_handle;
1529 r.in.lm_present = 1;
1530 r.in.old_lm_crypted = &hash1;
1531 r.in.new_lm_crypted = &hash2;
1532 r.in.nt_present = 1;
1533 r.in.old_nt_crypted = &hash3;
1534 r.in.new_nt_crypted = &hash4;
1535 r.in.cross1_present = 1;
1536 r.in.nt_cross = &hash5;
1537 r.in.cross2_present = 1;
1538 r.in.lm_cross = &hash6;
1540 status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1541 if (!NT_STATUS_IS_OK(status)) {
1542 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1543 ret = false;
1546 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
1547 ret = false;
1550 return ret;
1552 #endif
1554 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1555 const char *acct_name,
1556 struct policy_handle *handle, char **password)
1558 NTSTATUS status;
1559 struct samr_ChangePasswordUser r;
1560 bool ret = true;
1561 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1562 struct policy_handle user_handle;
1563 char *oldpass;
1564 uint8_t old_nt_hash[16], new_nt_hash[16];
1565 uint8_t old_lm_hash[16], new_lm_hash[16];
1566 bool changed = true;
1568 char *newpass;
1569 struct samr_GetUserPwInfo pwp;
1570 struct samr_PwInfo info;
1571 int policy_min_pw_len = 0;
1573 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1574 if (!NT_STATUS_IS_OK(status)) {
1575 return false;
1577 pwp.in.user_handle = &user_handle;
1578 pwp.out.info = &info;
1580 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1581 if (NT_STATUS_IS_OK(status)) {
1582 policy_min_pw_len = pwp.out.info->min_password_length;
1584 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1586 torture_comment(tctx, "Testing ChangePasswordUser\n");
1588 torture_assert(tctx, *password != NULL,
1589 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1591 oldpass = *password;
1593 E_md4hash(oldpass, old_nt_hash);
1594 E_md4hash(newpass, new_nt_hash);
1595 E_deshash(oldpass, old_lm_hash);
1596 E_deshash(newpass, new_lm_hash);
1598 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1599 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1600 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1601 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1602 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1603 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1605 r.in.user_handle = &user_handle;
1606 r.in.lm_present = 1;
1607 /* Break the LM hash */
1608 hash1.hash[0]++;
1609 r.in.old_lm_crypted = &hash1;
1610 r.in.new_lm_crypted = &hash2;
1611 r.in.nt_present = 1;
1612 r.in.old_nt_crypted = &hash3;
1613 r.in.new_nt_crypted = &hash4;
1614 r.in.cross1_present = 1;
1615 r.in.nt_cross = &hash5;
1616 r.in.cross2_present = 1;
1617 r.in.lm_cross = &hash6;
1619 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1620 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1621 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1623 /* Unbreak the LM hash */
1624 hash1.hash[0]--;
1626 r.in.user_handle = &user_handle;
1627 r.in.lm_present = 1;
1628 r.in.old_lm_crypted = &hash1;
1629 r.in.new_lm_crypted = &hash2;
1630 /* Break the NT hash */
1631 hash3.hash[0]--;
1632 r.in.nt_present = 1;
1633 r.in.old_nt_crypted = &hash3;
1634 r.in.new_nt_crypted = &hash4;
1635 r.in.cross1_present = 1;
1636 r.in.nt_cross = &hash5;
1637 r.in.cross2_present = 1;
1638 r.in.lm_cross = &hash6;
1640 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1641 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1642 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1644 /* Unbreak the NT hash */
1645 hash3.hash[0]--;
1647 r.in.user_handle = &user_handle;
1648 r.in.lm_present = 1;
1649 r.in.old_lm_crypted = &hash1;
1650 r.in.new_lm_crypted = &hash2;
1651 r.in.nt_present = 1;
1652 r.in.old_nt_crypted = &hash3;
1653 r.in.new_nt_crypted = &hash4;
1654 r.in.cross1_present = 1;
1655 r.in.nt_cross = &hash5;
1656 r.in.cross2_present = 1;
1657 /* Break the LM cross */
1658 hash6.hash[0]++;
1659 r.in.lm_cross = &hash6;
1661 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1662 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1663 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1664 ret = false;
1667 /* Unbreak the LM cross */
1668 hash6.hash[0]--;
1670 r.in.user_handle = &user_handle;
1671 r.in.lm_present = 1;
1672 r.in.old_lm_crypted = &hash1;
1673 r.in.new_lm_crypted = &hash2;
1674 r.in.nt_present = 1;
1675 r.in.old_nt_crypted = &hash3;
1676 r.in.new_nt_crypted = &hash4;
1677 r.in.cross1_present = 1;
1678 /* Break the NT cross */
1679 hash5.hash[0]++;
1680 r.in.nt_cross = &hash5;
1681 r.in.cross2_present = 1;
1682 r.in.lm_cross = &hash6;
1684 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1685 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1686 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1687 ret = false;
1690 /* Unbreak the NT cross */
1691 hash5.hash[0]--;
1694 /* Reset the hashes to not broken values */
1695 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1696 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1697 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1698 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1699 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1700 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1702 r.in.user_handle = &user_handle;
1703 r.in.lm_present = 1;
1704 r.in.old_lm_crypted = &hash1;
1705 r.in.new_lm_crypted = &hash2;
1706 r.in.nt_present = 1;
1707 r.in.old_nt_crypted = &hash3;
1708 r.in.new_nt_crypted = &hash4;
1709 r.in.cross1_present = 1;
1710 r.in.nt_cross = &hash5;
1711 r.in.cross2_present = 0;
1712 r.in.lm_cross = NULL;
1714 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1715 if (NT_STATUS_IS_OK(status)) {
1716 changed = true;
1717 *password = newpass;
1718 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1719 printf("ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1720 ret = false;
1723 oldpass = newpass;
1724 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1726 E_md4hash(oldpass, old_nt_hash);
1727 E_md4hash(newpass, new_nt_hash);
1728 E_deshash(oldpass, old_lm_hash);
1729 E_deshash(newpass, new_lm_hash);
1732 /* Reset the hashes to not broken values */
1733 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1734 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1735 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1736 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1737 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1738 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1740 r.in.user_handle = &user_handle;
1741 r.in.lm_present = 1;
1742 r.in.old_lm_crypted = &hash1;
1743 r.in.new_lm_crypted = &hash2;
1744 r.in.nt_present = 1;
1745 r.in.old_nt_crypted = &hash3;
1746 r.in.new_nt_crypted = &hash4;
1747 r.in.cross1_present = 0;
1748 r.in.nt_cross = NULL;
1749 r.in.cross2_present = 1;
1750 r.in.lm_cross = &hash6;
1752 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1753 if (NT_STATUS_IS_OK(status)) {
1754 changed = true;
1755 *password = newpass;
1756 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1757 printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1758 ret = false;
1761 oldpass = newpass;
1762 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1764 E_md4hash(oldpass, old_nt_hash);
1765 E_md4hash(newpass, new_nt_hash);
1766 E_deshash(oldpass, old_lm_hash);
1767 E_deshash(newpass, new_lm_hash);
1770 /* Reset the hashes to not broken values */
1771 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1772 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1773 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1774 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1775 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1776 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1778 r.in.user_handle = &user_handle;
1779 r.in.lm_present = 1;
1780 r.in.old_lm_crypted = &hash1;
1781 r.in.new_lm_crypted = &hash2;
1782 r.in.nt_present = 1;
1783 r.in.old_nt_crypted = &hash3;
1784 r.in.new_nt_crypted = &hash4;
1785 r.in.cross1_present = 1;
1786 r.in.nt_cross = &hash5;
1787 r.in.cross2_present = 1;
1788 r.in.lm_cross = &hash6;
1790 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1791 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1792 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1793 } else if (!NT_STATUS_IS_OK(status)) {
1794 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1795 ret = false;
1796 } else {
1797 changed = true;
1798 *password = newpass;
1801 r.in.user_handle = &user_handle;
1802 r.in.lm_present = 1;
1803 r.in.old_lm_crypted = &hash1;
1804 r.in.new_lm_crypted = &hash2;
1805 r.in.nt_present = 1;
1806 r.in.old_nt_crypted = &hash3;
1807 r.in.new_nt_crypted = &hash4;
1808 r.in.cross1_present = 1;
1809 r.in.nt_cross = &hash5;
1810 r.in.cross2_present = 1;
1811 r.in.lm_cross = &hash6;
1813 if (changed) {
1814 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1815 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1816 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1817 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1818 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1819 ret = false;
1824 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1825 ret = false;
1828 return ret;
1832 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1833 const char *acct_name,
1834 struct policy_handle *handle, char **password)
1836 NTSTATUS status;
1837 struct samr_OemChangePasswordUser2 r;
1838 bool ret = true;
1839 struct samr_Password lm_verifier;
1840 struct samr_CryptPassword lm_pass;
1841 struct lsa_AsciiString server, account, account_bad;
1842 char *oldpass;
1843 char *newpass;
1844 uint8_t old_lm_hash[16], new_lm_hash[16];
1846 struct samr_GetDomPwInfo dom_pw_info;
1847 struct samr_PwInfo info;
1848 int policy_min_pw_len = 0;
1850 struct lsa_String domain_name;
1852 domain_name.string = "";
1853 dom_pw_info.in.domain_name = &domain_name;
1854 dom_pw_info.out.info = &info;
1856 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1858 torture_assert(tctx, *password != NULL,
1859 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1861 oldpass = *password;
1863 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1864 if (NT_STATUS_IS_OK(status)) {
1865 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1868 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1870 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1871 account.string = acct_name;
1873 E_deshash(oldpass, old_lm_hash);
1874 E_deshash(newpass, new_lm_hash);
1876 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1877 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1878 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1880 r.in.server = &server;
1881 r.in.account = &account;
1882 r.in.password = &lm_pass;
1883 r.in.hash = &lm_verifier;
1885 /* Break the verification */
1886 lm_verifier.hash[0]++;
1888 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1890 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1891 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1892 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1893 nt_errstr(status));
1894 ret = false;
1897 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1898 /* Break the old password */
1899 old_lm_hash[0]++;
1900 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1901 /* unbreak it for the next operation */
1902 old_lm_hash[0]--;
1903 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1905 r.in.server = &server;
1906 r.in.account = &account;
1907 r.in.password = &lm_pass;
1908 r.in.hash = &lm_verifier;
1910 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1912 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1913 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1914 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1915 nt_errstr(status));
1916 ret = false;
1919 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1920 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1922 r.in.server = &server;
1923 r.in.account = &account;
1924 r.in.password = &lm_pass;
1925 r.in.hash = NULL;
1927 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1929 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1930 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1931 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1932 nt_errstr(status));
1933 ret = false;
1936 /* This shouldn't be a valid name */
1937 account_bad.string = TEST_ACCOUNT_NAME "XX";
1938 r.in.account = &account_bad;
1940 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1942 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1943 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1944 nt_errstr(status));
1945 ret = false;
1948 /* This shouldn't be a valid name */
1949 account_bad.string = TEST_ACCOUNT_NAME "XX";
1950 r.in.account = &account_bad;
1951 r.in.password = &lm_pass;
1952 r.in.hash = &lm_verifier;
1954 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1956 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1957 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1958 nt_errstr(status));
1959 ret = false;
1962 /* This shouldn't be a valid name */
1963 account_bad.string = TEST_ACCOUNT_NAME "XX";
1964 r.in.account = &account_bad;
1965 r.in.password = NULL;
1966 r.in.hash = &lm_verifier;
1968 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1970 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1971 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
1972 nt_errstr(status));
1973 ret = false;
1976 E_deshash(oldpass, old_lm_hash);
1977 E_deshash(newpass, new_lm_hash);
1979 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1980 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1981 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1983 r.in.server = &server;
1984 r.in.account = &account;
1985 r.in.password = &lm_pass;
1986 r.in.hash = &lm_verifier;
1988 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1989 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1990 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1991 } else if (!NT_STATUS_IS_OK(status)) {
1992 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
1993 ret = false;
1994 } else {
1995 *password = newpass;
1998 return ret;
2002 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2003 const char *acct_name,
2004 char **password,
2005 char *newpass, bool allow_password_restriction)
2007 NTSTATUS status;
2008 struct samr_ChangePasswordUser2 r;
2009 bool ret = true;
2010 struct lsa_String server, account;
2011 struct samr_CryptPassword nt_pass, lm_pass;
2012 struct samr_Password nt_verifier, lm_verifier;
2013 char *oldpass;
2014 uint8_t old_nt_hash[16], new_nt_hash[16];
2015 uint8_t old_lm_hash[16], new_lm_hash[16];
2017 struct samr_GetDomPwInfo dom_pw_info;
2018 struct samr_PwInfo info;
2020 struct lsa_String domain_name;
2022 domain_name.string = "";
2023 dom_pw_info.in.domain_name = &domain_name;
2024 dom_pw_info.out.info = &info;
2026 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2028 torture_assert(tctx, *password != NULL,
2029 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2030 oldpass = *password;
2032 if (!newpass) {
2033 int policy_min_pw_len = 0;
2034 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
2035 if (NT_STATUS_IS_OK(status)) {
2036 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2039 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2042 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2043 init_lsa_String(&account, acct_name);
2045 E_md4hash(oldpass, old_nt_hash);
2046 E_md4hash(newpass, new_nt_hash);
2048 E_deshash(oldpass, old_lm_hash);
2049 E_deshash(newpass, new_lm_hash);
2051 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2052 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2053 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2055 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2056 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2057 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2059 r.in.server = &server;
2060 r.in.account = &account;
2061 r.in.nt_password = &nt_pass;
2062 r.in.nt_verifier = &nt_verifier;
2063 r.in.lm_change = 1;
2064 r.in.lm_password = &lm_pass;
2065 r.in.lm_verifier = &lm_verifier;
2067 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
2068 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2069 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2070 } else if (!NT_STATUS_IS_OK(status)) {
2071 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2072 ret = false;
2073 } else {
2074 *password = newpass;
2077 return ret;
2081 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2082 const char *account_string,
2083 int policy_min_pw_len,
2084 char **password,
2085 const char *newpass,
2086 NTTIME last_password_change,
2087 bool handle_reject_reason)
2089 NTSTATUS status;
2090 struct samr_ChangePasswordUser3 r;
2091 bool ret = true;
2092 struct lsa_String server, account, account_bad;
2093 struct samr_CryptPassword nt_pass, lm_pass;
2094 struct samr_Password nt_verifier, lm_verifier;
2095 char *oldpass;
2096 uint8_t old_nt_hash[16], new_nt_hash[16];
2097 uint8_t old_lm_hash[16], new_lm_hash[16];
2098 NTTIME t;
2099 struct samr_DomInfo1 *dominfo = NULL;
2100 struct samr_ChangeReject *reject = NULL;
2102 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2104 if (newpass == NULL) {
2105 do {
2106 if (policy_min_pw_len == 0) {
2107 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2108 } else {
2109 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2111 } while (check_password_quality(newpass) == false);
2112 } else {
2113 torture_comment(tctx, "Using password '%s'\n", newpass);
2116 torture_assert(tctx, *password != NULL,
2117 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2119 oldpass = *password;
2120 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2121 init_lsa_String(&account, account_string);
2123 E_md4hash(oldpass, old_nt_hash);
2124 E_md4hash(newpass, new_nt_hash);
2126 E_deshash(oldpass, old_lm_hash);
2127 E_deshash(newpass, new_lm_hash);
2129 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2130 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2131 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2133 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2134 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2135 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2137 /* Break the verification */
2138 nt_verifier.hash[0]++;
2140 r.in.server = &server;
2141 r.in.account = &account;
2142 r.in.nt_password = &nt_pass;
2143 r.in.nt_verifier = &nt_verifier;
2144 r.in.lm_change = 1;
2145 r.in.lm_password = &lm_pass;
2146 r.in.lm_verifier = &lm_verifier;
2147 r.in.password3 = NULL;
2148 r.out.dominfo = &dominfo;
2149 r.out.reject = &reject;
2151 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2152 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2153 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2154 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2155 nt_errstr(status));
2156 ret = false;
2159 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2160 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2161 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2163 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2164 /* Break the NT hash */
2165 old_nt_hash[0]++;
2166 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2167 /* Unbreak it again */
2168 old_nt_hash[0]--;
2169 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2171 r.in.server = &server;
2172 r.in.account = &account;
2173 r.in.nt_password = &nt_pass;
2174 r.in.nt_verifier = &nt_verifier;
2175 r.in.lm_change = 1;
2176 r.in.lm_password = &lm_pass;
2177 r.in.lm_verifier = &lm_verifier;
2178 r.in.password3 = NULL;
2179 r.out.dominfo = &dominfo;
2180 r.out.reject = &reject;
2182 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2183 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2184 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2185 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2186 nt_errstr(status));
2187 ret = false;
2190 /* This shouldn't be a valid name */
2191 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2193 r.in.account = &account_bad;
2194 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2195 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2196 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2197 nt_errstr(status));
2198 ret = false;
2201 E_md4hash(oldpass, old_nt_hash);
2202 E_md4hash(newpass, new_nt_hash);
2204 E_deshash(oldpass, old_lm_hash);
2205 E_deshash(newpass, new_lm_hash);
2207 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2208 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2209 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2211 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2212 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2213 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2215 r.in.server = &server;
2216 r.in.account = &account;
2217 r.in.nt_password = &nt_pass;
2218 r.in.nt_verifier = &nt_verifier;
2219 r.in.lm_change = 1;
2220 r.in.lm_password = &lm_pass;
2221 r.in.lm_verifier = &lm_verifier;
2222 r.in.password3 = NULL;
2223 r.out.dominfo = &dominfo;
2224 r.out.reject = &reject;
2226 unix_to_nt_time(&t, time(NULL));
2228 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2230 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2231 && dominfo
2232 && reject
2233 && handle_reject_reason
2234 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2235 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2237 if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
2238 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2239 SAMR_REJECT_OTHER, reject->reason);
2240 return false;
2244 /* We tested the order of precendence which is as follows:
2246 * pwd min_age
2247 * pwd length
2248 * pwd complexity
2249 * pwd history
2251 Guenther */
2253 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2254 (last_password_change + dominfo->min_password_age > t)) {
2256 if (reject->reason != SAMR_REJECT_OTHER) {
2257 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2258 SAMR_REJECT_OTHER, reject->reason);
2259 return false;
2262 } else if ((dominfo->min_password_length > 0) &&
2263 (strlen(newpass) < dominfo->min_password_length)) {
2265 if (reject->reason != SAMR_REJECT_TOO_SHORT) {
2266 printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
2267 SAMR_REJECT_TOO_SHORT, reject->reason);
2268 return false;
2271 } else if ((dominfo->password_history_length > 0) &&
2272 strequal(oldpass, newpass)) {
2274 if (reject->reason != SAMR_REJECT_IN_HISTORY) {
2275 printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
2276 SAMR_REJECT_IN_HISTORY, reject->reason);
2277 return false;
2279 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2281 if (reject->reason != SAMR_REJECT_COMPLEXITY) {
2282 printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
2283 SAMR_REJECT_COMPLEXITY, reject->reason);
2284 return false;
2289 if (reject->reason == SAMR_REJECT_TOO_SHORT) {
2290 /* retry with adjusted size */
2291 return test_ChangePasswordUser3(p, tctx, account_string,
2292 dominfo->min_password_length,
2293 password, NULL, 0, false);
2297 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2298 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2299 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2300 SAMR_REJECT_OTHER, reject->reason);
2301 return false;
2303 /* Perhaps the server has a 'min password age' set? */
2305 } else {
2306 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2307 *password = talloc_strdup(tctx, newpass);
2310 return ret;
2313 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2314 const char *account_string,
2315 struct policy_handle *handle,
2316 char **password)
2318 NTSTATUS status;
2319 struct samr_ChangePasswordUser3 r;
2320 struct samr_SetUserInfo s;
2321 union samr_UserInfo u;
2322 DATA_BLOB session_key;
2323 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2324 uint8_t confounder[16];
2325 struct MD5Context ctx;
2327 bool ret = true;
2328 struct lsa_String server, account;
2329 struct samr_CryptPassword nt_pass;
2330 struct samr_Password nt_verifier;
2331 DATA_BLOB new_random_pass;
2332 char *newpass;
2333 char *oldpass;
2334 uint8_t old_nt_hash[16], new_nt_hash[16];
2335 NTTIME t;
2336 struct samr_DomInfo1 *dominfo = NULL;
2337 struct samr_ChangeReject *reject = NULL;
2339 new_random_pass = samr_very_rand_pass(tctx, 128);
2341 torture_assert(tctx, *password != NULL,
2342 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2344 oldpass = *password;
2345 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2346 init_lsa_String(&account, account_string);
2348 s.in.user_handle = handle;
2349 s.in.info = &u;
2350 s.in.level = 25;
2352 ZERO_STRUCT(u);
2354 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2356 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2358 status = dcerpc_fetch_session_key(p, &session_key);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 printf("SetUserInfo level %u - no session key - %s\n",
2361 s.in.level, nt_errstr(status));
2362 return false;
2365 generate_random_buffer((uint8_t *)confounder, 16);
2367 MD5Init(&ctx);
2368 MD5Update(&ctx, confounder, 16);
2369 MD5Update(&ctx, session_key.data, session_key.length);
2370 MD5Final(confounded_session_key.data, &ctx);
2372 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2373 memcpy(&u.info25.password.data[516], confounder, 16);
2375 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2377 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 printf("SetUserInfo level %u failed - %s\n",
2380 s.in.level, nt_errstr(status));
2381 ret = false;
2384 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2386 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2388 new_random_pass = samr_very_rand_pass(tctx, 128);
2390 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2392 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2393 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2394 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2396 r.in.server = &server;
2397 r.in.account = &account;
2398 r.in.nt_password = &nt_pass;
2399 r.in.nt_verifier = &nt_verifier;
2400 r.in.lm_change = 0;
2401 r.in.lm_password = NULL;
2402 r.in.lm_verifier = NULL;
2403 r.in.password3 = NULL;
2404 r.out.dominfo = &dominfo;
2405 r.out.reject = &reject;
2407 unix_to_nt_time(&t, time(NULL));
2409 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2411 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2412 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2413 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2414 SAMR_REJECT_OTHER, reject->reason);
2415 return false;
2417 /* Perhaps the server has a 'min password age' set? */
2419 } else if (!NT_STATUS_IS_OK(status)) {
2420 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2421 ret = false;
2424 newpass = samr_rand_pass(tctx, 128);
2426 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2428 E_md4hash(newpass, new_nt_hash);
2430 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2431 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2432 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2434 r.in.server = &server;
2435 r.in.account = &account;
2436 r.in.nt_password = &nt_pass;
2437 r.in.nt_verifier = &nt_verifier;
2438 r.in.lm_change = 0;
2439 r.in.lm_password = NULL;
2440 r.in.lm_verifier = NULL;
2441 r.in.password3 = NULL;
2442 r.out.dominfo = &dominfo;
2443 r.out.reject = &reject;
2445 unix_to_nt_time(&t, time(NULL));
2447 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2449 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2450 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2451 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2452 SAMR_REJECT_OTHER, reject->reason);
2453 return false;
2455 /* Perhaps the server has a 'min password age' set? */
2457 } else {
2458 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2459 *password = talloc_strdup(tctx, newpass);
2462 return ret;
2466 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2467 struct policy_handle *alias_handle)
2469 struct samr_GetMembersInAlias r;
2470 struct lsa_SidArray sids;
2471 NTSTATUS status;
2473 torture_comment(tctx, "Testing GetMembersInAlias\n");
2475 r.in.alias_handle = alias_handle;
2476 r.out.sids = &sids;
2478 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2479 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2481 return true;
2484 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2485 struct policy_handle *alias_handle,
2486 const struct dom_sid *domain_sid)
2488 struct samr_AddAliasMember r;
2489 struct samr_DeleteAliasMember d;
2490 NTSTATUS status;
2491 struct dom_sid *sid;
2493 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2495 torture_comment(tctx, "testing AddAliasMember\n");
2496 r.in.alias_handle = alias_handle;
2497 r.in.sid = sid;
2499 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2500 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2502 d.in.alias_handle = alias_handle;
2503 d.in.sid = sid;
2505 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2506 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2508 return true;
2511 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2512 struct policy_handle *alias_handle)
2514 struct samr_AddMultipleMembersToAlias a;
2515 struct samr_RemoveMultipleMembersFromAlias r;
2516 NTSTATUS status;
2517 struct lsa_SidArray sids;
2519 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2520 a.in.alias_handle = alias_handle;
2521 a.in.sids = &sids;
2523 sids.num_sids = 3;
2524 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2526 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2527 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2528 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2530 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2531 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2534 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2535 r.in.alias_handle = alias_handle;
2536 r.in.sids = &sids;
2538 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2539 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2541 /* strange! removing twice doesn't give any error */
2542 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2543 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2545 /* but removing an alias that isn't there does */
2546 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2548 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2549 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2551 return true;
2554 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2555 struct policy_handle *user_handle)
2557 struct samr_TestPrivateFunctionsUser r;
2558 NTSTATUS status;
2560 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2562 r.in.user_handle = user_handle;
2564 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2565 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2567 return true;
2570 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2571 struct torture_context *tctx,
2572 struct policy_handle *handle,
2573 bool use_info2,
2574 NTTIME *pwdlastset)
2576 NTSTATUS status;
2577 uint16_t levels[] = { /* 3, */ 5, 21 };
2578 int i;
2579 NTTIME pwdlastset3 = 0;
2580 NTTIME pwdlastset5 = 0;
2581 NTTIME pwdlastset21 = 0;
2583 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2584 use_info2 ? "2":"");
2586 for (i=0; i<ARRAY_SIZE(levels); i++) {
2588 struct samr_QueryUserInfo r;
2589 struct samr_QueryUserInfo2 r2;
2590 union samr_UserInfo *info;
2592 if (use_info2) {
2593 r2.in.user_handle = handle;
2594 r2.in.level = levels[i];
2595 r2.out.info = &info;
2596 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2598 } else {
2599 r.in.user_handle = handle;
2600 r.in.level = levels[i];
2601 r.out.info = &info;
2602 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2605 if (!NT_STATUS_IS_OK(status) &&
2606 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2607 printf("QueryUserInfo%s level %u failed - %s\n",
2608 use_info2 ? "2":"", levels[i], nt_errstr(status));
2609 return false;
2612 switch (levels[i]) {
2613 case 3:
2614 pwdlastset3 = info->info3.last_password_change;
2615 break;
2616 case 5:
2617 pwdlastset5 = info->info5.last_password_change;
2618 break;
2619 case 21:
2620 pwdlastset21 = info->info21.last_password_change;
2621 break;
2622 default:
2623 return false;
2626 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2627 "pwdlastset mixup"); */
2628 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2629 "pwdlastset mixup");
2631 *pwdlastset = pwdlastset21;
2633 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2635 return true;
2638 static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *tctx,
2639 struct cli_credentials *machine_credentials,
2640 struct cli_credentials *test_credentials,
2641 struct creds_CredentialState *creds,
2642 NTSTATUS expected_result)
2644 NTSTATUS status;
2645 struct netr_LogonSamLogon r;
2646 struct netr_Authenticator auth, auth2;
2647 union netr_LogonLevel logon;
2648 union netr_Validation validation;
2649 uint8_t authoritative;
2650 struct netr_NetworkInfo ninfo;
2651 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2652 int flags = CLI_CRED_NTLM_AUTH;
2654 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2655 flags |= CLI_CRED_LANMAN_AUTH;
2658 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2659 flags |= CLI_CRED_NTLMv2_AUTH;
2662 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2663 &ninfo.identity_info.account_name.string,
2664 &ninfo.identity_info.domain_name.string);
2666 generate_random_buffer(ninfo.challenge,
2667 sizeof(ninfo.challenge));
2668 chal = data_blob_const(ninfo.challenge,
2669 sizeof(ninfo.challenge));
2671 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(machine_credentials),
2672 cli_credentials_get_domain(machine_credentials));
2674 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2675 &flags,
2676 chal,
2677 names_blob,
2678 &lm_resp, &nt_resp,
2679 NULL, NULL);
2680 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2682 ninfo.lm.data = lm_resp.data;
2683 ninfo.lm.length = lm_resp.length;
2685 ninfo.nt.data = nt_resp.data;
2686 ninfo.nt.length = nt_resp.length;
2688 ninfo.identity_info.parameter_control =
2689 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2690 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2691 ninfo.identity_info.logon_id_low = 0;
2692 ninfo.identity_info.logon_id_high = 0;
2693 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(machine_credentials);
2695 logon.network = &ninfo;
2697 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2698 r.in.computer_name = cli_credentials_get_workstation(machine_credentials);
2699 r.in.credential = &auth;
2700 r.in.return_authenticator = &auth2;
2701 r.in.logon_level = 2;
2702 r.in.logon = &logon;
2703 r.out.validation = &validation;
2704 r.out.authoritative = &authoritative;
2706 d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
2708 ZERO_STRUCT(auth2);
2709 creds_client_authenticator(creds, &auth);
2711 r.in.validation_level = 2;
2713 status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
2714 if (!NT_STATUS_IS_OK(status)) {
2715 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogon failed");
2716 return true;
2717 } else {
2718 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
2721 torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred),
2722 "Credential chaining failed");
2724 return true;
2727 static bool test_SamLogon(struct torture_context *tctx,
2728 struct dcerpc_pipe *p,
2729 struct cli_credentials *machine_credentials,
2730 struct cli_credentials *test_credentials,
2731 NTSTATUS expected_result)
2733 struct creds_CredentialState *creds;
2735 if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
2736 return false;
2739 return test_SamLogon_Creds(p, tctx, machine_credentials, test_credentials,
2740 creds, expected_result);
2743 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2744 struct dcerpc_pipe *p,
2745 struct cli_credentials *machine_creds,
2746 const char *acct_name,
2747 char *password,
2748 NTSTATUS expected_samlogon_result)
2750 bool ret = true;
2751 struct cli_credentials *test_credentials;
2753 test_credentials = cli_credentials_init(tctx);
2755 cli_credentials_set_workstation(test_credentials,
2756 TEST_ACCOUNT_NAME_PWD, CRED_SPECIFIED);
2757 cli_credentials_set_domain(test_credentials,
2758 lp_workgroup(tctx->lp_ctx), CRED_SPECIFIED);
2759 cli_credentials_set_username(test_credentials,
2760 acct_name, CRED_SPECIFIED);
2761 cli_credentials_set_password(test_credentials,
2762 password, CRED_SPECIFIED);
2763 cli_credentials_set_secure_channel_type(test_credentials, SEC_CHAN_BDC);
2765 printf("testing samlogon as %s@%s password: %s\n",
2766 acct_name, TEST_ACCOUNT_NAME_PWD, password);
2768 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
2769 expected_samlogon_result)) {
2770 torture_warning(tctx, "new password did not work\n");
2771 ret = false;
2774 return ret;
2777 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2778 struct dcerpc_pipe *np,
2779 struct torture_context *tctx,
2780 struct policy_handle *handle,
2781 uint16_t level,
2782 uint32_t fields_present,
2783 uint8_t password_expired,
2784 bool *matched_expected_error,
2785 bool use_setinfo2,
2786 const char *acct_name,
2787 char **password,
2788 struct cli_credentials *machine_creds,
2789 bool use_queryinfo2,
2790 NTTIME *pwdlastset,
2791 NTSTATUS expected_samlogon_result)
2793 const char *fields = NULL;
2794 bool ret = true;
2796 switch (level) {
2797 case 21:
2798 case 23:
2799 case 25:
2800 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2801 fields_present);
2802 break;
2803 default:
2804 break;
2807 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2808 "(password_expired: %d) %s\n",
2809 use_setinfo2 ? "2":"", level, password_expired,
2810 fields ? fields : "");
2812 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2813 fields_present,
2814 password,
2815 password_expired,
2816 use_setinfo2,
2817 matched_expected_error)) {
2818 ret = false;
2821 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2822 use_queryinfo2,
2823 pwdlastset)) {
2824 ret = false;
2827 if (*matched_expected_error == true) {
2828 return ret;
2831 if (!test_SamLogon_with_creds(tctx, np,
2832 machine_creds,
2833 acct_name,
2834 *password,
2835 expected_samlogon_result)) {
2836 ret = false;
2839 return ret;
2842 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2843 struct torture_context *tctx,
2844 uint32_t acct_flags,
2845 const char *acct_name,
2846 struct policy_handle *handle,
2847 char **password,
2848 struct cli_credentials *machine_credentials)
2850 int s = 0, q = 0, f = 0, l = 0, z = 0;
2851 bool ret = true;
2852 int delay = 500000;
2853 bool set_levels[] = { false, true };
2854 bool query_levels[] = { false, true };
2855 uint32_t levels[] = { 18, 21, 23, 24, 25, 26 };
2856 uint32_t nonzeros[] = { 1, 24 };
2857 uint32_t fields_present[] = {
2859 SAMR_FIELD_EXPIRED_FLAG,
2860 SAMR_FIELD_LAST_PWD_CHANGE,
2861 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2862 SAMR_FIELD_COMMENT,
2863 SAMR_FIELD_NT_PASSWORD_PRESENT,
2864 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2865 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2866 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2867 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2868 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2869 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2871 NTSTATUS status;
2872 struct dcerpc_pipe *np = NULL;
2874 if (torture_setting_bool(tctx, "samba3", false)) {
2875 delay = 1000000;
2876 printf("Samba3 has second granularity, setting delay to: %d\n",
2877 delay);
2880 status = torture_rpc_connection(tctx, &np, &ndr_table_netlogon);
2881 if (!NT_STATUS_IS_OK(status)) {
2882 return false;
2885 /* set to 1 to enable testing for all possible opcode
2886 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2887 combinations */
2888 #if 0
2889 #define TEST_SET_LEVELS 1
2890 #define TEST_QUERY_LEVELS 1
2891 #endif
2892 for (l=0; l<ARRAY_SIZE(levels); l++) {
2893 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
2894 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2895 #ifdef TEST_SET_LEVELS
2896 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2897 #endif
2898 #ifdef TEST_QUERY_LEVELS
2899 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2900 #endif
2901 NTTIME pwdlastset_old = 0;
2902 NTTIME pwdlastset_new = 0;
2903 bool matched_expected_error = false;
2904 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
2906 torture_comment(tctx, "------------------------------\n"
2907 "Testing pwdLastSet attribute for flags: 0x%08x "
2908 "(s: %d (l: %d), q: %d)\n",
2909 acct_flags, s, levels[l], q);
2911 switch (levels[l]) {
2912 case 21:
2913 case 23:
2914 case 25:
2915 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2916 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
2917 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
2919 break;
2923 /* set #1 */
2925 /* set a password and force password change (pwdlastset 0) by
2926 * setting the password expired flag to a non-0 value */
2928 if (!test_SetPassword_level(p, np, tctx, handle,
2929 levels[l],
2930 fields_present[f],
2931 nonzeros[z],
2932 &matched_expected_error,
2933 set_levels[s],
2934 acct_name,
2935 password,
2936 machine_credentials,
2937 query_levels[q],
2938 &pwdlastset_old,
2939 expected_samlogon_result)) {
2940 ret = false;
2943 if (matched_expected_error == true) {
2944 /* skipping on expected failure */
2945 continue;
2948 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2949 * set without the SAMR_FIELD_EXPIRED_FLAG */
2951 switch (levels[l]) {
2952 case 21:
2953 case 23:
2954 case 25:
2955 if ((pwdlastset_new != 0) &&
2956 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
2957 torture_comment(tctx, "not considering a non-0 "
2958 "pwdLastSet as a an error as the "
2959 "SAMR_FIELD_EXPIRED_FLAG has not "
2960 "been set\n");
2961 break;
2963 default:
2964 if (pwdlastset_new != 0) {
2965 torture_warning(tctx, "pwdLastSet test failed: "
2966 "expected pwdLastSet 0 but got %lld\n",
2967 pwdlastset_old);
2968 ret = false;
2970 break;
2973 switch (levels[l]) {
2974 case 21:
2975 case 23:
2976 case 25:
2977 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2978 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
2979 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2980 (pwdlastset_old >= pwdlastset_new)) {
2981 torture_warning(tctx, "pwdlastset not increasing\n");
2982 ret = false;
2984 break;
2985 default:
2986 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2987 (pwdlastset_old >= pwdlastset_new)) {
2988 torture_warning(tctx, "pwdlastset not increasing\n");
2989 ret = false;
2991 break;
2994 usleep(delay);
2996 /* set #2 */
2998 /* set a password, pwdlastset needs to get updated (increased
2999 * value), password_expired value used here is 0 */
3001 if (!test_SetPassword_level(p, np, tctx, handle,
3002 levels[l],
3003 fields_present[f],
3005 &matched_expected_error,
3006 set_levels[s],
3007 acct_name,
3008 password,
3009 machine_credentials,
3010 query_levels[q],
3011 &pwdlastset_new,
3012 expected_samlogon_result)) {
3013 ret = false;
3016 /* when a password has been changed, pwdlastset must not be 0 afterwards
3017 * and must be larger then the old value */
3019 switch (levels[l]) {
3020 case 21:
3021 case 23:
3022 case 25:
3024 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3025 * password has been changed, old and new pwdlastset
3026 * need to be the same value */
3028 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3029 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3030 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3032 torture_assert_int_equal(tctx, pwdlastset_old,
3033 pwdlastset_new, "pwdlastset must be equal");
3034 break;
3036 default:
3037 if (pwdlastset_old >= pwdlastset_new) {
3038 torture_warning(tctx, "pwdLastSet test failed: "
3039 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3040 pwdlastset_old, pwdlastset_new);
3041 ret = false;
3043 if (pwdlastset_new == 0) {
3044 torture_warning(tctx, "pwdLastSet test failed: "
3045 "expected non-0 pwdlastset, got: %lld\n",
3046 pwdlastset_new);
3047 ret = false;
3051 switch (levels[l]) {
3052 case 21:
3053 case 23:
3054 case 25:
3055 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3056 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3057 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3058 (pwdlastset_old >= pwdlastset_new)) {
3059 torture_warning(tctx, "pwdlastset not increasing\n");
3060 ret = false;
3062 break;
3063 default:
3064 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3065 (pwdlastset_old >= pwdlastset_new)) {
3066 torture_warning(tctx, "pwdlastset not increasing\n");
3067 ret = false;
3069 break;
3072 pwdlastset_old = pwdlastset_new;
3074 usleep(delay);
3076 /* set #2b */
3078 /* set a password, pwdlastset needs to get updated (increased
3079 * value), password_expired value used here is 0 */
3081 if (!test_SetPassword_level(p, np, tctx, handle,
3082 levels[l],
3083 fields_present[f],
3085 &matched_expected_error,
3086 set_levels[s],
3087 acct_name,
3088 password,
3089 machine_credentials,
3090 query_levels[q],
3091 &pwdlastset_new,
3092 expected_samlogon_result)) {
3093 ret = false;
3096 /* when a password has been changed, pwdlastset must not be 0 afterwards
3097 * and must be larger then the old value */
3099 switch (levels[l]) {
3100 case 21:
3101 case 23:
3102 case 25:
3104 /* if no password has been changed, old and new pwdlastset
3105 * need to be the same value */
3107 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3108 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3110 torture_assert_int_equal(tctx, pwdlastset_old,
3111 pwdlastset_new, "pwdlastset must be equal");
3112 break;
3114 default:
3115 if (pwdlastset_old >= pwdlastset_new) {
3116 torture_warning(tctx, "pwdLastSet test failed: "
3117 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3118 pwdlastset_old, pwdlastset_new);
3119 ret = false;
3121 if (pwdlastset_new == 0) {
3122 torture_warning(tctx, "pwdLastSet test failed: "
3123 "expected non-0 pwdlastset, got: %lld\n",
3124 pwdlastset_new);
3125 ret = false;
3129 /* set #3 */
3131 /* set a password and force password change (pwdlastset 0) by
3132 * setting the password expired flag to a non-0 value */
3134 if (!test_SetPassword_level(p, np, tctx, handle,
3135 levels[l],
3136 fields_present[f],
3137 nonzeros[z],
3138 &matched_expected_error,
3139 set_levels[s],
3140 acct_name,
3141 password,
3142 machine_credentials,
3143 query_levels[q],
3144 &pwdlastset_new,
3145 expected_samlogon_result)) {
3146 ret = false;
3149 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3150 * set without the SAMR_FIELD_EXPIRED_FLAG */
3152 switch (levels[l]) {
3153 case 21:
3154 case 23:
3155 case 25:
3156 if ((pwdlastset_new != 0) &&
3157 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3158 torture_comment(tctx, "not considering a non-0 "
3159 "pwdLastSet as a an error as the "
3160 "SAMR_FIELD_EXPIRED_FLAG has not "
3161 "been set\n");
3162 break;
3165 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3166 * password has been changed, old and new pwdlastset
3167 * need to be the same value */
3169 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3170 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3171 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3173 torture_assert_int_equal(tctx, pwdlastset_old,
3174 pwdlastset_new, "pwdlastset must be equal");
3175 break;
3177 default:
3179 if (pwdlastset_old == pwdlastset_new) {
3180 torture_warning(tctx, "pwdLastSet test failed: "
3181 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3182 pwdlastset_old, pwdlastset_new);
3183 ret = false;
3186 if (pwdlastset_new != 0) {
3187 torture_warning(tctx, "pwdLastSet test failed: "
3188 "expected pwdLastSet 0, got %lld\n",
3189 pwdlastset_old);
3190 ret = false;
3192 break;
3195 switch (levels[l]) {
3196 case 21:
3197 case 23:
3198 case 25:
3199 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3200 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3201 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3202 (pwdlastset_old >= pwdlastset_new)) {
3203 torture_warning(tctx, "pwdlastset not increasing\n");
3204 ret = false;
3206 break;
3207 default:
3208 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3209 (pwdlastset_old >= pwdlastset_new)) {
3210 torture_warning(tctx, "pwdlastset not increasing\n");
3211 ret = false;
3213 break;
3216 /* if the level we are testing does not have a fields_present
3217 * field, skip all fields present tests by setting f to to
3218 * arraysize */
3219 switch (levels[l]) {
3220 case 18:
3221 case 24:
3222 case 26:
3223 f = ARRAY_SIZE(fields_present);
3224 break;
3227 #ifdef TEST_QUERY_LEVELS
3229 #endif
3230 #ifdef TEST_SET_LEVELS
3232 #endif
3233 } /* fields present */
3234 } /* nonzeros */
3235 } /* levels */
3237 #undef TEST_SET_LEVELS
3238 #undef TEST_QUERY_LEVELS
3240 return ret;
3243 static bool test_user_ops(struct dcerpc_pipe *p,
3244 struct torture_context *tctx,
3245 struct policy_handle *user_handle,
3246 struct policy_handle *domain_handle,
3247 uint32_t base_acct_flags,
3248 const char *base_acct_name, enum torture_samr_choice which_ops,
3249 struct cli_credentials *machine_credentials)
3251 char *password = NULL;
3252 struct samr_QueryUserInfo q;
3253 union samr_UserInfo *info;
3254 NTSTATUS status;
3256 bool ret = true;
3257 int i;
3258 uint32_t rid;
3259 const uint32_t password_fields[] = {
3260 SAMR_FIELD_NT_PASSWORD_PRESENT,
3261 SAMR_FIELD_LM_PASSWORD_PRESENT,
3262 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3266 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3267 if (!NT_STATUS_IS_OK(status)) {
3268 ret = false;
3271 switch (which_ops) {
3272 case TORTURE_SAMR_USER_ATTRIBUTES:
3273 if (!test_QuerySecurity(p, tctx, user_handle)) {
3274 ret = false;
3277 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3278 ret = false;
3281 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3282 ret = false;
3285 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3286 base_acct_name)) {
3287 ret = false;
3290 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3291 ret = false;
3294 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3295 ret = false;
3298 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3299 ret = false;
3301 break;
3302 case TORTURE_SAMR_PASSWORDS:
3303 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3304 char simple_pass[9];
3305 char *v = generate_random_str(tctx, 1);
3307 ZERO_STRUCT(simple_pass);
3308 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3310 printf("Testing machine account password policy rules\n");
3312 /* Workstation trust accounts don't seem to need to honour password quality policy */
3313 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3314 ret = false;
3317 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3318 ret = false;
3321 /* reset again, to allow another 'user' password change */
3322 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3323 ret = false;
3326 /* Try a 'short' password */
3327 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3328 ret = false;
3331 /* Try a compleatly random password */
3332 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3333 ret = false;
3337 for (i = 0; password_fields[i]; i++) {
3338 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3339 ret = false;
3342 /* check it was set right */
3343 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3344 ret = false;
3348 for (i = 0; password_fields[i]; i++) {
3349 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3350 ret = false;
3353 /* check it was set right */
3354 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3355 ret = false;
3359 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
3360 ret = false;
3363 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
3364 ret = false;
3367 if (torture_setting_bool(tctx, "samba4", false)) {
3368 printf("skipping Set Password level 18 and 21 against Samba4\n");
3369 } else {
3371 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
3372 ret = false;
3375 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3376 ret = false;
3379 for (i = 0; password_fields[i]; i++) {
3381 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
3382 /* we need to skip as that would break
3383 * the ChangePasswordUser3 verify */
3384 continue;
3387 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
3388 ret = false;
3391 /* check it was set right */
3392 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3393 ret = false;
3398 q.in.user_handle = user_handle;
3399 q.in.level = 5;
3400 q.out.info = &info;
3402 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3403 if (!NT_STATUS_IS_OK(status)) {
3404 printf("QueryUserInfo level %u failed - %s\n",
3405 q.in.level, nt_errstr(status));
3406 ret = false;
3407 } else {
3408 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
3409 if ((info->info5.acct_flags) != expected_flags) {
3410 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3411 info->info5.acct_flags,
3412 expected_flags);
3413 /* FIXME: GD */
3414 if (!torture_setting_bool(tctx, "samba3", false)) {
3415 ret = false;
3418 if (info->info5.rid != rid) {
3419 printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3420 info->info5.rid, rid);
3425 break;
3427 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
3429 /* test last password change timestamp behaviour */
3430 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
3431 base_acct_name,
3432 user_handle, &password,
3433 machine_credentials)) {
3434 ret = false;
3437 if (ret == true) {
3438 torture_comment(tctx, "pwdLastSet test succeeded\n");
3439 } else {
3440 torture_warning(tctx, "pwdLastSet test failed\n");
3443 break;
3445 case TORTURE_SAMR_OTHER:
3446 /* We just need the account to exist */
3447 break;
3449 return ret;
3452 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
3453 struct policy_handle *alias_handle,
3454 const struct dom_sid *domain_sid)
3456 bool ret = true;
3458 if (!test_QuerySecurity(p, tctx, alias_handle)) {
3459 ret = false;
3462 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
3463 ret = false;
3466 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
3467 ret = false;
3470 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
3471 ret = false;
3474 if (torture_setting_bool(tctx, "samba4", false)) {
3475 printf("skipping MultipleMembers Alias tests against Samba4\n");
3476 return ret;
3479 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
3480 ret = false;
3483 return ret;
3487 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3488 struct policy_handle *user_handle)
3490 struct samr_DeleteUser d;
3491 NTSTATUS status;
3492 torture_comment(tctx, "Testing DeleteUser\n");
3494 d.in.user_handle = user_handle;
3495 d.out.user_handle = user_handle;
3497 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3498 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
3500 return true;
3503 bool test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3504 struct policy_handle *handle, const char *name)
3506 NTSTATUS status;
3507 struct samr_DeleteUser d;
3508 struct policy_handle user_handle;
3509 uint32_t rid;
3511 status = test_LookupName(p, mem_ctx, handle, name, &rid);
3512 if (!NT_STATUS_IS_OK(status)) {
3513 goto failed;
3516 status = test_OpenUser_byname(p, mem_ctx, handle, name, &user_handle);
3517 if (!NT_STATUS_IS_OK(status)) {
3518 goto failed;
3521 d.in.user_handle = &user_handle;
3522 d.out.user_handle = &user_handle;
3523 status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
3524 if (!NT_STATUS_IS_OK(status)) {
3525 goto failed;
3528 return true;
3530 failed:
3531 printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
3532 return false;
3536 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3537 struct policy_handle *handle, const char *name)
3539 NTSTATUS status;
3540 struct samr_OpenGroup r;
3541 struct samr_DeleteDomainGroup d;
3542 struct policy_handle group_handle;
3543 uint32_t rid;
3545 status = test_LookupName(p, mem_ctx, handle, name, &rid);
3546 if (!NT_STATUS_IS_OK(status)) {
3547 goto failed;
3550 r.in.domain_handle = handle;
3551 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3552 r.in.rid = rid;
3553 r.out.group_handle = &group_handle;
3554 status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
3555 if (!NT_STATUS_IS_OK(status)) {
3556 goto failed;
3559 d.in.group_handle = &group_handle;
3560 d.out.group_handle = &group_handle;
3561 status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
3562 if (!NT_STATUS_IS_OK(status)) {
3563 goto failed;
3566 return true;
3568 failed:
3569 printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
3570 return false;
3574 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3575 struct policy_handle *domain_handle, const char *name)
3577 NTSTATUS status;
3578 struct samr_OpenAlias r;
3579 struct samr_DeleteDomAlias d;
3580 struct policy_handle alias_handle;
3581 uint32_t rid;
3583 printf("testing DeleteAlias_byname\n");
3585 status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
3586 if (!NT_STATUS_IS_OK(status)) {
3587 goto failed;
3590 r.in.domain_handle = domain_handle;
3591 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3592 r.in.rid = rid;
3593 r.out.alias_handle = &alias_handle;
3594 status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
3595 if (!NT_STATUS_IS_OK(status)) {
3596 goto failed;
3599 d.in.alias_handle = &alias_handle;
3600 d.out.alias_handle = &alias_handle;
3601 status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 goto failed;
3606 return true;
3608 failed:
3609 printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
3610 return false;
3613 static bool test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3614 struct policy_handle *alias_handle)
3616 struct samr_DeleteDomAlias d;
3617 NTSTATUS status;
3618 bool ret = true;
3619 printf("Testing DeleteAlias\n");
3621 d.in.alias_handle = alias_handle;
3622 d.out.alias_handle = alias_handle;
3624 status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
3625 if (!NT_STATUS_IS_OK(status)) {
3626 printf("DeleteAlias failed - %s\n", nt_errstr(status));
3627 ret = false;
3630 return ret;
3633 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
3634 struct policy_handle *domain_handle,
3635 struct policy_handle *alias_handle,
3636 const struct dom_sid *domain_sid)
3638 NTSTATUS status;
3639 struct samr_CreateDomAlias r;
3640 struct lsa_String name;
3641 uint32_t rid;
3642 bool ret = true;
3644 init_lsa_String(&name, TEST_ALIASNAME);
3645 r.in.domain_handle = domain_handle;
3646 r.in.alias_name = &name;
3647 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3648 r.out.alias_handle = alias_handle;
3649 r.out.rid = &rid;
3651 printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
3653 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
3655 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
3656 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3657 printf("Server correctly refused create of '%s'\n", r.in.alias_name->string);
3658 return true;
3659 } else {
3660 printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
3661 nt_errstr(status));
3662 return false;
3666 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
3667 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
3668 return false;
3670 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
3673 if (!NT_STATUS_IS_OK(status)) {
3674 printf("CreateAlias failed - %s\n", nt_errstr(status));
3675 return false;
3678 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
3679 ret = false;
3682 return ret;
3685 static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3686 const char *acct_name,
3687 struct policy_handle *domain_handle, char **password)
3689 bool ret = true;
3691 if (!*password) {
3692 return false;
3695 if (!test_ChangePasswordUser(p, mem_ctx, acct_name, domain_handle, password)) {
3696 ret = false;
3699 if (!test_ChangePasswordUser2(p, mem_ctx, acct_name, password, 0, true)) {
3700 ret = false;
3703 if (!test_OemChangePasswordUser2(p, mem_ctx, acct_name, domain_handle, password)) {
3704 ret = false;
3707 /* test what happens when setting the old password again */
3708 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, *password, 0, true)) {
3709 ret = false;
3713 char simple_pass[9];
3714 char *v = generate_random_str(mem_ctx, 1);
3716 ZERO_STRUCT(simple_pass);
3717 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3719 /* test what happens when picking a simple password */
3720 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, simple_pass, 0, true)) {
3721 ret = false;
3725 /* set samr_SetDomainInfo level 1 with min_length 5 */
3727 struct samr_QueryDomainInfo r;
3728 union samr_DomainInfo *info = NULL;
3729 struct samr_SetDomainInfo s;
3730 uint16_t len_old, len;
3731 uint32_t pwd_prop_old;
3732 int64_t min_pwd_age_old;
3733 NTSTATUS status;
3735 len = 5;
3737 r.in.domain_handle = domain_handle;
3738 r.in.level = 1;
3739 r.out.info = &info;
3741 printf("testing samr_QueryDomainInfo level 1\n");
3742 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
3743 if (!NT_STATUS_IS_OK(status)) {
3744 return false;
3747 s.in.domain_handle = domain_handle;
3748 s.in.level = 1;
3749 s.in.info = info;
3751 /* remember the old min length, so we can reset it */
3752 len_old = s.in.info->info1.min_password_length;
3753 s.in.info->info1.min_password_length = len;
3754 pwd_prop_old = s.in.info->info1.password_properties;
3755 /* turn off password complexity checks for this test */
3756 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
3758 min_pwd_age_old = s.in.info->info1.min_password_age;
3759 s.in.info->info1.min_password_age = 0;
3761 printf("testing samr_SetDomainInfo level 1\n");
3762 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
3763 if (!NT_STATUS_IS_OK(status)) {
3764 return false;
3767 printf("calling test_ChangePasswordUser3 with too short password\n");
3769 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, len - 1, password, NULL, 0, true)) {
3770 ret = false;
3773 s.in.info->info1.min_password_length = len_old;
3774 s.in.info->info1.password_properties = pwd_prop_old;
3775 s.in.info->info1.min_password_age = min_pwd_age_old;
3777 printf("testing samr_SetDomainInfo level 1\n");
3778 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
3779 if (!NT_STATUS_IS_OK(status)) {
3780 return false;
3786 NTSTATUS status;
3787 struct samr_OpenUser r;
3788 struct samr_QueryUserInfo q;
3789 union samr_UserInfo *info;
3790 struct samr_LookupNames n;
3791 struct policy_handle user_handle;
3792 struct samr_Ids rids, types;
3794 n.in.domain_handle = domain_handle;
3795 n.in.num_names = 1;
3796 n.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
3797 n.in.names[0].string = acct_name;
3798 n.out.rids = &rids;
3799 n.out.types = &types;
3801 status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
3802 if (!NT_STATUS_IS_OK(status)) {
3803 printf("LookupNames failed - %s\n", nt_errstr(status));
3804 return false;
3807 r.in.domain_handle = domain_handle;
3808 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3809 r.in.rid = n.out.rids->ids[0];
3810 r.out.user_handle = &user_handle;
3812 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
3813 if (!NT_STATUS_IS_OK(status)) {
3814 printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
3815 return false;
3818 q.in.user_handle = &user_handle;
3819 q.in.level = 5;
3820 q.out.info = &info;
3822 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
3823 if (!NT_STATUS_IS_OK(status)) {
3824 printf("QueryUserInfo failed - %s\n", nt_errstr(status));
3825 return false;
3828 printf("calling test_ChangePasswordUser3 with too early password change\n");
3830 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL,
3831 info->info5.last_password_change, true)) {
3832 ret = false;
3836 /* we change passwords twice - this has the effect of verifying
3837 they were changed correctly for the final call */
3838 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
3839 ret = false;
3842 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
3843 ret = false;
3846 return ret;
3849 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3850 struct policy_handle *domain_handle,
3851 struct policy_handle *user_handle_out,
3852 struct dom_sid *domain_sid,
3853 enum torture_samr_choice which_ops,
3854 struct cli_credentials *machine_credentials)
3857 TALLOC_CTX *user_ctx;
3859 NTSTATUS status;
3860 struct samr_CreateUser r;
3861 struct samr_QueryUserInfo q;
3862 union samr_UserInfo *info;
3863 struct samr_DeleteUser d;
3864 uint32_t rid;
3866 /* This call creates a 'normal' account - check that it really does */
3867 const uint32_t acct_flags = ACB_NORMAL;
3868 struct lsa_String name;
3869 bool ret = true;
3871 struct policy_handle user_handle;
3872 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
3873 init_lsa_String(&name, TEST_ACCOUNT_NAME);
3875 r.in.domain_handle = domain_handle;
3876 r.in.account_name = &name;
3877 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3878 r.out.user_handle = &user_handle;
3879 r.out.rid = &rid;
3881 printf("Testing CreateUser(%s)\n", r.in.account_name->string);
3883 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
3885 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
3886 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3887 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
3888 return true;
3889 } else {
3890 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
3891 nt_errstr(status));
3892 return false;
3896 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
3897 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
3898 talloc_free(user_ctx);
3899 return false;
3901 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
3903 if (!NT_STATUS_IS_OK(status)) {
3904 talloc_free(user_ctx);
3905 printf("CreateUser failed - %s\n", nt_errstr(status));
3906 return false;
3907 } else {
3908 q.in.user_handle = &user_handle;
3909 q.in.level = 16;
3910 q.out.info = &info;
3912 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
3913 if (!NT_STATUS_IS_OK(status)) {
3914 printf("QueryUserInfo level %u failed - %s\n",
3915 q.in.level, nt_errstr(status));
3916 ret = false;
3917 } else {
3918 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
3919 printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3920 info->info16.acct_flags,
3921 acct_flags);
3922 ret = false;
3926 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
3927 acct_flags, name.string, which_ops,
3928 machine_credentials)) {
3929 ret = false;
3932 if (user_handle_out) {
3933 *user_handle_out = user_handle;
3934 } else {
3935 printf("Testing DeleteUser (createuser test)\n");
3937 d.in.user_handle = &user_handle;
3938 d.out.user_handle = &user_handle;
3940 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
3941 if (!NT_STATUS_IS_OK(status)) {
3942 printf("DeleteUser failed - %s\n", nt_errstr(status));
3943 ret = false;
3949 talloc_free(user_ctx);
3951 return ret;
3955 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
3956 struct policy_handle *domain_handle,
3957 struct dom_sid *domain_sid,
3958 enum torture_samr_choice which_ops,
3959 struct cli_credentials *machine_credentials)
3961 NTSTATUS status;
3962 struct samr_CreateUser2 r;
3963 struct samr_QueryUserInfo q;
3964 union samr_UserInfo *info;
3965 struct samr_DeleteUser d;
3966 struct policy_handle user_handle;
3967 uint32_t rid;
3968 struct lsa_String name;
3969 bool ret = true;
3970 int i;
3972 struct {
3973 uint32_t acct_flags;
3974 const char *account_name;
3975 NTSTATUS nt_status;
3976 } account_types[] = {
3977 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
3978 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
3979 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
3980 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
3981 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
3982 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
3983 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
3984 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
3985 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
3986 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
3987 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
3988 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
3989 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
3990 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
3991 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
3994 for (i = 0; account_types[i].account_name; i++) {
3995 TALLOC_CTX *user_ctx;
3996 uint32_t acct_flags = account_types[i].acct_flags;
3997 uint32_t access_granted;
3998 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
3999 init_lsa_String(&name, account_types[i].account_name);
4001 r.in.domain_handle = domain_handle;
4002 r.in.account_name = &name;
4003 r.in.acct_flags = acct_flags;
4004 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4005 r.out.user_handle = &user_handle;
4006 r.out.access_granted = &access_granted;
4007 r.out.rid = &rid;
4009 printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
4011 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4013 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4014 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4015 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
4016 continue;
4017 } else {
4018 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4019 nt_errstr(status));
4020 ret = false;
4021 continue;
4025 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4026 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4027 talloc_free(user_ctx);
4028 ret = false;
4029 continue;
4031 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4034 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
4035 printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4036 nt_errstr(status), nt_errstr(account_types[i].nt_status));
4037 ret = false;
4040 if (NT_STATUS_IS_OK(status)) {
4041 q.in.user_handle = &user_handle;
4042 q.in.level = 5;
4043 q.out.info = &info;
4045 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4046 if (!NT_STATUS_IS_OK(status)) {
4047 printf("QueryUserInfo level %u failed - %s\n",
4048 q.in.level, nt_errstr(status));
4049 ret = false;
4050 } else {
4051 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4052 if (acct_flags == ACB_NORMAL) {
4053 expected_flags |= ACB_PW_EXPIRED;
4055 if ((info->info5.acct_flags) != expected_flags) {
4056 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4057 info->info5.acct_flags,
4058 expected_flags);
4059 ret = false;
4061 switch (acct_flags) {
4062 case ACB_SVRTRUST:
4063 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
4064 printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4065 DOMAIN_RID_DCS, info->info5.primary_gid);
4066 ret = false;
4068 break;
4069 case ACB_WSTRUST:
4070 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
4071 printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4072 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
4073 ret = false;
4075 break;
4076 case ACB_NORMAL:
4077 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
4078 printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4079 DOMAIN_RID_USERS, info->info5.primary_gid);
4080 ret = false;
4082 break;
4086 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4087 acct_flags, name.string, which_ops,
4088 machine_credentials)) {
4089 ret = false;
4092 printf("Testing DeleteUser (createuser2 test)\n");
4094 d.in.user_handle = &user_handle;
4095 d.out.user_handle = &user_handle;
4097 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4098 if (!NT_STATUS_IS_OK(status)) {
4099 printf("DeleteUser failed - %s\n", nt_errstr(status));
4100 ret = false;
4103 talloc_free(user_ctx);
4106 return ret;
4109 static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4110 struct policy_handle *handle)
4112 NTSTATUS status;
4113 struct samr_QueryAliasInfo r;
4114 union samr_AliasInfo *info;
4115 uint16_t levels[] = {1, 2, 3};
4116 int i;
4117 bool ret = true;
4119 for (i=0;i<ARRAY_SIZE(levels);i++) {
4120 printf("Testing QueryAliasInfo level %u\n", levels[i]);
4122 r.in.alias_handle = handle;
4123 r.in.level = levels[i];
4124 r.out.info = &info;
4126 status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
4127 if (!NT_STATUS_IS_OK(status)) {
4128 printf("QueryAliasInfo level %u failed - %s\n",
4129 levels[i], nt_errstr(status));
4130 ret = false;
4134 return ret;
4137 static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4138 struct policy_handle *handle)
4140 NTSTATUS status;
4141 struct samr_QueryGroupInfo r;
4142 union samr_GroupInfo *info;
4143 uint16_t levels[] = {1, 2, 3, 4, 5};
4144 int i;
4145 bool ret = true;
4147 for (i=0;i<ARRAY_SIZE(levels);i++) {
4148 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4150 r.in.group_handle = handle;
4151 r.in.level = levels[i];
4152 r.out.info = &info;
4154 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
4155 if (!NT_STATUS_IS_OK(status)) {
4156 printf("QueryGroupInfo level %u failed - %s\n",
4157 levels[i], nt_errstr(status));
4158 ret = false;
4162 return ret;
4165 static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4166 struct policy_handle *handle)
4168 NTSTATUS status;
4169 struct samr_QueryGroupMember r;
4170 struct samr_RidTypeArray *rids = NULL;
4171 bool ret = true;
4173 printf("Testing QueryGroupMember\n");
4175 r.in.group_handle = handle;
4176 r.out.rids = &rids;
4178 status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r);
4179 if (!NT_STATUS_IS_OK(status)) {
4180 printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
4181 ret = false;
4184 return ret;
4188 static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4189 struct policy_handle *handle)
4191 NTSTATUS status;
4192 struct samr_QueryGroupInfo r;
4193 union samr_GroupInfo *info;
4194 struct samr_SetGroupInfo s;
4195 uint16_t levels[] = {1, 2, 3, 4};
4196 uint16_t set_ok[] = {0, 1, 1, 1};
4197 int i;
4198 bool ret = true;
4200 for (i=0;i<ARRAY_SIZE(levels);i++) {
4201 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4203 r.in.group_handle = handle;
4204 r.in.level = levels[i];
4205 r.out.info = &info;
4207 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
4208 if (!NT_STATUS_IS_OK(status)) {
4209 printf("QueryGroupInfo level %u failed - %s\n",
4210 levels[i], nt_errstr(status));
4211 ret = false;
4214 printf("Testing SetGroupInfo level %u\n", levels[i]);
4216 s.in.group_handle = handle;
4217 s.in.level = levels[i];
4218 s.in.info = *r.out.info;
4220 #if 0
4221 /* disabled this, as it changes the name only from the point of view of samr,
4222 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4223 the name is still reserved, so creating the old name fails, but deleting by the old name
4224 also fails */
4225 if (s.in.level == 2) {
4226 init_lsa_String(&s.in.info->string, "NewName");
4228 #endif
4230 if (s.in.level == 4) {
4231 init_lsa_String(&s.in.info->description, "test description");
4234 status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
4235 if (set_ok[i]) {
4236 if (!NT_STATUS_IS_OK(status)) {
4237 printf("SetGroupInfo level %u failed - %s\n",
4238 r.in.level, nt_errstr(status));
4239 ret = false;
4240 continue;
4242 } else {
4243 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4244 printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4245 r.in.level, nt_errstr(status));
4246 ret = false;
4247 continue;
4252 return ret;
4255 static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4256 struct policy_handle *handle)
4258 NTSTATUS status;
4259 struct samr_QueryUserInfo r;
4260 union samr_UserInfo *info;
4261 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4262 11, 12, 13, 14, 16, 17, 20, 21};
4263 int i;
4264 bool ret = true;
4266 for (i=0;i<ARRAY_SIZE(levels);i++) {
4267 printf("Testing QueryUserInfo level %u\n", levels[i]);
4269 r.in.user_handle = handle;
4270 r.in.level = levels[i];
4271 r.out.info = &info;
4273 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r);
4274 if (!NT_STATUS_IS_OK(status)) {
4275 printf("QueryUserInfo level %u failed - %s\n",
4276 levels[i], nt_errstr(status));
4277 ret = false;
4281 return ret;
4284 static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4285 struct policy_handle *handle)
4287 NTSTATUS status;
4288 struct samr_QueryUserInfo2 r;
4289 union samr_UserInfo *info;
4290 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4291 11, 12, 13, 14, 16, 17, 20, 21};
4292 int i;
4293 bool ret = true;
4295 for (i=0;i<ARRAY_SIZE(levels);i++) {
4296 printf("Testing QueryUserInfo2 level %u\n", levels[i]);
4298 r.in.user_handle = handle;
4299 r.in.level = levels[i];
4300 r.out.info = &info;
4302 status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r);
4303 if (!NT_STATUS_IS_OK(status)) {
4304 printf("QueryUserInfo2 level %u failed - %s\n",
4305 levels[i], nt_errstr(status));
4306 ret = false;
4310 return ret;
4313 static bool test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4314 struct policy_handle *handle, uint32_t rid)
4316 NTSTATUS status;
4317 struct samr_OpenUser r;
4318 struct policy_handle user_handle;
4319 bool ret = true;
4321 printf("Testing OpenUser(%u)\n", rid);
4323 r.in.domain_handle = handle;
4324 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4325 r.in.rid = rid;
4326 r.out.user_handle = &user_handle;
4328 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
4329 if (!NT_STATUS_IS_OK(status)) {
4330 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4331 return false;
4334 if (!test_QuerySecurity(p, mem_ctx, &user_handle)) {
4335 ret = false;
4338 if (!test_QueryUserInfo(p, mem_ctx, &user_handle)) {
4339 ret = false;
4342 if (!test_QueryUserInfo2(p, mem_ctx, &user_handle)) {
4343 ret = false;
4346 if (!test_GetUserPwInfo(p, mem_ctx, &user_handle)) {
4347 ret = false;
4350 if (!test_GetGroupsForUser(p,mem_ctx, &user_handle)) {
4351 ret = false;
4354 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
4355 ret = false;
4358 return ret;
4361 static bool test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4362 struct policy_handle *handle, uint32_t rid)
4364 NTSTATUS status;
4365 struct samr_OpenGroup r;
4366 struct policy_handle group_handle;
4367 bool ret = true;
4369 printf("Testing OpenGroup(%u)\n", rid);
4371 r.in.domain_handle = handle;
4372 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4373 r.in.rid = rid;
4374 r.out.group_handle = &group_handle;
4376 status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
4377 if (!NT_STATUS_IS_OK(status)) {
4378 printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
4379 return false;
4382 if (!test_QuerySecurity(p, mem_ctx, &group_handle)) {
4383 ret = false;
4386 if (!test_QueryGroupInfo(p, mem_ctx, &group_handle)) {
4387 ret = false;
4390 if (!test_QueryGroupMember(p, mem_ctx, &group_handle)) {
4391 ret = false;
4394 if (!test_samr_handle_Close(p, mem_ctx, &group_handle)) {
4395 ret = false;
4398 return ret;
4401 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4402 struct policy_handle *handle, uint32_t rid)
4404 NTSTATUS status;
4405 struct samr_OpenAlias r;
4406 struct policy_handle alias_handle;
4407 bool ret = true;
4409 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
4411 r.in.domain_handle = handle;
4412 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4413 r.in.rid = rid;
4414 r.out.alias_handle = &alias_handle;
4416 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4417 if (!NT_STATUS_IS_OK(status)) {
4418 printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
4419 return false;
4422 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
4423 ret = false;
4426 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
4427 ret = false;
4430 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
4431 ret = false;
4434 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
4435 ret = false;
4438 return ret;
4441 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
4442 struct policy_handle *handle, uint32_t rid,
4443 uint32_t acct_flag_mask)
4445 NTSTATUS status;
4446 struct samr_OpenUser r;
4447 struct samr_QueryUserInfo q;
4448 union samr_UserInfo *info;
4449 struct policy_handle user_handle;
4450 bool ret = true;
4452 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4454 r.in.domain_handle = handle;
4455 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4456 r.in.rid = rid;
4457 r.out.user_handle = &user_handle;
4459 status = dcerpc_samr_OpenUser(p, tctx, &r);
4460 if (!NT_STATUS_IS_OK(status)) {
4461 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4462 return false;
4465 q.in.user_handle = &user_handle;
4466 q.in.level = 16;
4467 q.out.info = &info;
4469 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4470 if (!NT_STATUS_IS_OK(status)) {
4471 printf("QueryUserInfo level 16 failed - %s\n",
4472 nt_errstr(status));
4473 ret = false;
4474 } else {
4475 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
4476 printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4477 acct_flag_mask, info->info16.acct_flags, rid);
4478 ret = false;
4482 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4483 ret = false;
4486 return ret;
4489 static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *tctx,
4490 struct policy_handle *handle)
4492 NTSTATUS status = STATUS_MORE_ENTRIES;
4493 struct samr_EnumDomainUsers r;
4494 uint32_t mask, resume_handle=0;
4495 int i, mask_idx;
4496 bool ret = true;
4497 struct samr_LookupNames n;
4498 struct samr_LookupRids lr ;
4499 struct lsa_Strings names;
4500 struct samr_Ids rids, types;
4501 struct samr_SamArray *sam = NULL;
4502 uint32_t num_entries = 0;
4504 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
4505 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
4506 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
4507 ACB_PWNOEXP, 0};
4509 printf("Testing EnumDomainUsers\n");
4511 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
4512 r.in.domain_handle = handle;
4513 r.in.resume_handle = &resume_handle;
4514 r.in.acct_flags = mask = masks[mask_idx];
4515 r.in.max_size = (uint32_t)-1;
4516 r.out.resume_handle = &resume_handle;
4517 r.out.num_entries = &num_entries;
4518 r.out.sam = &sam;
4520 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
4521 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
4522 !NT_STATUS_IS_OK(status)) {
4523 printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
4524 return false;
4527 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4529 if (sam->count == 0) {
4530 continue;
4533 for (i=0;i<sam->count;i++) {
4534 if (mask) {
4535 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
4536 ret = false;
4538 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
4539 ret = false;
4544 printf("Testing LookupNames\n");
4545 n.in.domain_handle = handle;
4546 n.in.num_names = sam->count;
4547 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
4548 n.out.rids = &rids;
4549 n.out.types = &types;
4550 for (i=0;i<sam->count;i++) {
4551 n.in.names[i].string = sam->entries[i].name.string;
4553 status = dcerpc_samr_LookupNames(p, tctx, &n);
4554 if (!NT_STATUS_IS_OK(status)) {
4555 printf("LookupNames failed - %s\n", nt_errstr(status));
4556 ret = false;
4560 printf("Testing LookupRids\n");
4561 lr.in.domain_handle = handle;
4562 lr.in.num_rids = sam->count;
4563 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
4564 lr.out.names = &names;
4565 lr.out.types = &types;
4566 for (i=0;i<sam->count;i++) {
4567 lr.in.rids[i] = sam->entries[i].idx;
4569 status = dcerpc_samr_LookupRids(p, tctx, &lr);
4570 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
4572 return ret;
4576 try blasting the server with a bunch of sync requests
4578 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
4579 struct policy_handle *handle)
4581 NTSTATUS status;
4582 struct samr_EnumDomainUsers r;
4583 uint32_t resume_handle=0;
4584 int i;
4585 #define ASYNC_COUNT 100
4586 struct rpc_request *req[ASYNC_COUNT];
4588 if (!torture_setting_bool(tctx, "dangerous", false)) {
4589 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
4592 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
4594 r.in.domain_handle = handle;
4595 r.in.resume_handle = &resume_handle;
4596 r.in.acct_flags = 0;
4597 r.in.max_size = (uint32_t)-1;
4598 r.out.resume_handle = &resume_handle;
4600 for (i=0;i<ASYNC_COUNT;i++) {
4601 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
4604 for (i=0;i<ASYNC_COUNT;i++) {
4605 status = dcerpc_ndr_request_recv(req[i]);
4606 if (!NT_STATUS_IS_OK(status)) {
4607 printf("EnumDomainUsers[%d] failed - %s\n",
4608 i, nt_errstr(status));
4609 return false;
4613 torture_comment(tctx, "%d async requests OK\n", i);
4615 return true;
4618 static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4619 struct policy_handle *handle)
4621 NTSTATUS status;
4622 struct samr_EnumDomainGroups r;
4623 uint32_t resume_handle=0;
4624 struct samr_SamArray *sam = NULL;
4625 uint32_t num_entries = 0;
4626 int i;
4627 bool ret = true;
4629 printf("Testing EnumDomainGroups\n");
4631 r.in.domain_handle = handle;
4632 r.in.resume_handle = &resume_handle;
4633 r.in.max_size = (uint32_t)-1;
4634 r.out.resume_handle = &resume_handle;
4635 r.out.num_entries = &num_entries;
4636 r.out.sam = &sam;
4638 status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
4639 if (!NT_STATUS_IS_OK(status)) {
4640 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
4641 return false;
4644 if (!sam) {
4645 return false;
4648 for (i=0;i<sam->count;i++) {
4649 if (!test_OpenGroup(p, mem_ctx, handle, sam->entries[i].idx)) {
4650 ret = false;
4654 return ret;
4657 static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4658 struct policy_handle *handle)
4660 NTSTATUS status;
4661 struct samr_EnumDomainAliases r;
4662 uint32_t resume_handle=0;
4663 struct samr_SamArray *sam = NULL;
4664 uint32_t num_entries = 0;
4665 int i;
4666 bool ret = true;
4668 printf("Testing EnumDomainAliases\n");
4670 r.in.domain_handle = handle;
4671 r.in.resume_handle = &resume_handle;
4672 r.in.max_size = (uint32_t)-1;
4673 r.out.sam = &sam;
4674 r.out.num_entries = &num_entries;
4675 r.out.resume_handle = &resume_handle;
4677 status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
4678 if (!NT_STATUS_IS_OK(status)) {
4679 printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
4680 return false;
4683 if (!sam) {
4684 return false;
4687 for (i=0;i<sam->count;i++) {
4688 if (!test_OpenAlias(p, mem_ctx, handle, sam->entries[i].idx)) {
4689 ret = false;
4693 return ret;
4696 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4697 struct policy_handle *handle)
4699 NTSTATUS status;
4700 struct samr_GetDisplayEnumerationIndex r;
4701 bool ret = true;
4702 uint16_t levels[] = {1, 2, 3, 4, 5};
4703 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
4704 struct lsa_String name;
4705 uint32_t idx = 0;
4706 int i;
4708 for (i=0;i<ARRAY_SIZE(levels);i++) {
4709 printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
4711 init_lsa_String(&name, TEST_ACCOUNT_NAME);
4713 r.in.domain_handle = handle;
4714 r.in.level = levels[i];
4715 r.in.name = &name;
4716 r.out.idx = &idx;
4718 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
4720 if (ok_lvl[i] &&
4721 !NT_STATUS_IS_OK(status) &&
4722 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4723 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
4724 levels[i], nt_errstr(status));
4725 ret = false;
4728 init_lsa_String(&name, "zzzzzzzz");
4730 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
4732 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4733 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
4734 levels[i], nt_errstr(status));
4735 ret = false;
4739 return ret;
4742 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4743 struct policy_handle *handle)
4745 NTSTATUS status;
4746 struct samr_GetDisplayEnumerationIndex2 r;
4747 bool ret = true;
4748 uint16_t levels[] = {1, 2, 3, 4, 5};
4749 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
4750 struct lsa_String name;
4751 uint32_t idx = 0;
4752 int i;
4754 for (i=0;i<ARRAY_SIZE(levels);i++) {
4755 printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
4757 init_lsa_String(&name, TEST_ACCOUNT_NAME);
4759 r.in.domain_handle = handle;
4760 r.in.level = levels[i];
4761 r.in.name = &name;
4762 r.out.idx = &idx;
4764 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
4765 if (ok_lvl[i] &&
4766 !NT_STATUS_IS_OK(status) &&
4767 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4768 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
4769 levels[i], nt_errstr(status));
4770 ret = false;
4773 init_lsa_String(&name, "zzzzzzzz");
4775 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
4776 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4777 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
4778 levels[i], nt_errstr(status));
4779 ret = false;
4783 return ret;
4786 #define STRING_EQUAL_QUERY(s1, s2, user) \
4787 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
4788 /* odd, but valid */ \
4789 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
4790 printf("%s mismatch for %s: %s != %s (%s)\n", \
4791 #s1, user.string, s1.string, s2.string, __location__); \
4792 ret = false; \
4794 #define INT_EQUAL_QUERY(s1, s2, user) \
4795 if (s1 != s2) { \
4796 printf("%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
4797 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
4798 ret = false; \
4801 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4802 struct samr_QueryDisplayInfo *querydisplayinfo,
4803 bool *seen_testuser)
4805 struct samr_OpenUser r;
4806 struct samr_QueryUserInfo q;
4807 union samr_UserInfo *info;
4808 struct policy_handle user_handle;
4809 int i, ret = true;
4810 NTSTATUS status;
4811 r.in.domain_handle = querydisplayinfo->in.domain_handle;
4812 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4813 for (i = 0; ; i++) {
4814 switch (querydisplayinfo->in.level) {
4815 case 1:
4816 if (i >= querydisplayinfo->out.info->info1.count) {
4817 return ret;
4819 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
4820 break;
4821 case 2:
4822 if (i >= querydisplayinfo->out.info->info2.count) {
4823 return ret;
4825 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
4826 break;
4827 case 3:
4828 /* Groups */
4829 case 4:
4830 case 5:
4831 /* Not interested in validating just the account name */
4832 return true;
4835 r.out.user_handle = &user_handle;
4837 switch (querydisplayinfo->in.level) {
4838 case 1:
4839 case 2:
4840 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
4841 if (!NT_STATUS_IS_OK(status)) {
4842 printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
4843 return false;
4847 q.in.user_handle = &user_handle;
4848 q.in.level = 21;
4849 q.out.info = &info;
4850 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
4851 if (!NT_STATUS_IS_OK(status)) {
4852 printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
4853 return false;
4856 switch (querydisplayinfo->in.level) {
4857 case 1:
4858 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
4859 *seen_testuser = true;
4861 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
4862 info->info21.full_name, info->info21.account_name);
4863 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
4864 info->info21.account_name, info->info21.account_name);
4865 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
4866 info->info21.description, info->info21.account_name);
4867 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
4868 info->info21.rid, info->info21.account_name);
4869 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
4870 info->info21.acct_flags, info->info21.account_name);
4872 break;
4873 case 2:
4874 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
4875 info->info21.account_name, info->info21.account_name);
4876 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
4877 info->info21.description, info->info21.account_name);
4878 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
4879 info->info21.rid, info->info21.account_name);
4880 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
4881 info->info21.acct_flags, info->info21.account_name);
4883 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
4884 printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
4885 info->info21.account_name.string);
4888 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
4889 printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
4890 info->info21.account_name.string,
4891 querydisplayinfo->out.info->info2.entries[i].acct_flags,
4892 info->info21.acct_flags);
4893 return false;
4896 break;
4899 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
4900 return false;
4903 return ret;
4906 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4907 struct policy_handle *handle)
4909 NTSTATUS status;
4910 struct samr_QueryDisplayInfo r;
4911 struct samr_QueryDomainInfo dom_info;
4912 union samr_DomainInfo *info = NULL;
4913 bool ret = true;
4914 uint16_t levels[] = {1, 2, 3, 4, 5};
4915 int i;
4916 bool seen_testuser = false;
4917 uint32_t total_size;
4918 uint32_t returned_size;
4919 union samr_DispInfo disp_info;
4922 for (i=0;i<ARRAY_SIZE(levels);i++) {
4923 printf("Testing QueryDisplayInfo level %u\n", levels[i]);
4925 r.in.start_idx = 0;
4926 status = STATUS_MORE_ENTRIES;
4927 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
4928 r.in.domain_handle = handle;
4929 r.in.level = levels[i];
4930 r.in.max_entries = 2;
4931 r.in.buf_size = (uint32_t)-1;
4932 r.out.total_size = &total_size;
4933 r.out.returned_size = &returned_size;
4934 r.out.info = &disp_info;
4936 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
4937 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
4938 printf("QueryDisplayInfo level %u failed - %s\n",
4939 levels[i], nt_errstr(status));
4940 ret = false;
4942 switch (r.in.level) {
4943 case 1:
4944 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) {
4945 ret = false;
4947 r.in.start_idx += r.out.info->info1.count;
4948 break;
4949 case 2:
4950 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) {
4951 ret = false;
4953 r.in.start_idx += r.out.info->info2.count;
4954 break;
4955 case 3:
4956 r.in.start_idx += r.out.info->info3.count;
4957 break;
4958 case 4:
4959 r.in.start_idx += r.out.info->info4.count;
4960 break;
4961 case 5:
4962 r.in.start_idx += r.out.info->info5.count;
4963 break;
4966 dom_info.in.domain_handle = handle;
4967 dom_info.in.level = 2;
4968 dom_info.out.info = &info;
4970 /* Check number of users returned is correct */
4971 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info);
4972 if (!NT_STATUS_IS_OK(status)) {
4973 printf("QueryDomainInfo level %u failed - %s\n",
4974 r.in.level, nt_errstr(status));
4975 ret = false;
4976 break;
4978 switch (r.in.level) {
4979 case 1:
4980 case 4:
4981 if (info->general.num_users < r.in.start_idx) {
4982 printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
4983 r.in.start_idx, info->general.num_groups,
4984 info->general.domain_name.string);
4985 ret = false;
4987 if (!seen_testuser) {
4988 struct policy_handle user_handle;
4989 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
4990 printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
4991 info->general.domain_name.string);
4992 ret = false;
4993 test_samr_handle_Close(p, mem_ctx, &user_handle);
4996 break;
4997 case 3:
4998 case 5:
4999 if (info->general.num_groups != r.in.start_idx) {
5000 printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
5001 r.in.start_idx, info->general.num_groups,
5002 info->general.domain_name.string);
5003 ret = false;
5006 break;
5011 return ret;
5014 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
5015 struct policy_handle *handle)
5017 NTSTATUS status;
5018 struct samr_QueryDisplayInfo2 r;
5019 bool ret = true;
5020 uint16_t levels[] = {1, 2, 3, 4, 5};
5021 int i;
5022 uint32_t total_size;
5023 uint32_t returned_size;
5024 union samr_DispInfo info;
5026 for (i=0;i<ARRAY_SIZE(levels);i++) {
5027 printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
5029 r.in.domain_handle = handle;
5030 r.in.level = levels[i];
5031 r.in.start_idx = 0;
5032 r.in.max_entries = 1000;
5033 r.in.buf_size = (uint32_t)-1;
5034 r.out.total_size = &total_size;
5035 r.out.returned_size = &returned_size;
5036 r.out.info = &info;
5038 status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
5039 if (!NT_STATUS_IS_OK(status)) {
5040 printf("QueryDisplayInfo2 level %u failed - %s\n",
5041 levels[i], nt_errstr(status));
5042 ret = false;
5046 return ret;
5049 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
5050 struct policy_handle *handle)
5052 NTSTATUS status;
5053 struct samr_QueryDisplayInfo3 r;
5054 bool ret = true;
5055 uint16_t levels[] = {1, 2, 3, 4, 5};
5056 int i;
5057 uint32_t total_size;
5058 uint32_t returned_size;
5059 union samr_DispInfo info;
5061 for (i=0;i<ARRAY_SIZE(levels);i++) {
5062 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
5064 r.in.domain_handle = handle;
5065 r.in.level = levels[i];
5066 r.in.start_idx = 0;
5067 r.in.max_entries = 1000;
5068 r.in.buf_size = (uint32_t)-1;
5069 r.out.total_size = &total_size;
5070 r.out.returned_size = &returned_size;
5071 r.out.info = &info;
5073 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
5074 if (!NT_STATUS_IS_OK(status)) {
5075 printf("QueryDisplayInfo3 level %u failed - %s\n",
5076 levels[i], nt_errstr(status));
5077 ret = false;
5081 return ret;
5085 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
5086 struct policy_handle *handle)
5088 NTSTATUS status;
5089 struct samr_QueryDisplayInfo r;
5090 bool ret = true;
5091 uint32_t total_size;
5092 uint32_t returned_size;
5093 union samr_DispInfo info;
5095 printf("Testing QueryDisplayInfo continuation\n");
5097 r.in.domain_handle = handle;
5098 r.in.level = 1;
5099 r.in.start_idx = 0;
5100 r.in.max_entries = 1;
5101 r.in.buf_size = (uint32_t)-1;
5102 r.out.total_size = &total_size;
5103 r.out.returned_size = &returned_size;
5104 r.out.info = &info;
5106 do {
5107 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
5108 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
5109 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
5110 printf("expected idx %d but got %d\n",
5111 r.in.start_idx + 1,
5112 r.out.info->info1.entries[0].idx);
5113 break;
5116 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5117 !NT_STATUS_IS_OK(status)) {
5118 printf("QueryDisplayInfo level %u failed - %s\n",
5119 r.in.level, nt_errstr(status));
5120 ret = false;
5121 break;
5123 r.in.start_idx++;
5124 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
5125 NT_STATUS_IS_OK(status)) &&
5126 *r.out.returned_size != 0);
5128 return ret;
5131 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
5132 struct policy_handle *handle)
5134 NTSTATUS status;
5135 struct samr_QueryDomainInfo r;
5136 union samr_DomainInfo *info = NULL;
5137 struct samr_SetDomainInfo s;
5138 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5139 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5140 int i;
5141 bool ret = true;
5142 const char *domain_comment = talloc_asprintf(tctx,
5143 "Tortured by Samba4 RPC-SAMR: %s",
5144 timestring(tctx, time(NULL)));
5146 s.in.domain_handle = handle;
5147 s.in.level = 4;
5148 s.in.info = talloc(tctx, union samr_DomainInfo);
5150 s.in.info->oem.oem_information.string = domain_comment;
5151 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5152 if (!NT_STATUS_IS_OK(status)) {
5153 printf("SetDomainInfo level %u (set comment) failed - %s\n",
5154 r.in.level, nt_errstr(status));
5155 return false;
5158 for (i=0;i<ARRAY_SIZE(levels);i++) {
5159 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
5161 r.in.domain_handle = handle;
5162 r.in.level = levels[i];
5163 r.out.info = &info;
5165 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5166 if (!NT_STATUS_IS_OK(status)) {
5167 printf("QueryDomainInfo level %u failed - %s\n",
5168 r.in.level, nt_errstr(status));
5169 ret = false;
5170 continue;
5173 switch (levels[i]) {
5174 case 2:
5175 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
5176 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5177 levels[i], info->general.oem_information.string, domain_comment);
5178 ret = false;
5180 if (!info->general.primary.string) {
5181 printf("QueryDomainInfo level %u returned no PDC name\n",
5182 levels[i]);
5183 ret = false;
5184 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
5185 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
5186 printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5187 levels[i], info->general.primary.string, dcerpc_server_name(p));
5190 break;
5191 case 4:
5192 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
5193 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5194 levels[i], info->oem.oem_information.string, domain_comment);
5195 ret = false;
5197 break;
5198 case 6:
5199 if (!info->info6.primary.string) {
5200 printf("QueryDomainInfo level %u returned no PDC name\n",
5201 levels[i]);
5202 ret = false;
5204 break;
5205 case 11:
5206 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
5207 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5208 levels[i], info->general2.general.oem_information.string, domain_comment);
5209 ret = false;
5211 break;
5214 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
5216 s.in.domain_handle = handle;
5217 s.in.level = levels[i];
5218 s.in.info = info;
5220 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5221 if (set_ok[i]) {
5222 if (!NT_STATUS_IS_OK(status)) {
5223 printf("SetDomainInfo level %u failed - %s\n",
5224 r.in.level, nt_errstr(status));
5225 ret = false;
5226 continue;
5228 } else {
5229 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5230 printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5231 r.in.level, nt_errstr(status));
5232 ret = false;
5233 continue;
5237 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5238 if (!NT_STATUS_IS_OK(status)) {
5239 printf("QueryDomainInfo level %u failed - %s\n",
5240 r.in.level, nt_errstr(status));
5241 ret = false;
5242 continue;
5246 return ret;
5250 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
5251 struct policy_handle *handle)
5253 NTSTATUS status;
5254 struct samr_QueryDomainInfo2 r;
5255 union samr_DomainInfo *info = NULL;
5256 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5257 int i;
5258 bool ret = true;
5260 for (i=0;i<ARRAY_SIZE(levels);i++) {
5261 printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
5263 r.in.domain_handle = handle;
5264 r.in.level = levels[i];
5265 r.out.info = &info;
5267 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
5268 if (!NT_STATUS_IS_OK(status)) {
5269 printf("QueryDomainInfo2 level %u failed - %s\n",
5270 r.in.level, nt_errstr(status));
5271 ret = false;
5272 continue;
5276 return true;
5279 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5280 set of group names. */
5281 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
5282 struct policy_handle *handle)
5284 struct samr_EnumDomainGroups q1;
5285 struct samr_QueryDisplayInfo q2;
5286 NTSTATUS status;
5287 uint32_t resume_handle=0;
5288 struct samr_SamArray *sam = NULL;
5289 uint32_t num_entries = 0;
5290 int i;
5291 bool ret = true;
5292 uint32_t total_size;
5293 uint32_t returned_size;
5294 union samr_DispInfo info;
5296 int num_names = 0;
5297 const char **names = NULL;
5299 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
5301 q1.in.domain_handle = handle;
5302 q1.in.resume_handle = &resume_handle;
5303 q1.in.max_size = 5;
5304 q1.out.resume_handle = &resume_handle;
5305 q1.out.num_entries = &num_entries;
5306 q1.out.sam = &sam;
5308 status = STATUS_MORE_ENTRIES;
5309 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5310 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
5312 if (!NT_STATUS_IS_OK(status) &&
5313 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5314 break;
5316 for (i=0; i<*q1.out.num_entries; i++) {
5317 add_string_to_array(tctx,
5318 sam->entries[i].name.string,
5319 &names, &num_names);
5323 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
5325 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
5327 q2.in.domain_handle = handle;
5328 q2.in.level = 5;
5329 q2.in.start_idx = 0;
5330 q2.in.max_entries = 5;
5331 q2.in.buf_size = (uint32_t)-1;
5332 q2.out.total_size = &total_size;
5333 q2.out.returned_size = &returned_size;
5334 q2.out.info = &info;
5336 status = STATUS_MORE_ENTRIES;
5337 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5338 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
5340 if (!NT_STATUS_IS_OK(status) &&
5341 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5342 break;
5344 for (i=0; i<q2.out.info->info5.count; i++) {
5345 int j;
5346 const char *name = q2.out.info->info5.entries[i].account_name.string;
5347 bool found = false;
5348 for (j=0; j<num_names; j++) {
5349 if (names[j] == NULL)
5350 continue;
5351 if (strequal(names[j], name)) {
5352 names[j] = NULL;
5353 found = true;
5354 break;
5358 if (!found) {
5359 printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5360 name);
5361 ret = false;
5364 q2.in.start_idx += q2.out.info->info5.count;
5367 if (!NT_STATUS_IS_OK(status)) {
5368 printf("QueryDisplayInfo level 5 failed - %s\n",
5369 nt_errstr(status));
5370 ret = false;
5373 for (i=0; i<num_names; i++) {
5374 if (names[i] != NULL) {
5375 printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5376 names[i]);
5377 ret = false;
5381 return ret;
5384 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
5385 struct policy_handle *group_handle)
5387 struct samr_DeleteDomainGroup d;
5388 NTSTATUS status;
5390 torture_comment(tctx, "Testing DeleteDomainGroup\n");
5392 d.in.group_handle = group_handle;
5393 d.out.group_handle = group_handle;
5395 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
5396 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
5398 return true;
5401 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5402 struct policy_handle *domain_handle)
5404 struct samr_TestPrivateFunctionsDomain r;
5405 NTSTATUS status;
5406 bool ret = true;
5408 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
5410 r.in.domain_handle = domain_handle;
5412 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
5413 torture_assert_ntstatus_equal(tctx, NT_STATUS_NOT_IMPLEMENTED, status, "TestPrivateFunctionsDomain");
5415 return ret;
5418 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
5419 struct dom_sid *domain_sid,
5420 struct policy_handle *domain_handle)
5422 struct samr_RidToSid r;
5423 NTSTATUS status;
5424 bool ret = true;
5425 struct dom_sid *calc_sid, *out_sid;
5426 int rids[] = { 0, 42, 512, 10200 };
5427 int i;
5429 for (i=0;i<ARRAY_SIZE(rids);i++) {
5430 torture_comment(tctx, "Testing RidToSid\n");
5432 calc_sid = dom_sid_dup(tctx, domain_sid);
5433 r.in.domain_handle = domain_handle;
5434 r.in.rid = rids[i];
5435 r.out.sid = &out_sid;
5437 status = dcerpc_samr_RidToSid(p, tctx, &r);
5438 if (!NT_STATUS_IS_OK(status)) {
5439 printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
5440 ret = false;
5441 } else {
5442 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
5444 if (!dom_sid_equal(calc_sid, out_sid)) {
5445 printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
5446 dom_sid_string(tctx, out_sid),
5447 dom_sid_string(tctx, calc_sid));
5448 ret = false;
5453 return ret;
5456 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
5457 struct policy_handle *domain_handle)
5459 struct samr_GetBootKeyInformation r;
5460 NTSTATUS status;
5461 bool ret = true;
5462 uint32_t unknown = 0;
5464 torture_comment(tctx, "Testing GetBootKeyInformation\n");
5466 r.in.domain_handle = domain_handle;
5467 r.out.unknown = &unknown;
5469 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
5470 if (!NT_STATUS_IS_OK(status)) {
5471 /* w2k3 seems to fail this sometimes and pass it sometimes */
5472 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
5475 return ret;
5478 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
5479 struct policy_handle *domain_handle,
5480 struct policy_handle *group_handle)
5482 NTSTATUS status;
5483 struct samr_AddGroupMember r;
5484 struct samr_DeleteGroupMember d;
5485 struct samr_QueryGroupMember q;
5486 struct samr_RidTypeArray *rids = NULL;
5487 struct samr_SetMemberAttributesOfGroup s;
5488 uint32_t rid;
5490 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
5491 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
5493 r.in.group_handle = group_handle;
5494 r.in.rid = rid;
5495 r.in.flags = 0; /* ??? */
5497 torture_comment(tctx, "Testing AddGroupMember and DeleteGroupMember\n");
5499 d.in.group_handle = group_handle;
5500 d.in.rid = rid;
5502 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5503 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
5505 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5506 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5508 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5509 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
5511 if (torture_setting_bool(tctx, "samba4", false)) {
5512 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba4\n");
5513 } else {
5514 /* this one is quite strange. I am using random inputs in the
5515 hope of triggering an error that might give us a clue */
5517 s.in.group_handle = group_handle;
5518 s.in.unknown1 = random();
5519 s.in.unknown2 = random();
5521 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
5522 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
5525 q.in.group_handle = group_handle;
5526 q.out.rids = &rids;
5528 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5529 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5531 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5532 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
5534 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5535 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5537 return true;
5541 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
5542 struct torture_context *tctx,
5543 struct policy_handle *domain_handle,
5544 struct policy_handle *group_handle,
5545 struct dom_sid *domain_sid)
5547 NTSTATUS status;
5548 struct samr_CreateDomainGroup r;
5549 uint32_t rid;
5550 struct lsa_String name;
5551 bool ret = true;
5553 init_lsa_String(&name, TEST_GROUPNAME);
5555 r.in.domain_handle = domain_handle;
5556 r.in.name = &name;
5557 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5558 r.out.group_handle = group_handle;
5559 r.out.rid = &rid;
5561 printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
5563 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5565 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5566 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5567 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
5568 return true;
5569 } else {
5570 printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
5571 nt_errstr(status));
5572 return false;
5576 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
5577 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
5578 printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
5579 nt_errstr(status));
5580 return false;
5582 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5584 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5585 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
5587 printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
5588 nt_errstr(status));
5589 return false;
5591 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5593 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
5595 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
5596 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
5597 ret = false;
5600 if (!test_SetGroupInfo(p, tctx, group_handle)) {
5601 ret = false;
5604 return ret;
5609 its not totally clear what this does. It seems to accept any sid you like.
5611 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
5612 struct torture_context *tctx,
5613 struct policy_handle *domain_handle)
5615 NTSTATUS status;
5616 struct samr_RemoveMemberFromForeignDomain r;
5618 r.in.domain_handle = domain_handle;
5619 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
5621 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
5622 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
5624 return true;
5629 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
5630 struct policy_handle *handle);
5632 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5633 struct policy_handle *handle, struct dom_sid *sid,
5634 enum torture_samr_choice which_ops,
5635 struct cli_credentials *machine_credentials)
5637 NTSTATUS status;
5638 struct samr_OpenDomain r;
5639 struct policy_handle domain_handle;
5640 struct policy_handle alias_handle;
5641 struct policy_handle user_handle;
5642 struct policy_handle group_handle;
5643 bool ret = true;
5645 ZERO_STRUCT(alias_handle);
5646 ZERO_STRUCT(user_handle);
5647 ZERO_STRUCT(group_handle);
5648 ZERO_STRUCT(domain_handle);
5650 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
5652 r.in.connect_handle = handle;
5653 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5654 r.in.sid = sid;
5655 r.out.domain_handle = &domain_handle;
5657 status = dcerpc_samr_OpenDomain(p, tctx, &r);
5658 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
5660 /* run the domain tests with the main handle closed - this tests
5661 the servers reference counting */
5662 ret &= test_samr_handle_Close(p, tctx, handle);
5664 switch (which_ops) {
5665 case TORTURE_SAMR_USER_ATTRIBUTES:
5666 case TORTURE_SAMR_PASSWORDS:
5667 if (!torture_setting_bool(tctx, "samba3", false)) {
5668 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
5670 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
5671 /* This test needs 'complex' users to validate */
5672 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
5673 if (!ret) {
5674 printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
5676 break;
5677 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
5678 if (!torture_setting_bool(tctx, "samba3", false)) {
5679 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, machine_credentials);
5681 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, machine_credentials);
5682 if (!ret) {
5683 printf("Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
5685 break;
5686 case TORTURE_SAMR_OTHER:
5687 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
5688 if (!ret) {
5689 printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
5691 ret &= test_QuerySecurity(p, tctx, &domain_handle);
5692 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
5693 ret &= test_CreateAlias(p, tctx, &domain_handle, &alias_handle, sid);
5694 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle, sid);
5695 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
5696 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
5697 ret &= test_EnumDomainUsers(p, tctx, &domain_handle);
5698 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
5699 ret &= test_EnumDomainGroups(p, tctx, &domain_handle);
5700 ret &= test_EnumDomainAliases(p, tctx, &domain_handle);
5701 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
5702 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
5703 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
5705 if (torture_setting_bool(tctx, "samba4", false)) {
5706 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
5707 } else {
5708 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
5709 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
5711 ret &= test_GroupList(p, tctx, &domain_handle);
5712 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
5713 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
5714 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
5715 if (!ret) {
5716 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
5718 break;
5721 if (!policy_handle_empty(&user_handle) &&
5722 !test_DeleteUser(p, tctx, &user_handle)) {
5723 ret = false;
5726 if (!policy_handle_empty(&alias_handle) &&
5727 !test_DeleteAlias(p, tctx, &alias_handle)) {
5728 ret = false;
5731 if (!policy_handle_empty(&group_handle) &&
5732 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
5733 ret = false;
5736 ret &= test_samr_handle_Close(p, tctx, &domain_handle);
5738 /* reconnect the main handle */
5739 ret &= test_Connect(p, tctx, handle);
5741 if (!ret) {
5742 printf("Testing domain %s failed!\n", dom_sid_string(tctx, sid));
5745 return ret;
5748 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5749 struct policy_handle *handle, const char *domain,
5750 enum torture_samr_choice which_ops,
5751 struct cli_credentials *machine_credentials)
5753 NTSTATUS status;
5754 struct samr_LookupDomain r;
5755 struct dom_sid2 *sid = NULL;
5756 struct lsa_String n1;
5757 struct lsa_String n2;
5758 bool ret = true;
5760 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
5762 /* check for correct error codes */
5763 r.in.connect_handle = handle;
5764 r.in.domain_name = &n2;
5765 r.out.sid = &sid;
5766 n2.string = NULL;
5768 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5769 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
5771 init_lsa_String(&n2, "xxNODOMAINxx");
5773 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5774 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
5776 r.in.connect_handle = handle;
5778 init_lsa_String(&n1, domain);
5779 r.in.domain_name = &n1;
5781 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5782 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
5784 if (!test_GetDomPwInfo(p, tctx, &n1)) {
5785 ret = false;
5788 if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops,
5789 machine_credentials)) {
5790 ret = false;
5793 return ret;
5797 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
5798 struct policy_handle *handle, enum torture_samr_choice which_ops,
5799 struct cli_credentials *machine_credentials)
5801 NTSTATUS status;
5802 struct samr_EnumDomains r;
5803 uint32_t resume_handle = 0;
5804 uint32_t num_entries = 0;
5805 struct samr_SamArray *sam = NULL;
5806 int i;
5807 bool ret = true;
5809 r.in.connect_handle = handle;
5810 r.in.resume_handle = &resume_handle;
5811 r.in.buf_size = (uint32_t)-1;
5812 r.out.resume_handle = &resume_handle;
5813 r.out.num_entries = &num_entries;
5814 r.out.sam = &sam;
5816 status = dcerpc_samr_EnumDomains(p, tctx, &r);
5817 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
5819 if (!*r.out.sam) {
5820 return false;
5823 for (i=0;i<sam->count;i++) {
5824 if (!test_LookupDomain(p, tctx, handle,
5825 sam->entries[i].name.string, which_ops,
5826 machine_credentials)) {
5827 ret = false;
5831 status = dcerpc_samr_EnumDomains(p, tctx, &r);
5832 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
5834 return ret;
5838 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
5839 struct policy_handle *handle)
5841 NTSTATUS status;
5842 struct samr_Connect r;
5843 struct samr_Connect2 r2;
5844 struct samr_Connect3 r3;
5845 struct samr_Connect4 r4;
5846 struct samr_Connect5 r5;
5847 union samr_ConnectInfo info;
5848 struct policy_handle h;
5849 uint32_t level_out = 0;
5850 bool ret = true, got_handle = false;
5852 torture_comment(tctx, "testing samr_Connect\n");
5854 r.in.system_name = 0;
5855 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5856 r.out.connect_handle = &h;
5858 status = dcerpc_samr_Connect(p, tctx, &r);
5859 if (!NT_STATUS_IS_OK(status)) {
5860 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
5861 ret = false;
5862 } else {
5863 got_handle = true;
5864 *handle = h;
5867 torture_comment(tctx, "testing samr_Connect2\n");
5869 r2.in.system_name = NULL;
5870 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5871 r2.out.connect_handle = &h;
5873 status = dcerpc_samr_Connect2(p, tctx, &r2);
5874 if (!NT_STATUS_IS_OK(status)) {
5875 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
5876 ret = false;
5877 } else {
5878 if (got_handle) {
5879 test_samr_handle_Close(p, tctx, handle);
5881 got_handle = true;
5882 *handle = h;
5885 torture_comment(tctx, "testing samr_Connect3\n");
5887 r3.in.system_name = NULL;
5888 r3.in.unknown = 0;
5889 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5890 r3.out.connect_handle = &h;
5892 status = dcerpc_samr_Connect3(p, tctx, &r3);
5893 if (!NT_STATUS_IS_OK(status)) {
5894 printf("Connect3 failed - %s\n", nt_errstr(status));
5895 ret = false;
5896 } else {
5897 if (got_handle) {
5898 test_samr_handle_Close(p, tctx, handle);
5900 got_handle = true;
5901 *handle = h;
5904 torture_comment(tctx, "testing samr_Connect4\n");
5906 r4.in.system_name = "";
5907 r4.in.client_version = 0;
5908 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5909 r4.out.connect_handle = &h;
5911 status = dcerpc_samr_Connect4(p, tctx, &r4);
5912 if (!NT_STATUS_IS_OK(status)) {
5913 printf("Connect4 failed - %s\n", nt_errstr(status));
5914 ret = false;
5915 } else {
5916 if (got_handle) {
5917 test_samr_handle_Close(p, tctx, handle);
5919 got_handle = true;
5920 *handle = h;
5923 torture_comment(tctx, "testing samr_Connect5\n");
5925 info.info1.client_version = 0;
5926 info.info1.unknown2 = 0;
5928 r5.in.system_name = "";
5929 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5930 r5.in.level_in = 1;
5931 r5.out.level_out = &level_out;
5932 r5.in.info_in = &info;
5933 r5.out.info_out = &info;
5934 r5.out.connect_handle = &h;
5936 status = dcerpc_samr_Connect5(p, tctx, &r5);
5937 if (!NT_STATUS_IS_OK(status)) {
5938 printf("Connect5 failed - %s\n", nt_errstr(status));
5939 ret = false;
5940 } else {
5941 if (got_handle) {
5942 test_samr_handle_Close(p, tctx, handle);
5944 got_handle = true;
5945 *handle = h;
5948 return ret;
5952 bool torture_rpc_samr(struct torture_context *torture)
5954 NTSTATUS status;
5955 struct dcerpc_pipe *p;
5956 bool ret = true;
5957 struct policy_handle handle;
5959 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
5960 if (!NT_STATUS_IS_OK(status)) {
5961 return false;
5964 ret &= test_Connect(p, torture, &handle);
5966 ret &= test_QuerySecurity(p, torture, &handle);
5968 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
5970 ret &= test_SetDsrmPassword(p, torture, &handle);
5972 ret &= test_Shutdown(p, torture, &handle);
5974 ret &= test_samr_handle_Close(p, torture, &handle);
5976 return ret;
5980 bool torture_rpc_samr_users(struct torture_context *torture)
5982 NTSTATUS status;
5983 struct dcerpc_pipe *p;
5984 bool ret = true;
5985 struct policy_handle handle;
5987 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
5988 if (!NT_STATUS_IS_OK(status)) {
5989 return false;
5992 ret &= test_Connect(p, torture, &handle);
5994 ret &= test_QuerySecurity(p, torture, &handle);
5996 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
5998 ret &= test_SetDsrmPassword(p, torture, &handle);
6000 ret &= test_Shutdown(p, torture, &handle);
6002 ret &= test_samr_handle_Close(p, torture, &handle);
6004 return ret;
6008 bool torture_rpc_samr_passwords(struct torture_context *torture)
6010 NTSTATUS status;
6011 struct dcerpc_pipe *p;
6012 bool ret = true;
6013 struct policy_handle handle;
6015 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6016 if (!NT_STATUS_IS_OK(status)) {
6017 return false;
6020 ret &= test_Connect(p, torture, &handle);
6022 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
6024 ret &= test_samr_handle_Close(p, torture, &handle);
6026 return ret;
6029 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
6030 struct dcerpc_pipe *p2,
6031 struct cli_credentials *machine_credentials)
6033 NTSTATUS status;
6034 struct dcerpc_pipe *p;
6035 bool ret = true;
6036 struct policy_handle handle;
6038 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6039 if (!NT_STATUS_IS_OK(status)) {
6040 return false;
6043 ret &= test_Connect(p, torture, &handle);
6045 ret &= test_EnumDomains(p, torture, &handle,
6046 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
6047 machine_credentials);
6049 ret &= test_samr_handle_Close(p, torture, &handle);
6051 return ret;
6054 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
6056 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
6057 struct torture_rpc_tcase *tcase;
6059 tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
6060 &ndr_table_samr,
6061 TEST_ACCOUNT_NAME_PWD);
6063 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
6064 torture_rpc_samr_pwdlastset);
6066 return suite;