s4-smbtorture: skip unsupported ACB bits for Samba3 in RPC-SAMR-USER.
[Samba.git] / source4 / torture / rpc / samr.c
blobdec8984ca85b6d57c0079e0c6cfa5338b8d1305b
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;
193 if (!torture_setting_bool(tctx, "samba3", false)) {
194 if (base_acct_flags == ACB_NORMAL) {
195 /* When created, accounts are expired by default */
196 user_extra_flags = ACB_PW_EXPIRED;
200 s.in.user_handle = handle;
201 s.in.info = &u;
203 s2.in.user_handle = handle;
204 s2.in.info = &u;
206 q.in.user_handle = handle;
207 q.out.info = &info;
208 q0 = q;
210 #define TESTCALL(call, r) \
211 status = dcerpc_samr_ ##call(p, tctx, &r); \
212 if (!NT_STATUS_IS_OK(status)) { \
213 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
214 r.in.level, nt_errstr(status), __location__); \
215 ret = false; \
216 break; \
219 #define STRING_EQUAL(s1, s2, field) \
220 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
221 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
222 #field, s2, __location__); \
223 ret = false; \
224 break; \
227 #define MEM_EQUAL(s1, s2, length, field) \
228 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
229 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
230 #field, (const char *)s2, __location__); \
231 ret = false; \
232 break; \
235 #define INT_EQUAL(i1, i2, field) \
236 if (i1 != i2) { \
237 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
238 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
239 ret = false; \
240 break; \
243 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
244 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
245 q.in.level = lvl1; \
246 TESTCALL(QueryUserInfo, q) \
247 s.in.level = lvl1; \
248 s2.in.level = lvl1; \
249 u = *info; \
250 if (lvl1 == 21) { \
251 ZERO_STRUCT(u.info21); \
252 u.info21.fields_present = fpval; \
254 init_lsa_String(&u.info ## lvl1.field1, value); \
255 TESTCALL(SetUserInfo, s) \
256 TESTCALL(SetUserInfo2, s2) \
257 init_lsa_String(&u.info ## lvl1.field1, ""); \
258 TESTCALL(QueryUserInfo, q); \
259 u = *info; \
260 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
261 q.in.level = lvl2; \
262 TESTCALL(QueryUserInfo, q) \
263 u = *info; \
264 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
265 } while (0)
267 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
268 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
269 q.in.level = lvl1; \
270 TESTCALL(QueryUserInfo, q) \
271 s.in.level = lvl1; \
272 s2.in.level = lvl1; \
273 u = *info; \
274 if (lvl1 == 21) { \
275 ZERO_STRUCT(u.info21); \
276 u.info21.fields_present = fpval; \
278 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
279 TESTCALL(SetUserInfo, s) \
280 TESTCALL(SetUserInfo2, s2) \
281 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
282 TESTCALL(QueryUserInfo, q); \
283 u = *info; \
284 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
285 q.in.level = lvl2; \
286 TESTCALL(QueryUserInfo, q) \
287 u = *info; \
288 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
289 } while (0)
291 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
292 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
293 q.in.level = lvl1; \
294 TESTCALL(QueryUserInfo, q) \
295 s.in.level = lvl1; \
296 s2.in.level = lvl1; \
297 u = *info; \
298 if (lvl1 == 21) { \
299 uint8_t *bits = u.info21.logon_hours.bits; \
300 ZERO_STRUCT(u.info21); \
301 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
302 u.info21.logon_hours.units_per_week = 168; \
303 u.info21.logon_hours.bits = bits; \
305 u.info21.fields_present = fpval; \
307 u.info ## lvl1.field1 = value; \
308 TESTCALL(SetUserInfo, s) \
309 TESTCALL(SetUserInfo2, s2) \
310 u.info ## lvl1.field1 = 0; \
311 TESTCALL(QueryUserInfo, q); \
312 u = *info; \
313 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
314 q.in.level = lvl2; \
315 TESTCALL(QueryUserInfo, q) \
316 u = *info; \
317 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
318 } while (0)
320 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
321 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
322 } while (0)
324 q0.in.level = 12;
325 do { TESTCALL(QueryUserInfo, q0) } while (0);
327 /* Samba 3 cannot store comment fields atm. - gd */
328 if (!torture_setting_bool(tctx, "samba3", false)) {
329 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
330 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
331 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
332 SAMR_FIELD_COMMENT);
335 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
336 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
337 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
338 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
339 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
340 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
341 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
342 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
343 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
344 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
345 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
346 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
347 test_account_name = base_account_name;
348 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
349 SAMR_FIELD_ACCOUNT_NAME);
351 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
352 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
353 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
354 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
355 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
356 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
357 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
358 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
359 SAMR_FIELD_FULL_NAME);
361 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
362 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
363 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
364 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
365 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
366 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
367 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
368 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
369 SAMR_FIELD_FULL_NAME);
371 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
372 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
373 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
374 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
375 SAMR_FIELD_LOGON_SCRIPT);
377 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
378 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
379 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
380 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
381 SAMR_FIELD_PROFILE_PATH);
383 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
384 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
385 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
386 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
387 SAMR_FIELD_HOME_DIRECTORY);
388 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
389 SAMR_FIELD_HOME_DIRECTORY);
391 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
392 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
393 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
394 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
395 SAMR_FIELD_HOME_DRIVE);
396 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
397 SAMR_FIELD_HOME_DRIVE);
399 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
400 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
401 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
402 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
403 SAMR_FIELD_DESCRIPTION);
405 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
406 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
407 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
408 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
409 SAMR_FIELD_WORKSTATIONS);
410 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
411 SAMR_FIELD_WORKSTATIONS);
412 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
413 SAMR_FIELD_WORKSTATIONS);
414 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
415 SAMR_FIELD_WORKSTATIONS);
417 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
418 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
419 SAMR_FIELD_PARAMETERS);
420 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
421 SAMR_FIELD_PARAMETERS);
422 /* also empty user parameters are allowed */
423 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
424 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
425 SAMR_FIELD_PARAMETERS);
426 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
427 SAMR_FIELD_PARAMETERS);
429 /* Samba 3 cannot store country_code and copy_page atm. - gd */
430 if (!torture_setting_bool(tctx, "samba3", false)) {
431 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
432 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
433 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
434 SAMR_FIELD_COUNTRY_CODE);
435 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
436 SAMR_FIELD_COUNTRY_CODE);
438 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
439 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
440 SAMR_FIELD_CODE_PAGE);
441 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
442 SAMR_FIELD_CODE_PAGE);
445 if (!torture_setting_bool(tctx, "samba3", false)) {
446 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
447 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
448 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
449 SAMR_FIELD_ACCT_EXPIRY);
450 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
451 SAMR_FIELD_ACCT_EXPIRY);
452 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
453 SAMR_FIELD_ACCT_EXPIRY);
454 } else {
455 /* Samba 3 can only store seconds / time_t in passdb - gd */
456 NTTIME nt;
457 unix_to_nt_time(&nt, time(NULL) + __LINE__);
458 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
459 unix_to_nt_time(&nt, time(NULL) + __LINE__);
460 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
461 unix_to_nt_time(&nt, time(NULL) + __LINE__);
462 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
463 unix_to_nt_time(&nt, time(NULL) + __LINE__);
464 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
465 unix_to_nt_time(&nt, time(NULL) + __LINE__);
466 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
469 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
470 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
471 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
472 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
473 SAMR_FIELD_LOGON_HOURS);
475 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
476 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
477 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
479 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
480 (base_acct_flags | ACB_DISABLED),
481 (base_acct_flags | ACB_DISABLED | user_extra_flags),
484 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
485 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
486 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
487 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
489 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
490 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
491 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
495 /* The 'autolock' flag doesn't stick - check this */
496 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
497 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
498 (base_acct_flags | ACB_DISABLED | user_extra_flags),
500 #if 0
501 /* Removing the 'disabled' flag doesn't stick - check this */
502 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
503 (base_acct_flags),
504 (base_acct_flags | ACB_DISABLED | user_extra_flags),
506 #endif
508 /* Samba3 cannot store these atm */
509 if (!torture_setting_bool(tctx, "samba3", false)) {
510 /* The 'store plaintext' flag does stick */
511 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
512 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
513 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
515 /* The 'use DES' flag does stick */
516 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
517 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
518 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
520 /* The 'don't require kerberos pre-authentication flag does stick */
521 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
522 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
523 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
525 /* The 'no kerberos PAC required' flag sticks */
526 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
527 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
528 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
531 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
532 (base_acct_flags | ACB_DISABLED),
533 (base_acct_flags | ACB_DISABLED | user_extra_flags),
534 SAMR_FIELD_ACCT_FLAGS);
536 #if 0
537 /* these fail with win2003 - it appears you can't set the primary gid?
538 the set succeeds, but the gid isn't changed. Very weird! */
539 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
540 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
541 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
542 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
543 #endif
545 return ret;
549 generate a random password for password change tests
551 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
553 size_t len = MAX(8, min_len) + (random() % 6);
554 char *s = generate_random_str(mem_ctx, len);
555 return s;
558 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
560 char *s = samr_rand_pass_silent(mem_ctx, min_len);
561 printf("Generated password '%s'\n", s);
562 return s;
567 generate a random password for password change tests
569 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
571 int i;
572 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
573 generate_random_buffer(password.data, password.length);
575 for (i=0; i < len; i++) {
576 if (((uint16_t *)password.data)[i] == 0) {
577 ((uint16_t *)password.data)[i] = 1;
581 return password;
585 generate a random password for password change tests (fixed length)
587 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
589 char *s = generate_random_str(mem_ctx, len);
590 printf("Generated password '%s'\n", s);
591 return s;
594 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
595 struct policy_handle *handle, char **password)
597 NTSTATUS status;
598 struct samr_SetUserInfo s;
599 union samr_UserInfo u;
600 bool ret = true;
601 DATA_BLOB session_key;
602 char *newpass;
603 struct samr_GetUserPwInfo pwp;
604 struct samr_PwInfo info;
605 int policy_min_pw_len = 0;
606 pwp.in.user_handle = handle;
607 pwp.out.info = &info;
609 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
610 if (NT_STATUS_IS_OK(status)) {
611 policy_min_pw_len = pwp.out.info->min_password_length;
613 newpass = samr_rand_pass(tctx, policy_min_pw_len);
615 s.in.user_handle = handle;
616 s.in.info = &u;
617 s.in.level = 24;
619 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
620 u.info24.password_expired = 0;
622 status = dcerpc_fetch_session_key(p, &session_key);
623 if (!NT_STATUS_IS_OK(status)) {
624 printf("SetUserInfo level %u - no session key - %s\n",
625 s.in.level, nt_errstr(status));
626 return false;
629 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
631 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
633 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
634 if (!NT_STATUS_IS_OK(status)) {
635 printf("SetUserInfo level %u failed - %s\n",
636 s.in.level, nt_errstr(status));
637 ret = false;
638 } else {
639 *password = newpass;
642 return ret;
646 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
647 struct policy_handle *handle, uint32_t fields_present,
648 char **password)
650 NTSTATUS status;
651 struct samr_SetUserInfo s;
652 union samr_UserInfo u;
653 bool ret = true;
654 DATA_BLOB session_key;
655 char *newpass;
656 struct samr_GetUserPwInfo pwp;
657 struct samr_PwInfo info;
658 int policy_min_pw_len = 0;
659 pwp.in.user_handle = handle;
660 pwp.out.info = &info;
662 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
663 if (NT_STATUS_IS_OK(status)) {
664 policy_min_pw_len = pwp.out.info->min_password_length;
666 newpass = samr_rand_pass(tctx, policy_min_pw_len);
668 s.in.user_handle = handle;
669 s.in.info = &u;
670 s.in.level = 23;
672 ZERO_STRUCT(u);
674 u.info23.info.fields_present = fields_present;
676 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
678 status = dcerpc_fetch_session_key(p, &session_key);
679 if (!NT_STATUS_IS_OK(status)) {
680 printf("SetUserInfo level %u - no session key - %s\n",
681 s.in.level, nt_errstr(status));
682 return false;
685 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
687 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
689 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
690 if (!NT_STATUS_IS_OK(status)) {
691 printf("SetUserInfo level %u failed - %s\n",
692 s.in.level, nt_errstr(status));
693 ret = false;
694 } else {
695 *password = newpass;
698 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
700 status = dcerpc_fetch_session_key(p, &session_key);
701 if (!NT_STATUS_IS_OK(status)) {
702 printf("SetUserInfo level %u - no session key - %s\n",
703 s.in.level, nt_errstr(status));
704 return false;
707 /* This should break the key nicely */
708 session_key.length--;
709 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
711 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
713 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
714 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
715 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
716 s.in.level, nt_errstr(status));
717 ret = false;
720 return ret;
724 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
725 struct policy_handle *handle, bool makeshort,
726 char **password)
728 NTSTATUS status;
729 struct samr_SetUserInfo s;
730 union samr_UserInfo u;
731 bool ret = true;
732 DATA_BLOB session_key;
733 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
734 uint8_t confounder[16];
735 char *newpass;
736 struct MD5Context ctx;
737 struct samr_GetUserPwInfo pwp;
738 struct samr_PwInfo info;
739 int policy_min_pw_len = 0;
740 pwp.in.user_handle = handle;
741 pwp.out.info = &info;
743 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
744 if (NT_STATUS_IS_OK(status)) {
745 policy_min_pw_len = pwp.out.info->min_password_length;
747 if (makeshort && policy_min_pw_len) {
748 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
749 } else {
750 newpass = samr_rand_pass(tctx, policy_min_pw_len);
753 s.in.user_handle = handle;
754 s.in.info = &u;
755 s.in.level = 26;
757 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
758 u.info26.password_expired = 0;
760 status = dcerpc_fetch_session_key(p, &session_key);
761 if (!NT_STATUS_IS_OK(status)) {
762 printf("SetUserInfo level %u - no session key - %s\n",
763 s.in.level, nt_errstr(status));
764 return false;
767 generate_random_buffer((uint8_t *)confounder, 16);
769 MD5Init(&ctx);
770 MD5Update(&ctx, confounder, 16);
771 MD5Update(&ctx, session_key.data, session_key.length);
772 MD5Final(confounded_session_key.data, &ctx);
774 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
775 memcpy(&u.info26.password.data[516], confounder, 16);
777 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
779 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
780 if (!NT_STATUS_IS_OK(status)) {
781 printf("SetUserInfo level %u failed - %s\n",
782 s.in.level, nt_errstr(status));
783 ret = false;
784 } else {
785 *password = newpass;
788 /* This should break the key nicely */
789 confounded_session_key.data[0]++;
791 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
792 memcpy(&u.info26.password.data[516], confounder, 16);
794 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
796 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
797 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
798 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
799 s.in.level, nt_errstr(status));
800 ret = false;
801 } else {
802 *password = newpass;
805 return ret;
808 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
809 struct policy_handle *handle, uint32_t fields_present,
810 char **password)
812 NTSTATUS status;
813 struct samr_SetUserInfo s;
814 union samr_UserInfo u;
815 bool ret = true;
816 DATA_BLOB session_key;
817 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
818 struct MD5Context ctx;
819 uint8_t confounder[16];
820 char *newpass;
821 struct samr_GetUserPwInfo pwp;
822 struct samr_PwInfo info;
823 int policy_min_pw_len = 0;
824 pwp.in.user_handle = handle;
825 pwp.out.info = &info;
827 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
828 if (NT_STATUS_IS_OK(status)) {
829 policy_min_pw_len = pwp.out.info->min_password_length;
831 newpass = samr_rand_pass(tctx, policy_min_pw_len);
833 s.in.user_handle = handle;
834 s.in.info = &u;
835 s.in.level = 25;
837 ZERO_STRUCT(u);
839 u.info25.info.fields_present = fields_present;
841 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
843 status = dcerpc_fetch_session_key(p, &session_key);
844 if (!NT_STATUS_IS_OK(status)) {
845 printf("SetUserInfo level %u - no session key - %s\n",
846 s.in.level, nt_errstr(status));
847 return false;
850 generate_random_buffer((uint8_t *)confounder, 16);
852 MD5Init(&ctx);
853 MD5Update(&ctx, confounder, 16);
854 MD5Update(&ctx, session_key.data, session_key.length);
855 MD5Final(confounded_session_key.data, &ctx);
857 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
858 memcpy(&u.info25.password.data[516], confounder, 16);
860 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
862 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
863 if (!NT_STATUS_IS_OK(status)) {
864 printf("SetUserInfo level %u failed - %s\n",
865 s.in.level, nt_errstr(status));
866 ret = false;
867 } else {
868 *password = newpass;
871 /* This should break the key nicely */
872 confounded_session_key.data[0]++;
874 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
875 memcpy(&u.info25.password.data[516], confounder, 16);
877 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
879 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
880 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
881 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
882 s.in.level, nt_errstr(status));
883 ret = false;
886 return ret;
889 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
890 struct policy_handle *handle, char **password)
892 NTSTATUS status;
893 struct samr_SetUserInfo s;
894 union samr_UserInfo u;
895 bool ret = true;
896 DATA_BLOB session_key;
897 char *newpass;
898 struct samr_GetUserPwInfo pwp;
899 struct samr_PwInfo info;
900 int policy_min_pw_len = 0;
901 uint8_t lm_hash[16], nt_hash[16];
903 pwp.in.user_handle = handle;
904 pwp.out.info = &info;
906 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
907 if (NT_STATUS_IS_OK(status)) {
908 policy_min_pw_len = pwp.out.info->min_password_length;
910 newpass = samr_rand_pass(tctx, policy_min_pw_len);
912 s.in.user_handle = handle;
913 s.in.info = &u;
914 s.in.level = 18;
916 ZERO_STRUCT(u);
918 u.info18.nt_pwd_active = true;
919 u.info18.lm_pwd_active = true;
921 E_md4hash(newpass, nt_hash);
922 E_deshash(newpass, lm_hash);
924 status = dcerpc_fetch_session_key(p, &session_key);
925 if (!NT_STATUS_IS_OK(status)) {
926 printf("SetUserInfo level %u - no session key - %s\n",
927 s.in.level, nt_errstr(status));
928 return false;
932 DATA_BLOB in,out;
933 in = data_blob_const(nt_hash, 16);
934 out = data_blob_talloc_zero(tctx, 16);
935 sess_crypt_blob(&out, &in, &session_key, true);
936 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
939 DATA_BLOB in,out;
940 in = data_blob_const(lm_hash, 16);
941 out = data_blob_talloc_zero(tctx, 16);
942 sess_crypt_blob(&out, &in, &session_key, true);
943 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
946 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
948 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
949 if (!NT_STATUS_IS_OK(status)) {
950 printf("SetUserInfo level %u failed - %s\n",
951 s.in.level, nt_errstr(status));
952 ret = false;
953 } else {
954 *password = newpass;
957 return ret;
960 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
961 struct policy_handle *handle, uint32_t fields_present,
962 char **password)
964 NTSTATUS status;
965 struct samr_SetUserInfo s;
966 union samr_UserInfo u;
967 bool ret = true;
968 DATA_BLOB session_key;
969 char *newpass;
970 struct samr_GetUserPwInfo pwp;
971 struct samr_PwInfo info;
972 int policy_min_pw_len = 0;
973 uint8_t lm_hash[16], nt_hash[16];
975 pwp.in.user_handle = handle;
976 pwp.out.info = &info;
978 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
979 if (NT_STATUS_IS_OK(status)) {
980 policy_min_pw_len = pwp.out.info->min_password_length;
982 newpass = samr_rand_pass(tctx, policy_min_pw_len);
984 s.in.user_handle = handle;
985 s.in.info = &u;
986 s.in.level = 21;
988 E_md4hash(newpass, nt_hash);
989 E_deshash(newpass, lm_hash);
991 ZERO_STRUCT(u);
993 u.info21.fields_present = fields_present;
995 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
996 u.info21.lm_owf_password.length = 16;
997 u.info21.lm_owf_password.size = 16;
998 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
999 u.info21.lm_password_set = true;
1002 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1003 u.info21.nt_owf_password.length = 16;
1004 u.info21.nt_owf_password.size = 16;
1005 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1006 u.info21.nt_password_set = true;
1009 status = dcerpc_fetch_session_key(p, &session_key);
1010 if (!NT_STATUS_IS_OK(status)) {
1011 printf("SetUserInfo level %u - no session key - %s\n",
1012 s.in.level, nt_errstr(status));
1013 return false;
1016 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1017 DATA_BLOB in,out;
1018 in = data_blob_const(u.info21.lm_owf_password.array,
1019 u.info21.lm_owf_password.length);
1020 out = data_blob_talloc_zero(tctx, 16);
1021 sess_crypt_blob(&out, &in, &session_key, true);
1022 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1025 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1026 DATA_BLOB in,out;
1027 in = data_blob_const(u.info21.nt_owf_password.array,
1028 u.info21.nt_owf_password.length);
1029 out = data_blob_talloc_zero(tctx, 16);
1030 sess_crypt_blob(&out, &in, &session_key, true);
1031 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1034 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1036 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1037 if (!NT_STATUS_IS_OK(status)) {
1038 printf("SetUserInfo level %u failed - %s\n",
1039 s.in.level, nt_errstr(status));
1040 ret = false;
1041 } else {
1042 *password = newpass;
1045 /* try invalid length */
1046 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1048 u.info21.nt_owf_password.length++;
1050 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1052 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1053 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1054 s.in.level, nt_errstr(status));
1055 ret = false;
1059 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1061 u.info21.lm_owf_password.length++;
1063 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1065 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1066 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1067 s.in.level, nt_errstr(status));
1068 ret = false;
1072 return ret;
1075 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1076 struct torture_context *tctx,
1077 struct policy_handle *handle,
1078 uint16_t level,
1079 uint32_t fields_present,
1080 char **password, uint8_t password_expired,
1081 bool use_setinfo2,
1082 bool *matched_expected_error)
1084 NTSTATUS status;
1085 NTSTATUS expected_error = NT_STATUS_OK;
1086 struct samr_SetUserInfo s;
1087 struct samr_SetUserInfo2 s2;
1088 union samr_UserInfo u;
1089 bool ret = true;
1090 DATA_BLOB session_key;
1091 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1092 struct MD5Context ctx;
1093 uint8_t confounder[16];
1094 char *newpass;
1095 struct samr_GetUserPwInfo pwp;
1096 struct samr_PwInfo info;
1097 int policy_min_pw_len = 0;
1098 const char *comment = NULL;
1099 uint8_t lm_hash[16], nt_hash[16];
1101 pwp.in.user_handle = handle;
1102 pwp.out.info = &info;
1104 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1105 if (NT_STATUS_IS_OK(status)) {
1106 policy_min_pw_len = pwp.out.info->min_password_length;
1108 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1110 if (use_setinfo2) {
1111 s2.in.user_handle = handle;
1112 s2.in.info = &u;
1113 s2.in.level = level;
1114 } else {
1115 s.in.user_handle = handle;
1116 s.in.info = &u;
1117 s.in.level = level;
1120 if (fields_present & SAMR_FIELD_COMMENT) {
1121 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1124 ZERO_STRUCT(u);
1126 switch (level) {
1127 case 18:
1128 E_md4hash(newpass, nt_hash);
1129 E_deshash(newpass, lm_hash);
1131 u.info18.nt_pwd_active = true;
1132 u.info18.lm_pwd_active = true;
1133 u.info18.password_expired = password_expired;
1135 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1136 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1138 break;
1139 case 21:
1140 E_md4hash(newpass, nt_hash);
1141 E_deshash(newpass, lm_hash);
1143 u.info21.fields_present = fields_present;
1144 u.info21.password_expired = password_expired;
1145 u.info21.comment.string = comment;
1147 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1148 u.info21.lm_owf_password.length = 16;
1149 u.info21.lm_owf_password.size = 16;
1150 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1151 u.info21.lm_password_set = true;
1154 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1155 u.info21.nt_owf_password.length = 16;
1156 u.info21.nt_owf_password.size = 16;
1157 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1158 u.info21.nt_password_set = true;
1161 break;
1162 case 23:
1163 u.info23.info.fields_present = fields_present;
1164 u.info23.info.password_expired = password_expired;
1165 u.info23.info.comment.string = comment;
1167 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1169 break;
1170 case 24:
1171 u.info24.password_expired = password_expired;
1173 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1175 break;
1176 case 25:
1177 u.info25.info.fields_present = fields_present;
1178 u.info25.info.password_expired = password_expired;
1179 u.info25.info.comment.string = comment;
1181 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1183 break;
1184 case 26:
1185 u.info26.password_expired = password_expired;
1187 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1189 break;
1192 status = dcerpc_fetch_session_key(p, &session_key);
1193 if (!NT_STATUS_IS_OK(status)) {
1194 printf("SetUserInfo level %u - no session key - %s\n",
1195 s.in.level, nt_errstr(status));
1196 return false;
1199 generate_random_buffer((uint8_t *)confounder, 16);
1201 MD5Init(&ctx);
1202 MD5Update(&ctx, confounder, 16);
1203 MD5Update(&ctx, session_key.data, session_key.length);
1204 MD5Final(confounded_session_key.data, &ctx);
1206 switch (level) {
1207 case 18:
1209 DATA_BLOB in,out;
1210 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1211 out = data_blob_talloc_zero(tctx, 16);
1212 sess_crypt_blob(&out, &in, &session_key, true);
1213 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1216 DATA_BLOB in,out;
1217 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1218 out = data_blob_talloc_zero(tctx, 16);
1219 sess_crypt_blob(&out, &in, &session_key, true);
1220 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1223 break;
1224 case 21:
1225 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1226 DATA_BLOB in,out;
1227 in = data_blob_const(u.info21.lm_owf_password.array,
1228 u.info21.lm_owf_password.length);
1229 out = data_blob_talloc_zero(tctx, 16);
1230 sess_crypt_blob(&out, &in, &session_key, true);
1231 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1233 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1234 DATA_BLOB in,out;
1235 in = data_blob_const(u.info21.nt_owf_password.array,
1236 u.info21.nt_owf_password.length);
1237 out = data_blob_talloc_zero(tctx, 16);
1238 sess_crypt_blob(&out, &in, &session_key, true);
1239 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1241 break;
1242 case 23:
1243 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1244 break;
1245 case 24:
1246 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1247 break;
1248 case 25:
1249 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1250 memcpy(&u.info25.password.data[516], confounder, 16);
1251 break;
1252 case 26:
1253 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1254 memcpy(&u.info26.password.data[516], confounder, 16);
1255 break;
1258 if (use_setinfo2) {
1259 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1260 } else {
1261 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 if (fields_present == 0) {
1266 expected_error = NT_STATUS_INVALID_PARAMETER;
1268 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1269 expected_error = NT_STATUS_ACCESS_DENIED;
1273 if (!NT_STATUS_IS_OK(expected_error)) {
1274 if (use_setinfo2) {
1275 torture_assert_ntstatus_equal(tctx,
1276 s2.out.result,
1277 expected_error, "SetUserInfo2 failed");
1278 } else {
1279 torture_assert_ntstatus_equal(tctx,
1280 s.out.result,
1281 expected_error, "SetUserInfo failed");
1283 *matched_expected_error = true;
1284 return true;
1287 if (!NT_STATUS_IS_OK(status)) {
1288 printf("SetUserInfo%s level %u failed - %s\n",
1289 use_setinfo2 ? "2":"", level, nt_errstr(status));
1290 ret = false;
1291 } else {
1292 *password = newpass;
1295 return ret;
1298 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1299 struct policy_handle *handle)
1301 NTSTATUS status;
1302 struct samr_SetAliasInfo r;
1303 struct samr_QueryAliasInfo q;
1304 union samr_AliasInfo *info;
1305 uint16_t levels[] = {2, 3};
1306 int i;
1307 bool ret = true;
1309 /* Ignoring switch level 1, as that includes the number of members for the alias
1310 * and setting this to a wrong value might have negative consequences
1313 for (i=0;i<ARRAY_SIZE(levels);i++) {
1314 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1316 r.in.alias_handle = handle;
1317 r.in.level = levels[i];
1318 r.in.info = talloc(tctx, union samr_AliasInfo);
1319 switch (r.in.level) {
1320 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1321 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1322 "Test Description, should test I18N as well"); break;
1323 case ALIASINFOALL: printf("ALIASINFOALL ignored\n"); break;
1326 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 printf("SetAliasInfo level %u failed - %s\n",
1329 levels[i], nt_errstr(status));
1330 ret = false;
1333 q.in.alias_handle = handle;
1334 q.in.level = levels[i];
1335 q.out.info = &info;
1337 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 printf("QueryAliasInfo level %u failed - %s\n",
1340 levels[i], nt_errstr(status));
1341 ret = false;
1345 return ret;
1348 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1349 struct policy_handle *user_handle)
1351 struct samr_GetGroupsForUser r;
1352 struct samr_RidWithAttributeArray *rids = NULL;
1353 NTSTATUS status;
1355 torture_comment(tctx, "testing GetGroupsForUser\n");
1357 r.in.user_handle = user_handle;
1358 r.out.rids = &rids;
1360 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1361 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1363 return true;
1367 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1368 struct lsa_String *domain_name)
1370 NTSTATUS status;
1371 struct samr_GetDomPwInfo r;
1372 struct samr_PwInfo info;
1374 r.in.domain_name = domain_name;
1375 r.out.info = &info;
1377 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1379 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1380 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1382 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1383 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1385 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1386 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1388 r.in.domain_name->string = "\\\\__NONAME__";
1389 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1391 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1392 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1394 r.in.domain_name->string = "\\\\Builtin";
1395 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1397 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1398 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1400 return true;
1403 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1404 struct policy_handle *handle)
1406 NTSTATUS status;
1407 struct samr_GetUserPwInfo r;
1408 struct samr_PwInfo info;
1410 torture_comment(tctx, "Testing GetUserPwInfo\n");
1412 r.in.user_handle = handle;
1413 r.out.info = &info;
1415 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1416 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1418 return true;
1421 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1422 struct policy_handle *domain_handle, const char *name,
1423 uint32_t *rid)
1425 NTSTATUS status;
1426 struct samr_LookupNames n;
1427 struct lsa_String sname[2];
1428 struct samr_Ids rids, types;
1430 init_lsa_String(&sname[0], name);
1432 n.in.domain_handle = domain_handle;
1433 n.in.num_names = 1;
1434 n.in.names = sname;
1435 n.out.rids = &rids;
1436 n.out.types = &types;
1437 status = dcerpc_samr_LookupNames(p, tctx, &n);
1438 if (NT_STATUS_IS_OK(status)) {
1439 *rid = n.out.rids->ids[0];
1440 } else {
1441 return status;
1444 init_lsa_String(&sname[1], "xxNONAMExx");
1445 n.in.num_names = 2;
1446 status = dcerpc_samr_LookupNames(p, tctx, &n);
1447 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1448 printf("LookupNames[2] failed - %s\n", nt_errstr(status));
1449 if (NT_STATUS_IS_OK(status)) {
1450 return NT_STATUS_UNSUCCESSFUL;
1452 return status;
1455 n.in.num_names = 0;
1456 status = dcerpc_samr_LookupNames(p, tctx, &n);
1457 if (!NT_STATUS_IS_OK(status)) {
1458 printf("LookupNames[0] failed - %s\n", nt_errstr(status));
1459 return status;
1462 init_lsa_String(&sname[0], "xxNONAMExx");
1463 n.in.num_names = 1;
1464 status = dcerpc_samr_LookupNames(p, tctx, &n);
1465 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1466 printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1467 if (NT_STATUS_IS_OK(status)) {
1468 return NT_STATUS_UNSUCCESSFUL;
1470 return status;
1473 init_lsa_String(&sname[0], "xxNONAMExx");
1474 init_lsa_String(&sname[1], "xxNONAME2xx");
1475 n.in.num_names = 2;
1476 status = dcerpc_samr_LookupNames(p, tctx, &n);
1477 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1478 printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1479 if (NT_STATUS_IS_OK(status)) {
1480 return NT_STATUS_UNSUCCESSFUL;
1482 return status;
1485 return NT_STATUS_OK;
1488 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1489 struct policy_handle *domain_handle,
1490 const char *name, struct policy_handle *user_handle)
1492 NTSTATUS status;
1493 struct samr_OpenUser r;
1494 uint32_t rid;
1496 status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 return status;
1501 r.in.domain_handle = domain_handle;
1502 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1503 r.in.rid = rid;
1504 r.out.user_handle = user_handle;
1505 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
1506 if (!NT_STATUS_IS_OK(status)) {
1507 printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1510 return status;
1513 #if 0
1514 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1515 struct policy_handle *handle)
1517 NTSTATUS status;
1518 struct samr_ChangePasswordUser r;
1519 bool ret = true;
1520 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1521 struct policy_handle user_handle;
1522 char *oldpass = "test";
1523 char *newpass = "test2";
1524 uint8_t old_nt_hash[16], new_nt_hash[16];
1525 uint8_t old_lm_hash[16], new_lm_hash[16];
1527 status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 return false;
1532 printf("Testing ChangePasswordUser for user 'testuser'\n");
1534 printf("old password: %s\n", oldpass);
1535 printf("new password: %s\n", newpass);
1537 E_md4hash(oldpass, old_nt_hash);
1538 E_md4hash(newpass, new_nt_hash);
1539 E_deshash(oldpass, old_lm_hash);
1540 E_deshash(newpass, new_lm_hash);
1542 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1543 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1544 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1545 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1546 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1547 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1549 r.in.handle = &user_handle;
1550 r.in.lm_present = 1;
1551 r.in.old_lm_crypted = &hash1;
1552 r.in.new_lm_crypted = &hash2;
1553 r.in.nt_present = 1;
1554 r.in.old_nt_crypted = &hash3;
1555 r.in.new_nt_crypted = &hash4;
1556 r.in.cross1_present = 1;
1557 r.in.nt_cross = &hash5;
1558 r.in.cross2_present = 1;
1559 r.in.lm_cross = &hash6;
1561 status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1562 if (!NT_STATUS_IS_OK(status)) {
1563 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1564 ret = false;
1567 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
1568 ret = false;
1571 return ret;
1573 #endif
1575 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1576 const char *acct_name,
1577 struct policy_handle *handle, char **password)
1579 NTSTATUS status;
1580 struct samr_ChangePasswordUser r;
1581 bool ret = true;
1582 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1583 struct policy_handle user_handle;
1584 char *oldpass;
1585 uint8_t old_nt_hash[16], new_nt_hash[16];
1586 uint8_t old_lm_hash[16], new_lm_hash[16];
1587 bool changed = true;
1589 char *newpass;
1590 struct samr_GetUserPwInfo pwp;
1591 struct samr_PwInfo info;
1592 int policy_min_pw_len = 0;
1594 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1595 if (!NT_STATUS_IS_OK(status)) {
1596 return false;
1598 pwp.in.user_handle = &user_handle;
1599 pwp.out.info = &info;
1601 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1602 if (NT_STATUS_IS_OK(status)) {
1603 policy_min_pw_len = pwp.out.info->min_password_length;
1605 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1607 torture_comment(tctx, "Testing ChangePasswordUser\n");
1609 torture_assert(tctx, *password != NULL,
1610 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1612 oldpass = *password;
1614 E_md4hash(oldpass, old_nt_hash);
1615 E_md4hash(newpass, new_nt_hash);
1616 E_deshash(oldpass, old_lm_hash);
1617 E_deshash(newpass, new_lm_hash);
1619 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1620 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1621 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1622 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1623 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1624 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1626 r.in.user_handle = &user_handle;
1627 r.in.lm_present = 1;
1628 /* Break the LM hash */
1629 hash1.hash[0]++;
1630 r.in.old_lm_crypted = &hash1;
1631 r.in.new_lm_crypted = &hash2;
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 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1644 /* Unbreak the LM hash */
1645 hash1.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 /* Break the NT hash */
1652 hash3.hash[0]--;
1653 r.in.nt_present = 1;
1654 r.in.old_nt_crypted = &hash3;
1655 r.in.new_nt_crypted = &hash4;
1656 r.in.cross1_present = 1;
1657 r.in.nt_cross = &hash5;
1658 r.in.cross2_present = 1;
1659 r.in.lm_cross = &hash6;
1661 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1662 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1663 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1665 /* Unbreak the NT hash */
1666 hash3.hash[0]--;
1668 r.in.user_handle = &user_handle;
1669 r.in.lm_present = 1;
1670 r.in.old_lm_crypted = &hash1;
1671 r.in.new_lm_crypted = &hash2;
1672 r.in.nt_present = 1;
1673 r.in.old_nt_crypted = &hash3;
1674 r.in.new_nt_crypted = &hash4;
1675 r.in.cross1_present = 1;
1676 r.in.nt_cross = &hash5;
1677 r.in.cross2_present = 1;
1678 /* Break the LM cross */
1679 hash6.hash[0]++;
1680 r.in.lm_cross = &hash6;
1682 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1683 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1684 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1685 ret = false;
1688 /* Unbreak the LM cross */
1689 hash6.hash[0]--;
1691 r.in.user_handle = &user_handle;
1692 r.in.lm_present = 1;
1693 r.in.old_lm_crypted = &hash1;
1694 r.in.new_lm_crypted = &hash2;
1695 r.in.nt_present = 1;
1696 r.in.old_nt_crypted = &hash3;
1697 r.in.new_nt_crypted = &hash4;
1698 r.in.cross1_present = 1;
1699 /* Break the NT cross */
1700 hash5.hash[0]++;
1701 r.in.nt_cross = &hash5;
1702 r.in.cross2_present = 1;
1703 r.in.lm_cross = &hash6;
1705 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1706 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1707 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1708 ret = false;
1711 /* Unbreak the NT cross */
1712 hash5.hash[0]--;
1715 /* Reset the hashes to not broken values */
1716 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1717 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1718 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1719 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1720 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1721 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1723 r.in.user_handle = &user_handle;
1724 r.in.lm_present = 1;
1725 r.in.old_lm_crypted = &hash1;
1726 r.in.new_lm_crypted = &hash2;
1727 r.in.nt_present = 1;
1728 r.in.old_nt_crypted = &hash3;
1729 r.in.new_nt_crypted = &hash4;
1730 r.in.cross1_present = 1;
1731 r.in.nt_cross = &hash5;
1732 r.in.cross2_present = 0;
1733 r.in.lm_cross = NULL;
1735 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1736 if (NT_STATUS_IS_OK(status)) {
1737 changed = true;
1738 *password = newpass;
1739 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1740 printf("ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1741 ret = false;
1744 oldpass = newpass;
1745 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1747 E_md4hash(oldpass, old_nt_hash);
1748 E_md4hash(newpass, new_nt_hash);
1749 E_deshash(oldpass, old_lm_hash);
1750 E_deshash(newpass, new_lm_hash);
1753 /* Reset the hashes to not broken values */
1754 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1755 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1756 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1757 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1758 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1759 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1761 r.in.user_handle = &user_handle;
1762 r.in.lm_present = 1;
1763 r.in.old_lm_crypted = &hash1;
1764 r.in.new_lm_crypted = &hash2;
1765 r.in.nt_present = 1;
1766 r.in.old_nt_crypted = &hash3;
1767 r.in.new_nt_crypted = &hash4;
1768 r.in.cross1_present = 0;
1769 r.in.nt_cross = NULL;
1770 r.in.cross2_present = 1;
1771 r.in.lm_cross = &hash6;
1773 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1774 if (NT_STATUS_IS_OK(status)) {
1775 changed = true;
1776 *password = newpass;
1777 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1778 printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1779 ret = false;
1782 oldpass = newpass;
1783 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1785 E_md4hash(oldpass, old_nt_hash);
1786 E_md4hash(newpass, new_nt_hash);
1787 E_deshash(oldpass, old_lm_hash);
1788 E_deshash(newpass, new_lm_hash);
1791 /* Reset the hashes to not broken values */
1792 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1793 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1794 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1795 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1796 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1797 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1799 r.in.user_handle = &user_handle;
1800 r.in.lm_present = 1;
1801 r.in.old_lm_crypted = &hash1;
1802 r.in.new_lm_crypted = &hash2;
1803 r.in.nt_present = 1;
1804 r.in.old_nt_crypted = &hash3;
1805 r.in.new_nt_crypted = &hash4;
1806 r.in.cross1_present = 1;
1807 r.in.nt_cross = &hash5;
1808 r.in.cross2_present = 1;
1809 r.in.lm_cross = &hash6;
1811 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1812 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1813 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1814 } else if (!NT_STATUS_IS_OK(status)) {
1815 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1816 ret = false;
1817 } else {
1818 changed = true;
1819 *password = newpass;
1822 r.in.user_handle = &user_handle;
1823 r.in.lm_present = 1;
1824 r.in.old_lm_crypted = &hash1;
1825 r.in.new_lm_crypted = &hash2;
1826 r.in.nt_present = 1;
1827 r.in.old_nt_crypted = &hash3;
1828 r.in.new_nt_crypted = &hash4;
1829 r.in.cross1_present = 1;
1830 r.in.nt_cross = &hash5;
1831 r.in.cross2_present = 1;
1832 r.in.lm_cross = &hash6;
1834 if (changed) {
1835 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1836 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1837 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1838 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1839 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1840 ret = false;
1845 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1846 ret = false;
1849 return ret;
1853 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1854 const char *acct_name,
1855 struct policy_handle *handle, char **password)
1857 NTSTATUS status;
1858 struct samr_OemChangePasswordUser2 r;
1859 bool ret = true;
1860 struct samr_Password lm_verifier;
1861 struct samr_CryptPassword lm_pass;
1862 struct lsa_AsciiString server, account, account_bad;
1863 char *oldpass;
1864 char *newpass;
1865 uint8_t old_lm_hash[16], new_lm_hash[16];
1867 struct samr_GetDomPwInfo dom_pw_info;
1868 struct samr_PwInfo info;
1869 int policy_min_pw_len = 0;
1871 struct lsa_String domain_name;
1873 domain_name.string = "";
1874 dom_pw_info.in.domain_name = &domain_name;
1875 dom_pw_info.out.info = &info;
1877 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1879 torture_assert(tctx, *password != NULL,
1880 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1882 oldpass = *password;
1884 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1885 if (NT_STATUS_IS_OK(status)) {
1886 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1889 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1891 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1892 account.string = acct_name;
1894 E_deshash(oldpass, old_lm_hash);
1895 E_deshash(newpass, new_lm_hash);
1897 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1898 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1899 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1901 r.in.server = &server;
1902 r.in.account = &account;
1903 r.in.password = &lm_pass;
1904 r.in.hash = &lm_verifier;
1906 /* Break the verification */
1907 lm_verifier.hash[0]++;
1909 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1911 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1912 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1913 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1914 nt_errstr(status));
1915 ret = false;
1918 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1919 /* Break the old password */
1920 old_lm_hash[0]++;
1921 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1922 /* unbreak it for the next operation */
1923 old_lm_hash[0]--;
1924 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1926 r.in.server = &server;
1927 r.in.account = &account;
1928 r.in.password = &lm_pass;
1929 r.in.hash = &lm_verifier;
1931 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1933 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1934 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1935 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1936 nt_errstr(status));
1937 ret = false;
1940 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1941 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1943 r.in.server = &server;
1944 r.in.account = &account;
1945 r.in.password = &lm_pass;
1946 r.in.hash = NULL;
1948 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1950 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1951 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1952 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1953 nt_errstr(status));
1954 ret = false;
1957 /* This shouldn't be a valid name */
1958 account_bad.string = TEST_ACCOUNT_NAME "XX";
1959 r.in.account = &account_bad;
1961 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1963 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1964 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1965 nt_errstr(status));
1966 ret = false;
1969 /* This shouldn't be a valid name */
1970 account_bad.string = TEST_ACCOUNT_NAME "XX";
1971 r.in.account = &account_bad;
1972 r.in.password = &lm_pass;
1973 r.in.hash = &lm_verifier;
1975 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1977 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1978 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1979 nt_errstr(status));
1980 ret = false;
1983 /* This shouldn't be a valid name */
1984 account_bad.string = TEST_ACCOUNT_NAME "XX";
1985 r.in.account = &account_bad;
1986 r.in.password = NULL;
1987 r.in.hash = &lm_verifier;
1989 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1991 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1992 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
1993 nt_errstr(status));
1994 ret = false;
1997 E_deshash(oldpass, old_lm_hash);
1998 E_deshash(newpass, new_lm_hash);
2000 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2001 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2002 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2004 r.in.server = &server;
2005 r.in.account = &account;
2006 r.in.password = &lm_pass;
2007 r.in.hash = &lm_verifier;
2009 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
2010 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2011 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2012 } else if (!NT_STATUS_IS_OK(status)) {
2013 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
2014 ret = false;
2015 } else {
2016 *password = newpass;
2019 return ret;
2023 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2024 const char *acct_name,
2025 char **password,
2026 char *newpass, bool allow_password_restriction)
2028 NTSTATUS status;
2029 struct samr_ChangePasswordUser2 r;
2030 bool ret = true;
2031 struct lsa_String server, account;
2032 struct samr_CryptPassword nt_pass, lm_pass;
2033 struct samr_Password nt_verifier, lm_verifier;
2034 char *oldpass;
2035 uint8_t old_nt_hash[16], new_nt_hash[16];
2036 uint8_t old_lm_hash[16], new_lm_hash[16];
2038 struct samr_GetDomPwInfo dom_pw_info;
2039 struct samr_PwInfo info;
2041 struct lsa_String domain_name;
2043 domain_name.string = "";
2044 dom_pw_info.in.domain_name = &domain_name;
2045 dom_pw_info.out.info = &info;
2047 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2049 torture_assert(tctx, *password != NULL,
2050 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2051 oldpass = *password;
2053 if (!newpass) {
2054 int policy_min_pw_len = 0;
2055 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
2056 if (NT_STATUS_IS_OK(status)) {
2057 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2060 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2063 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2064 init_lsa_String(&account, acct_name);
2066 E_md4hash(oldpass, old_nt_hash);
2067 E_md4hash(newpass, new_nt_hash);
2069 E_deshash(oldpass, old_lm_hash);
2070 E_deshash(newpass, new_lm_hash);
2072 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2073 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2074 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2076 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2077 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2078 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2080 r.in.server = &server;
2081 r.in.account = &account;
2082 r.in.nt_password = &nt_pass;
2083 r.in.nt_verifier = &nt_verifier;
2084 r.in.lm_change = 1;
2085 r.in.lm_password = &lm_pass;
2086 r.in.lm_verifier = &lm_verifier;
2088 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
2089 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2090 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2091 } else if (!NT_STATUS_IS_OK(status)) {
2092 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2093 ret = false;
2094 } else {
2095 *password = newpass;
2098 return ret;
2102 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2103 const char *account_string,
2104 int policy_min_pw_len,
2105 char **password,
2106 const char *newpass,
2107 NTTIME last_password_change,
2108 bool handle_reject_reason)
2110 NTSTATUS status;
2111 struct samr_ChangePasswordUser3 r;
2112 bool ret = true;
2113 struct lsa_String server, account, account_bad;
2114 struct samr_CryptPassword nt_pass, lm_pass;
2115 struct samr_Password nt_verifier, lm_verifier;
2116 char *oldpass;
2117 uint8_t old_nt_hash[16], new_nt_hash[16];
2118 uint8_t old_lm_hash[16], new_lm_hash[16];
2119 NTTIME t;
2120 struct samr_DomInfo1 *dominfo = NULL;
2121 struct samr_ChangeReject *reject = NULL;
2123 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2125 if (newpass == NULL) {
2126 do {
2127 if (policy_min_pw_len == 0) {
2128 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2129 } else {
2130 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2132 } while (check_password_quality(newpass) == false);
2133 } else {
2134 torture_comment(tctx, "Using password '%s'\n", newpass);
2137 torture_assert(tctx, *password != NULL,
2138 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2140 oldpass = *password;
2141 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2142 init_lsa_String(&account, account_string);
2144 E_md4hash(oldpass, old_nt_hash);
2145 E_md4hash(newpass, new_nt_hash);
2147 E_deshash(oldpass, old_lm_hash);
2148 E_deshash(newpass, new_lm_hash);
2150 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2151 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2152 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2154 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2155 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2156 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2158 /* Break the verification */
2159 nt_verifier.hash[0]++;
2161 r.in.server = &server;
2162 r.in.account = &account;
2163 r.in.nt_password = &nt_pass;
2164 r.in.nt_verifier = &nt_verifier;
2165 r.in.lm_change = 1;
2166 r.in.lm_password = &lm_pass;
2167 r.in.lm_verifier = &lm_verifier;
2168 r.in.password3 = NULL;
2169 r.out.dominfo = &dominfo;
2170 r.out.reject = &reject;
2172 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2173 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2174 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2175 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2176 nt_errstr(status));
2177 ret = false;
2180 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2181 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2182 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2184 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2185 /* Break the NT hash */
2186 old_nt_hash[0]++;
2187 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2188 /* Unbreak it again */
2189 old_nt_hash[0]--;
2190 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2192 r.in.server = &server;
2193 r.in.account = &account;
2194 r.in.nt_password = &nt_pass;
2195 r.in.nt_verifier = &nt_verifier;
2196 r.in.lm_change = 1;
2197 r.in.lm_password = &lm_pass;
2198 r.in.lm_verifier = &lm_verifier;
2199 r.in.password3 = NULL;
2200 r.out.dominfo = &dominfo;
2201 r.out.reject = &reject;
2203 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2204 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2205 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2206 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2207 nt_errstr(status));
2208 ret = false;
2211 /* This shouldn't be a valid name */
2212 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2214 r.in.account = &account_bad;
2215 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2216 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2217 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2218 nt_errstr(status));
2219 ret = false;
2222 E_md4hash(oldpass, old_nt_hash);
2223 E_md4hash(newpass, new_nt_hash);
2225 E_deshash(oldpass, old_lm_hash);
2226 E_deshash(newpass, new_lm_hash);
2228 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2229 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2230 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2232 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2233 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2234 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2236 r.in.server = &server;
2237 r.in.account = &account;
2238 r.in.nt_password = &nt_pass;
2239 r.in.nt_verifier = &nt_verifier;
2240 r.in.lm_change = 1;
2241 r.in.lm_password = &lm_pass;
2242 r.in.lm_verifier = &lm_verifier;
2243 r.in.password3 = NULL;
2244 r.out.dominfo = &dominfo;
2245 r.out.reject = &reject;
2247 unix_to_nt_time(&t, time(NULL));
2249 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2251 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2252 && dominfo
2253 && reject
2254 && handle_reject_reason
2255 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2256 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2258 if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
2259 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2260 SAMR_REJECT_OTHER, reject->reason);
2261 return false;
2265 /* We tested the order of precendence which is as follows:
2267 * pwd min_age
2268 * pwd length
2269 * pwd complexity
2270 * pwd history
2272 Guenther */
2274 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2275 (last_password_change + dominfo->min_password_age > t)) {
2277 if (reject->reason != SAMR_REJECT_OTHER) {
2278 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2279 SAMR_REJECT_OTHER, reject->reason);
2280 return false;
2283 } else if ((dominfo->min_password_length > 0) &&
2284 (strlen(newpass) < dominfo->min_password_length)) {
2286 if (reject->reason != SAMR_REJECT_TOO_SHORT) {
2287 printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
2288 SAMR_REJECT_TOO_SHORT, reject->reason);
2289 return false;
2292 } else if ((dominfo->password_history_length > 0) &&
2293 strequal(oldpass, newpass)) {
2295 if (reject->reason != SAMR_REJECT_IN_HISTORY) {
2296 printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
2297 SAMR_REJECT_IN_HISTORY, reject->reason);
2298 return false;
2300 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2302 if (reject->reason != SAMR_REJECT_COMPLEXITY) {
2303 printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
2304 SAMR_REJECT_COMPLEXITY, reject->reason);
2305 return false;
2310 if (reject->reason == SAMR_REJECT_TOO_SHORT) {
2311 /* retry with adjusted size */
2312 return test_ChangePasswordUser3(p, tctx, account_string,
2313 dominfo->min_password_length,
2314 password, NULL, 0, false);
2318 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2319 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2320 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2321 SAMR_REJECT_OTHER, reject->reason);
2322 return false;
2324 /* Perhaps the server has a 'min password age' set? */
2326 } else {
2327 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2328 *password = talloc_strdup(tctx, newpass);
2331 return ret;
2334 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2335 const char *account_string,
2336 struct policy_handle *handle,
2337 char **password)
2339 NTSTATUS status;
2340 struct samr_ChangePasswordUser3 r;
2341 struct samr_SetUserInfo s;
2342 union samr_UserInfo u;
2343 DATA_BLOB session_key;
2344 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2345 uint8_t confounder[16];
2346 struct MD5Context ctx;
2348 bool ret = true;
2349 struct lsa_String server, account;
2350 struct samr_CryptPassword nt_pass;
2351 struct samr_Password nt_verifier;
2352 DATA_BLOB new_random_pass;
2353 char *newpass;
2354 char *oldpass;
2355 uint8_t old_nt_hash[16], new_nt_hash[16];
2356 NTTIME t;
2357 struct samr_DomInfo1 *dominfo = NULL;
2358 struct samr_ChangeReject *reject = NULL;
2360 new_random_pass = samr_very_rand_pass(tctx, 128);
2362 torture_assert(tctx, *password != NULL,
2363 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2365 oldpass = *password;
2366 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2367 init_lsa_String(&account, account_string);
2369 s.in.user_handle = handle;
2370 s.in.info = &u;
2371 s.in.level = 25;
2373 ZERO_STRUCT(u);
2375 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2377 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2379 status = dcerpc_fetch_session_key(p, &session_key);
2380 if (!NT_STATUS_IS_OK(status)) {
2381 printf("SetUserInfo level %u - no session key - %s\n",
2382 s.in.level, nt_errstr(status));
2383 return false;
2386 generate_random_buffer((uint8_t *)confounder, 16);
2388 MD5Init(&ctx);
2389 MD5Update(&ctx, confounder, 16);
2390 MD5Update(&ctx, session_key.data, session_key.length);
2391 MD5Final(confounded_session_key.data, &ctx);
2393 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2394 memcpy(&u.info25.password.data[516], confounder, 16);
2396 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2398 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2399 if (!NT_STATUS_IS_OK(status)) {
2400 printf("SetUserInfo level %u failed - %s\n",
2401 s.in.level, nt_errstr(status));
2402 ret = false;
2405 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2407 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2409 new_random_pass = samr_very_rand_pass(tctx, 128);
2411 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2413 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2414 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2415 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2417 r.in.server = &server;
2418 r.in.account = &account;
2419 r.in.nt_password = &nt_pass;
2420 r.in.nt_verifier = &nt_verifier;
2421 r.in.lm_change = 0;
2422 r.in.lm_password = NULL;
2423 r.in.lm_verifier = NULL;
2424 r.in.password3 = NULL;
2425 r.out.dominfo = &dominfo;
2426 r.out.reject = &reject;
2428 unix_to_nt_time(&t, time(NULL));
2430 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2432 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2433 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2434 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2435 SAMR_REJECT_OTHER, reject->reason);
2436 return false;
2438 /* Perhaps the server has a 'min password age' set? */
2440 } else if (!NT_STATUS_IS_OK(status)) {
2441 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2442 ret = false;
2445 newpass = samr_rand_pass(tctx, 128);
2447 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2449 E_md4hash(newpass, new_nt_hash);
2451 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2452 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2453 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2455 r.in.server = &server;
2456 r.in.account = &account;
2457 r.in.nt_password = &nt_pass;
2458 r.in.nt_verifier = &nt_verifier;
2459 r.in.lm_change = 0;
2460 r.in.lm_password = NULL;
2461 r.in.lm_verifier = NULL;
2462 r.in.password3 = NULL;
2463 r.out.dominfo = &dominfo;
2464 r.out.reject = &reject;
2466 unix_to_nt_time(&t, time(NULL));
2468 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2470 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2471 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2472 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2473 SAMR_REJECT_OTHER, reject->reason);
2474 return false;
2476 /* Perhaps the server has a 'min password age' set? */
2478 } else {
2479 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2480 *password = talloc_strdup(tctx, newpass);
2483 return ret;
2487 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2488 struct policy_handle *alias_handle)
2490 struct samr_GetMembersInAlias r;
2491 struct lsa_SidArray sids;
2492 NTSTATUS status;
2494 torture_comment(tctx, "Testing GetMembersInAlias\n");
2496 r.in.alias_handle = alias_handle;
2497 r.out.sids = &sids;
2499 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2500 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2502 return true;
2505 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2506 struct policy_handle *alias_handle,
2507 const struct dom_sid *domain_sid)
2509 struct samr_AddAliasMember r;
2510 struct samr_DeleteAliasMember d;
2511 NTSTATUS status;
2512 struct dom_sid *sid;
2514 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2516 torture_comment(tctx, "testing AddAliasMember\n");
2517 r.in.alias_handle = alias_handle;
2518 r.in.sid = sid;
2520 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2521 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2523 d.in.alias_handle = alias_handle;
2524 d.in.sid = sid;
2526 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2527 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2529 return true;
2532 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2533 struct policy_handle *alias_handle)
2535 struct samr_AddMultipleMembersToAlias a;
2536 struct samr_RemoveMultipleMembersFromAlias r;
2537 NTSTATUS status;
2538 struct lsa_SidArray sids;
2540 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2541 a.in.alias_handle = alias_handle;
2542 a.in.sids = &sids;
2544 sids.num_sids = 3;
2545 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2547 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2548 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2549 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2551 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2552 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2555 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2556 r.in.alias_handle = alias_handle;
2557 r.in.sids = &sids;
2559 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2560 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2562 /* strange! removing twice doesn't give any error */
2563 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2564 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2566 /* but removing an alias that isn't there does */
2567 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2569 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2570 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2572 return true;
2575 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2576 struct policy_handle *user_handle)
2578 struct samr_TestPrivateFunctionsUser r;
2579 NTSTATUS status;
2581 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2583 r.in.user_handle = user_handle;
2585 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2586 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2588 return true;
2591 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2592 struct torture_context *tctx,
2593 struct policy_handle *handle,
2594 bool use_info2,
2595 NTTIME *pwdlastset)
2597 NTSTATUS status;
2598 uint16_t levels[] = { /* 3, */ 5, 21 };
2599 int i;
2600 NTTIME pwdlastset3 = 0;
2601 NTTIME pwdlastset5 = 0;
2602 NTTIME pwdlastset21 = 0;
2604 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2605 use_info2 ? "2":"");
2607 for (i=0; i<ARRAY_SIZE(levels); i++) {
2609 struct samr_QueryUserInfo r;
2610 struct samr_QueryUserInfo2 r2;
2611 union samr_UserInfo *info;
2613 if (use_info2) {
2614 r2.in.user_handle = handle;
2615 r2.in.level = levels[i];
2616 r2.out.info = &info;
2617 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2619 } else {
2620 r.in.user_handle = handle;
2621 r.in.level = levels[i];
2622 r.out.info = &info;
2623 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2626 if (!NT_STATUS_IS_OK(status) &&
2627 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2628 printf("QueryUserInfo%s level %u failed - %s\n",
2629 use_info2 ? "2":"", levels[i], nt_errstr(status));
2630 return false;
2633 switch (levels[i]) {
2634 case 3:
2635 pwdlastset3 = info->info3.last_password_change;
2636 break;
2637 case 5:
2638 pwdlastset5 = info->info5.last_password_change;
2639 break;
2640 case 21:
2641 pwdlastset21 = info->info21.last_password_change;
2642 break;
2643 default:
2644 return false;
2647 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2648 "pwdlastset mixup"); */
2649 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2650 "pwdlastset mixup");
2652 *pwdlastset = pwdlastset21;
2654 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2656 return true;
2659 static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *tctx,
2660 struct cli_credentials *machine_credentials,
2661 struct cli_credentials *test_credentials,
2662 struct creds_CredentialState *creds,
2663 NTSTATUS expected_result)
2665 NTSTATUS status;
2666 struct netr_LogonSamLogon r;
2667 struct netr_Authenticator auth, auth2;
2668 union netr_LogonLevel logon;
2669 union netr_Validation validation;
2670 uint8_t authoritative;
2671 struct netr_NetworkInfo ninfo;
2672 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2673 int flags = CLI_CRED_NTLM_AUTH;
2675 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2676 flags |= CLI_CRED_LANMAN_AUTH;
2679 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2680 flags |= CLI_CRED_NTLMv2_AUTH;
2683 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2684 &ninfo.identity_info.account_name.string,
2685 &ninfo.identity_info.domain_name.string);
2687 generate_random_buffer(ninfo.challenge,
2688 sizeof(ninfo.challenge));
2689 chal = data_blob_const(ninfo.challenge,
2690 sizeof(ninfo.challenge));
2692 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(machine_credentials),
2693 cli_credentials_get_domain(machine_credentials));
2695 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2696 &flags,
2697 chal,
2698 names_blob,
2699 &lm_resp, &nt_resp,
2700 NULL, NULL);
2701 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2703 ninfo.lm.data = lm_resp.data;
2704 ninfo.lm.length = lm_resp.length;
2706 ninfo.nt.data = nt_resp.data;
2707 ninfo.nt.length = nt_resp.length;
2709 ninfo.identity_info.parameter_control =
2710 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2711 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2712 ninfo.identity_info.logon_id_low = 0;
2713 ninfo.identity_info.logon_id_high = 0;
2714 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(machine_credentials);
2716 logon.network = &ninfo;
2718 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2719 r.in.computer_name = cli_credentials_get_workstation(machine_credentials);
2720 r.in.credential = &auth;
2721 r.in.return_authenticator = &auth2;
2722 r.in.logon_level = 2;
2723 r.in.logon = &logon;
2724 r.out.validation = &validation;
2725 r.out.authoritative = &authoritative;
2727 d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
2729 ZERO_STRUCT(auth2);
2730 creds_client_authenticator(creds, &auth);
2732 r.in.validation_level = 2;
2734 status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
2735 if (!NT_STATUS_IS_OK(status)) {
2736 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogon failed");
2737 return true;
2738 } else {
2739 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
2742 torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred),
2743 "Credential chaining failed");
2745 return true;
2748 static bool test_SamLogon(struct torture_context *tctx,
2749 struct dcerpc_pipe *p,
2750 struct cli_credentials *machine_credentials,
2751 struct cli_credentials *test_credentials,
2752 NTSTATUS expected_result)
2754 struct creds_CredentialState *creds;
2756 if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
2757 return false;
2760 return test_SamLogon_Creds(p, tctx, machine_credentials, test_credentials,
2761 creds, expected_result);
2764 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2765 struct dcerpc_pipe *p,
2766 struct cli_credentials *machine_creds,
2767 const char *acct_name,
2768 char *password,
2769 NTSTATUS expected_samlogon_result)
2771 bool ret = true;
2772 struct cli_credentials *test_credentials;
2774 test_credentials = cli_credentials_init(tctx);
2776 cli_credentials_set_workstation(test_credentials,
2777 TEST_ACCOUNT_NAME_PWD, CRED_SPECIFIED);
2778 cli_credentials_set_domain(test_credentials,
2779 lp_workgroup(tctx->lp_ctx), CRED_SPECIFIED);
2780 cli_credentials_set_username(test_credentials,
2781 acct_name, CRED_SPECIFIED);
2782 cli_credentials_set_password(test_credentials,
2783 password, CRED_SPECIFIED);
2784 cli_credentials_set_secure_channel_type(test_credentials, SEC_CHAN_BDC);
2786 printf("testing samlogon as %s@%s password: %s\n",
2787 acct_name, TEST_ACCOUNT_NAME_PWD, password);
2789 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
2790 expected_samlogon_result)) {
2791 torture_warning(tctx, "new password did not work\n");
2792 ret = false;
2795 return ret;
2798 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2799 struct dcerpc_pipe *np,
2800 struct torture_context *tctx,
2801 struct policy_handle *handle,
2802 uint16_t level,
2803 uint32_t fields_present,
2804 uint8_t password_expired,
2805 bool *matched_expected_error,
2806 bool use_setinfo2,
2807 const char *acct_name,
2808 char **password,
2809 struct cli_credentials *machine_creds,
2810 bool use_queryinfo2,
2811 NTTIME *pwdlastset,
2812 NTSTATUS expected_samlogon_result)
2814 const char *fields = NULL;
2815 bool ret = true;
2817 switch (level) {
2818 case 21:
2819 case 23:
2820 case 25:
2821 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2822 fields_present);
2823 break;
2824 default:
2825 break;
2828 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2829 "(password_expired: %d) %s\n",
2830 use_setinfo2 ? "2":"", level, password_expired,
2831 fields ? fields : "");
2833 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2834 fields_present,
2835 password,
2836 password_expired,
2837 use_setinfo2,
2838 matched_expected_error)) {
2839 ret = false;
2842 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2843 use_queryinfo2,
2844 pwdlastset)) {
2845 ret = false;
2848 if (*matched_expected_error == true) {
2849 return ret;
2852 if (!test_SamLogon_with_creds(tctx, np,
2853 machine_creds,
2854 acct_name,
2855 *password,
2856 expected_samlogon_result)) {
2857 ret = false;
2860 return ret;
2863 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2864 struct torture_context *tctx,
2865 uint32_t acct_flags,
2866 const char *acct_name,
2867 struct policy_handle *handle,
2868 char **password,
2869 struct cli_credentials *machine_credentials)
2871 int s = 0, q = 0, f = 0, l = 0, z = 0;
2872 bool ret = true;
2873 int delay = 500000;
2874 bool set_levels[] = { false, true };
2875 bool query_levels[] = { false, true };
2876 uint32_t levels[] = { 18, 21, 23, 24, 25, 26 };
2877 uint32_t nonzeros[] = { 1, 24 };
2878 uint32_t fields_present[] = {
2880 SAMR_FIELD_EXPIRED_FLAG,
2881 SAMR_FIELD_LAST_PWD_CHANGE,
2882 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2883 SAMR_FIELD_COMMENT,
2884 SAMR_FIELD_NT_PASSWORD_PRESENT,
2885 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2886 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2887 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2888 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2889 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2890 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2892 NTSTATUS status;
2893 struct dcerpc_pipe *np = NULL;
2895 if (torture_setting_bool(tctx, "samba3", false)) {
2896 delay = 1000000;
2897 printf("Samba3 has second granularity, setting delay to: %d\n",
2898 delay);
2901 status = torture_rpc_connection(tctx, &np, &ndr_table_netlogon);
2902 if (!NT_STATUS_IS_OK(status)) {
2903 return false;
2906 /* set to 1 to enable testing for all possible opcode
2907 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2908 combinations */
2909 #if 0
2910 #define TEST_SET_LEVELS 1
2911 #define TEST_QUERY_LEVELS 1
2912 #endif
2913 for (l=0; l<ARRAY_SIZE(levels); l++) {
2914 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
2915 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2916 #ifdef TEST_SET_LEVELS
2917 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2918 #endif
2919 #ifdef TEST_QUERY_LEVELS
2920 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2921 #endif
2922 NTTIME pwdlastset_old = 0;
2923 NTTIME pwdlastset_new = 0;
2924 bool matched_expected_error = false;
2925 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
2927 torture_comment(tctx, "------------------------------\n"
2928 "Testing pwdLastSet attribute for flags: 0x%08x "
2929 "(s: %d (l: %d), q: %d)\n",
2930 acct_flags, s, levels[l], q);
2932 switch (levels[l]) {
2933 case 21:
2934 case 23:
2935 case 25:
2936 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2937 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
2938 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
2940 break;
2944 /* set #1 */
2946 /* set a password and force password change (pwdlastset 0) by
2947 * setting the password expired flag to a non-0 value */
2949 if (!test_SetPassword_level(p, np, tctx, handle,
2950 levels[l],
2951 fields_present[f],
2952 nonzeros[z],
2953 &matched_expected_error,
2954 set_levels[s],
2955 acct_name,
2956 password,
2957 machine_credentials,
2958 query_levels[q],
2959 &pwdlastset_old,
2960 expected_samlogon_result)) {
2961 ret = false;
2964 if (matched_expected_error == true) {
2965 /* skipping on expected failure */
2966 continue;
2969 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2970 * set without the SAMR_FIELD_EXPIRED_FLAG */
2972 switch (levels[l]) {
2973 case 21:
2974 case 23:
2975 case 25:
2976 if ((pwdlastset_new != 0) &&
2977 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
2978 torture_comment(tctx, "not considering a non-0 "
2979 "pwdLastSet as a an error as the "
2980 "SAMR_FIELD_EXPIRED_FLAG has not "
2981 "been set\n");
2982 break;
2984 default:
2985 if (pwdlastset_new != 0) {
2986 torture_warning(tctx, "pwdLastSet test failed: "
2987 "expected pwdLastSet 0 but got %lld\n",
2988 pwdlastset_old);
2989 ret = false;
2991 break;
2994 switch (levels[l]) {
2995 case 21:
2996 case 23:
2997 case 25:
2998 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2999 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3000 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3001 (pwdlastset_old >= pwdlastset_new)) {
3002 torture_warning(tctx, "pwdlastset not increasing\n");
3003 ret = false;
3005 break;
3006 default:
3007 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3008 (pwdlastset_old >= pwdlastset_new)) {
3009 torture_warning(tctx, "pwdlastset not increasing\n");
3010 ret = false;
3012 break;
3015 usleep(delay);
3017 /* set #2 */
3019 /* set a password, pwdlastset needs to get updated (increased
3020 * value), password_expired value used here is 0 */
3022 if (!test_SetPassword_level(p, np, tctx, handle,
3023 levels[l],
3024 fields_present[f],
3026 &matched_expected_error,
3027 set_levels[s],
3028 acct_name,
3029 password,
3030 machine_credentials,
3031 query_levels[q],
3032 &pwdlastset_new,
3033 expected_samlogon_result)) {
3034 ret = false;
3037 /* when a password has been changed, pwdlastset must not be 0 afterwards
3038 * and must be larger then the old value */
3040 switch (levels[l]) {
3041 case 21:
3042 case 23:
3043 case 25:
3045 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3046 * password has been changed, old and new pwdlastset
3047 * need to be the same value */
3049 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3050 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3051 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3053 torture_assert_int_equal(tctx, pwdlastset_old,
3054 pwdlastset_new, "pwdlastset must be equal");
3055 break;
3057 default:
3058 if (pwdlastset_old >= pwdlastset_new) {
3059 torture_warning(tctx, "pwdLastSet test failed: "
3060 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3061 pwdlastset_old, pwdlastset_new);
3062 ret = false;
3064 if (pwdlastset_new == 0) {
3065 torture_warning(tctx, "pwdLastSet test failed: "
3066 "expected non-0 pwdlastset, got: %lld\n",
3067 pwdlastset_new);
3068 ret = false;
3072 switch (levels[l]) {
3073 case 21:
3074 case 23:
3075 case 25:
3076 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3077 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3078 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3079 (pwdlastset_old >= pwdlastset_new)) {
3080 torture_warning(tctx, "pwdlastset not increasing\n");
3081 ret = false;
3083 break;
3084 default:
3085 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3086 (pwdlastset_old >= pwdlastset_new)) {
3087 torture_warning(tctx, "pwdlastset not increasing\n");
3088 ret = false;
3090 break;
3093 pwdlastset_old = pwdlastset_new;
3095 usleep(delay);
3097 /* set #2b */
3099 /* set a password, pwdlastset needs to get updated (increased
3100 * value), password_expired value used here is 0 */
3102 if (!test_SetPassword_level(p, np, tctx, handle,
3103 levels[l],
3104 fields_present[f],
3106 &matched_expected_error,
3107 set_levels[s],
3108 acct_name,
3109 password,
3110 machine_credentials,
3111 query_levels[q],
3112 &pwdlastset_new,
3113 expected_samlogon_result)) {
3114 ret = false;
3117 /* when a password has been changed, pwdlastset must not be 0 afterwards
3118 * and must be larger then the old value */
3120 switch (levels[l]) {
3121 case 21:
3122 case 23:
3123 case 25:
3125 /* if no password has been changed, old and new pwdlastset
3126 * need to be the same value */
3128 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3129 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3131 torture_assert_int_equal(tctx, pwdlastset_old,
3132 pwdlastset_new, "pwdlastset must be equal");
3133 break;
3135 default:
3136 if (pwdlastset_old >= pwdlastset_new) {
3137 torture_warning(tctx, "pwdLastSet test failed: "
3138 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3139 pwdlastset_old, pwdlastset_new);
3140 ret = false;
3142 if (pwdlastset_new == 0) {
3143 torture_warning(tctx, "pwdLastSet test failed: "
3144 "expected non-0 pwdlastset, got: %lld\n",
3145 pwdlastset_new);
3146 ret = false;
3150 /* set #3 */
3152 /* set a password and force password change (pwdlastset 0) by
3153 * setting the password expired flag to a non-0 value */
3155 if (!test_SetPassword_level(p, np, tctx, handle,
3156 levels[l],
3157 fields_present[f],
3158 nonzeros[z],
3159 &matched_expected_error,
3160 set_levels[s],
3161 acct_name,
3162 password,
3163 machine_credentials,
3164 query_levels[q],
3165 &pwdlastset_new,
3166 expected_samlogon_result)) {
3167 ret = false;
3170 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3171 * set without the SAMR_FIELD_EXPIRED_FLAG */
3173 switch (levels[l]) {
3174 case 21:
3175 case 23:
3176 case 25:
3177 if ((pwdlastset_new != 0) &&
3178 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3179 torture_comment(tctx, "not considering a non-0 "
3180 "pwdLastSet as a an error as the "
3181 "SAMR_FIELD_EXPIRED_FLAG has not "
3182 "been set\n");
3183 break;
3186 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3187 * password has been changed, old and new pwdlastset
3188 * need to be the same value */
3190 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3191 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3192 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3194 torture_assert_int_equal(tctx, pwdlastset_old,
3195 pwdlastset_new, "pwdlastset must be equal");
3196 break;
3198 default:
3200 if (pwdlastset_old == pwdlastset_new) {
3201 torture_warning(tctx, "pwdLastSet test failed: "
3202 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3203 pwdlastset_old, pwdlastset_new);
3204 ret = false;
3207 if (pwdlastset_new != 0) {
3208 torture_warning(tctx, "pwdLastSet test failed: "
3209 "expected pwdLastSet 0, got %lld\n",
3210 pwdlastset_old);
3211 ret = false;
3213 break;
3216 switch (levels[l]) {
3217 case 21:
3218 case 23:
3219 case 25:
3220 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3221 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3222 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3223 (pwdlastset_old >= pwdlastset_new)) {
3224 torture_warning(tctx, "pwdlastset not increasing\n");
3225 ret = false;
3227 break;
3228 default:
3229 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3230 (pwdlastset_old >= pwdlastset_new)) {
3231 torture_warning(tctx, "pwdlastset not increasing\n");
3232 ret = false;
3234 break;
3237 /* if the level we are testing does not have a fields_present
3238 * field, skip all fields present tests by setting f to to
3239 * arraysize */
3240 switch (levels[l]) {
3241 case 18:
3242 case 24:
3243 case 26:
3244 f = ARRAY_SIZE(fields_present);
3245 break;
3248 #ifdef TEST_QUERY_LEVELS
3250 #endif
3251 #ifdef TEST_SET_LEVELS
3253 #endif
3254 } /* fields present */
3255 } /* nonzeros */
3256 } /* levels */
3258 #undef TEST_SET_LEVELS
3259 #undef TEST_QUERY_LEVELS
3261 return ret;
3264 static bool test_user_ops(struct dcerpc_pipe *p,
3265 struct torture_context *tctx,
3266 struct policy_handle *user_handle,
3267 struct policy_handle *domain_handle,
3268 uint32_t base_acct_flags,
3269 const char *base_acct_name, enum torture_samr_choice which_ops,
3270 struct cli_credentials *machine_credentials)
3272 char *password = NULL;
3273 struct samr_QueryUserInfo q;
3274 union samr_UserInfo *info;
3275 NTSTATUS status;
3277 bool ret = true;
3278 int i;
3279 uint32_t rid;
3280 const uint32_t password_fields[] = {
3281 SAMR_FIELD_NT_PASSWORD_PRESENT,
3282 SAMR_FIELD_LM_PASSWORD_PRESENT,
3283 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3287 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3288 if (!NT_STATUS_IS_OK(status)) {
3289 ret = false;
3292 switch (which_ops) {
3293 case TORTURE_SAMR_USER_ATTRIBUTES:
3294 if (!test_QuerySecurity(p, tctx, user_handle)) {
3295 ret = false;
3298 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3299 ret = false;
3302 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3303 ret = false;
3306 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3307 base_acct_name)) {
3308 ret = false;
3311 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3312 ret = false;
3315 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3316 ret = false;
3319 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3320 ret = false;
3322 break;
3323 case TORTURE_SAMR_PASSWORDS:
3324 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3325 char simple_pass[9];
3326 char *v = generate_random_str(tctx, 1);
3328 ZERO_STRUCT(simple_pass);
3329 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3331 printf("Testing machine account password policy rules\n");
3333 /* Workstation trust accounts don't seem to need to honour password quality policy */
3334 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3335 ret = false;
3338 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3339 ret = false;
3342 /* reset again, to allow another 'user' password change */
3343 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3344 ret = false;
3347 /* Try a 'short' password */
3348 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3349 ret = false;
3352 /* Try a compleatly random password */
3353 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3354 ret = false;
3358 for (i = 0; password_fields[i]; i++) {
3359 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3360 ret = false;
3363 /* check it was set right */
3364 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3365 ret = false;
3369 for (i = 0; password_fields[i]; i++) {
3370 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3371 ret = false;
3374 /* check it was set right */
3375 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3376 ret = false;
3380 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
3381 ret = false;
3384 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
3385 ret = false;
3388 if (torture_setting_bool(tctx, "samba4", false)) {
3389 printf("skipping Set Password level 18 and 21 against Samba4\n");
3390 } else {
3392 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
3393 ret = false;
3396 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3397 ret = false;
3400 for (i = 0; password_fields[i]; i++) {
3402 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
3403 /* we need to skip as that would break
3404 * the ChangePasswordUser3 verify */
3405 continue;
3408 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
3409 ret = false;
3412 /* check it was set right */
3413 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3414 ret = false;
3419 q.in.user_handle = user_handle;
3420 q.in.level = 5;
3421 q.out.info = &info;
3423 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3424 if (!NT_STATUS_IS_OK(status)) {
3425 printf("QueryUserInfo level %u failed - %s\n",
3426 q.in.level, nt_errstr(status));
3427 ret = false;
3428 } else {
3429 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
3430 if ((info->info5.acct_flags) != expected_flags) {
3431 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3432 info->info5.acct_flags,
3433 expected_flags);
3434 /* FIXME: GD */
3435 if (!torture_setting_bool(tctx, "samba3", false)) {
3436 ret = false;
3439 if (info->info5.rid != rid) {
3440 printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3441 info->info5.rid, rid);
3446 break;
3448 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
3450 /* test last password change timestamp behaviour */
3451 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
3452 base_acct_name,
3453 user_handle, &password,
3454 machine_credentials)) {
3455 ret = false;
3458 if (ret == true) {
3459 torture_comment(tctx, "pwdLastSet test succeeded\n");
3460 } else {
3461 torture_warning(tctx, "pwdLastSet test failed\n");
3464 break;
3466 case TORTURE_SAMR_OTHER:
3467 /* We just need the account to exist */
3468 break;
3470 return ret;
3473 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
3474 struct policy_handle *alias_handle,
3475 const struct dom_sid *domain_sid)
3477 bool ret = true;
3479 if (!test_QuerySecurity(p, tctx, alias_handle)) {
3480 ret = false;
3483 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
3484 ret = false;
3487 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
3488 ret = false;
3491 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
3492 ret = false;
3495 if (torture_setting_bool(tctx, "samba4", false)) {
3496 printf("skipping MultipleMembers Alias tests against Samba4\n");
3497 return ret;
3500 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
3501 ret = false;
3504 return ret;
3508 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3509 struct policy_handle *user_handle)
3511 struct samr_DeleteUser d;
3512 NTSTATUS status;
3513 torture_comment(tctx, "Testing DeleteUser\n");
3515 d.in.user_handle = user_handle;
3516 d.out.user_handle = user_handle;
3518 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3519 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
3521 return true;
3524 bool test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3525 struct policy_handle *handle, const char *name)
3527 NTSTATUS status;
3528 struct samr_DeleteUser d;
3529 struct policy_handle user_handle;
3530 uint32_t rid;
3532 status = test_LookupName(p, mem_ctx, handle, name, &rid);
3533 if (!NT_STATUS_IS_OK(status)) {
3534 goto failed;
3537 status = test_OpenUser_byname(p, mem_ctx, handle, name, &user_handle);
3538 if (!NT_STATUS_IS_OK(status)) {
3539 goto failed;
3542 d.in.user_handle = &user_handle;
3543 d.out.user_handle = &user_handle;
3544 status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
3545 if (!NT_STATUS_IS_OK(status)) {
3546 goto failed;
3549 return true;
3551 failed:
3552 printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
3553 return false;
3557 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3558 struct policy_handle *handle, const char *name)
3560 NTSTATUS status;
3561 struct samr_OpenGroup r;
3562 struct samr_DeleteDomainGroup d;
3563 struct policy_handle group_handle;
3564 uint32_t rid;
3566 status = test_LookupName(p, mem_ctx, handle, name, &rid);
3567 if (!NT_STATUS_IS_OK(status)) {
3568 goto failed;
3571 r.in.domain_handle = handle;
3572 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3573 r.in.rid = rid;
3574 r.out.group_handle = &group_handle;
3575 status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
3576 if (!NT_STATUS_IS_OK(status)) {
3577 goto failed;
3580 d.in.group_handle = &group_handle;
3581 d.out.group_handle = &group_handle;
3582 status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
3583 if (!NT_STATUS_IS_OK(status)) {
3584 goto failed;
3587 return true;
3589 failed:
3590 printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
3591 return false;
3595 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3596 struct policy_handle *domain_handle, const char *name)
3598 NTSTATUS status;
3599 struct samr_OpenAlias r;
3600 struct samr_DeleteDomAlias d;
3601 struct policy_handle alias_handle;
3602 uint32_t rid;
3604 printf("testing DeleteAlias_byname\n");
3606 status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
3607 if (!NT_STATUS_IS_OK(status)) {
3608 goto failed;
3611 r.in.domain_handle = domain_handle;
3612 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3613 r.in.rid = rid;
3614 r.out.alias_handle = &alias_handle;
3615 status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
3616 if (!NT_STATUS_IS_OK(status)) {
3617 goto failed;
3620 d.in.alias_handle = &alias_handle;
3621 d.out.alias_handle = &alias_handle;
3622 status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
3623 if (!NT_STATUS_IS_OK(status)) {
3624 goto failed;
3627 return true;
3629 failed:
3630 printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
3631 return false;
3634 static bool test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3635 struct policy_handle *alias_handle)
3637 struct samr_DeleteDomAlias d;
3638 NTSTATUS status;
3639 bool ret = true;
3640 printf("Testing DeleteAlias\n");
3642 d.in.alias_handle = alias_handle;
3643 d.out.alias_handle = alias_handle;
3645 status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
3646 if (!NT_STATUS_IS_OK(status)) {
3647 printf("DeleteAlias failed - %s\n", nt_errstr(status));
3648 ret = false;
3651 return ret;
3654 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
3655 struct policy_handle *domain_handle,
3656 struct policy_handle *alias_handle,
3657 const struct dom_sid *domain_sid)
3659 NTSTATUS status;
3660 struct samr_CreateDomAlias r;
3661 struct lsa_String name;
3662 uint32_t rid;
3663 bool ret = true;
3665 init_lsa_String(&name, TEST_ALIASNAME);
3666 r.in.domain_handle = domain_handle;
3667 r.in.alias_name = &name;
3668 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3669 r.out.alias_handle = alias_handle;
3670 r.out.rid = &rid;
3672 printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
3674 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
3676 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
3677 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3678 printf("Server correctly refused create of '%s'\n", r.in.alias_name->string);
3679 return true;
3680 } else {
3681 printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
3682 nt_errstr(status));
3683 return false;
3687 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
3688 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
3689 return false;
3691 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
3694 if (!NT_STATUS_IS_OK(status)) {
3695 printf("CreateAlias failed - %s\n", nt_errstr(status));
3696 return false;
3699 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
3700 ret = false;
3703 return ret;
3706 static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3707 const char *acct_name,
3708 struct policy_handle *domain_handle, char **password)
3710 bool ret = true;
3712 if (!*password) {
3713 return false;
3716 if (!test_ChangePasswordUser(p, mem_ctx, acct_name, domain_handle, password)) {
3717 ret = false;
3720 if (!test_ChangePasswordUser2(p, mem_ctx, acct_name, password, 0, true)) {
3721 ret = false;
3724 if (!test_OemChangePasswordUser2(p, mem_ctx, acct_name, domain_handle, password)) {
3725 ret = false;
3728 /* test what happens when setting the old password again */
3729 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, *password, 0, true)) {
3730 ret = false;
3734 char simple_pass[9];
3735 char *v = generate_random_str(mem_ctx, 1);
3737 ZERO_STRUCT(simple_pass);
3738 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3740 /* test what happens when picking a simple password */
3741 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, simple_pass, 0, true)) {
3742 ret = false;
3746 /* set samr_SetDomainInfo level 1 with min_length 5 */
3748 struct samr_QueryDomainInfo r;
3749 union samr_DomainInfo *info = NULL;
3750 struct samr_SetDomainInfo s;
3751 uint16_t len_old, len;
3752 uint32_t pwd_prop_old;
3753 int64_t min_pwd_age_old;
3754 NTSTATUS status;
3756 len = 5;
3758 r.in.domain_handle = domain_handle;
3759 r.in.level = 1;
3760 r.out.info = &info;
3762 printf("testing samr_QueryDomainInfo level 1\n");
3763 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
3764 if (!NT_STATUS_IS_OK(status)) {
3765 return false;
3768 s.in.domain_handle = domain_handle;
3769 s.in.level = 1;
3770 s.in.info = info;
3772 /* remember the old min length, so we can reset it */
3773 len_old = s.in.info->info1.min_password_length;
3774 s.in.info->info1.min_password_length = len;
3775 pwd_prop_old = s.in.info->info1.password_properties;
3776 /* turn off password complexity checks for this test */
3777 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
3779 min_pwd_age_old = s.in.info->info1.min_password_age;
3780 s.in.info->info1.min_password_age = 0;
3782 printf("testing samr_SetDomainInfo level 1\n");
3783 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
3784 if (!NT_STATUS_IS_OK(status)) {
3785 return false;
3788 printf("calling test_ChangePasswordUser3 with too short password\n");
3790 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, len - 1, password, NULL, 0, true)) {
3791 ret = false;
3794 s.in.info->info1.min_password_length = len_old;
3795 s.in.info->info1.password_properties = pwd_prop_old;
3796 s.in.info->info1.min_password_age = min_pwd_age_old;
3798 printf("testing samr_SetDomainInfo level 1\n");
3799 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
3800 if (!NT_STATUS_IS_OK(status)) {
3801 return false;
3807 NTSTATUS status;
3808 struct samr_OpenUser r;
3809 struct samr_QueryUserInfo q;
3810 union samr_UserInfo *info;
3811 struct samr_LookupNames n;
3812 struct policy_handle user_handle;
3813 struct samr_Ids rids, types;
3815 n.in.domain_handle = domain_handle;
3816 n.in.num_names = 1;
3817 n.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
3818 n.in.names[0].string = acct_name;
3819 n.out.rids = &rids;
3820 n.out.types = &types;
3822 status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
3823 if (!NT_STATUS_IS_OK(status)) {
3824 printf("LookupNames failed - %s\n", nt_errstr(status));
3825 return false;
3828 r.in.domain_handle = domain_handle;
3829 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3830 r.in.rid = n.out.rids->ids[0];
3831 r.out.user_handle = &user_handle;
3833 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
3834 if (!NT_STATUS_IS_OK(status)) {
3835 printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
3836 return false;
3839 q.in.user_handle = &user_handle;
3840 q.in.level = 5;
3841 q.out.info = &info;
3843 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
3844 if (!NT_STATUS_IS_OK(status)) {
3845 printf("QueryUserInfo failed - %s\n", nt_errstr(status));
3846 return false;
3849 printf("calling test_ChangePasswordUser3 with too early password change\n");
3851 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL,
3852 info->info5.last_password_change, true)) {
3853 ret = false;
3857 /* we change passwords twice - this has the effect of verifying
3858 they were changed correctly for the final call */
3859 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
3860 ret = false;
3863 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
3864 ret = false;
3867 return ret;
3870 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3871 struct policy_handle *domain_handle,
3872 struct policy_handle *user_handle_out,
3873 struct dom_sid *domain_sid,
3874 enum torture_samr_choice which_ops,
3875 struct cli_credentials *machine_credentials)
3878 TALLOC_CTX *user_ctx;
3880 NTSTATUS status;
3881 struct samr_CreateUser r;
3882 struct samr_QueryUserInfo q;
3883 union samr_UserInfo *info;
3884 struct samr_DeleteUser d;
3885 uint32_t rid;
3887 /* This call creates a 'normal' account - check that it really does */
3888 const uint32_t acct_flags = ACB_NORMAL;
3889 struct lsa_String name;
3890 bool ret = true;
3892 struct policy_handle user_handle;
3893 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
3894 init_lsa_String(&name, TEST_ACCOUNT_NAME);
3896 r.in.domain_handle = domain_handle;
3897 r.in.account_name = &name;
3898 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3899 r.out.user_handle = &user_handle;
3900 r.out.rid = &rid;
3902 printf("Testing CreateUser(%s)\n", r.in.account_name->string);
3904 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
3906 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
3907 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3908 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
3909 return true;
3910 } else {
3911 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
3912 nt_errstr(status));
3913 return false;
3917 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
3918 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
3919 talloc_free(user_ctx);
3920 return false;
3922 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
3924 if (!NT_STATUS_IS_OK(status)) {
3925 talloc_free(user_ctx);
3926 printf("CreateUser failed - %s\n", nt_errstr(status));
3927 return false;
3928 } else {
3929 q.in.user_handle = &user_handle;
3930 q.in.level = 16;
3931 q.out.info = &info;
3933 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
3934 if (!NT_STATUS_IS_OK(status)) {
3935 printf("QueryUserInfo level %u failed - %s\n",
3936 q.in.level, nt_errstr(status));
3937 ret = false;
3938 } else {
3939 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
3940 printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3941 info->info16.acct_flags,
3942 acct_flags);
3943 ret = false;
3947 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
3948 acct_flags, name.string, which_ops,
3949 machine_credentials)) {
3950 ret = false;
3953 if (user_handle_out) {
3954 *user_handle_out = user_handle;
3955 } else {
3956 printf("Testing DeleteUser (createuser test)\n");
3958 d.in.user_handle = &user_handle;
3959 d.out.user_handle = &user_handle;
3961 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
3962 if (!NT_STATUS_IS_OK(status)) {
3963 printf("DeleteUser failed - %s\n", nt_errstr(status));
3964 ret = false;
3970 talloc_free(user_ctx);
3972 return ret;
3976 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
3977 struct policy_handle *domain_handle,
3978 struct dom_sid *domain_sid,
3979 enum torture_samr_choice which_ops,
3980 struct cli_credentials *machine_credentials)
3982 NTSTATUS status;
3983 struct samr_CreateUser2 r;
3984 struct samr_QueryUserInfo q;
3985 union samr_UserInfo *info;
3986 struct samr_DeleteUser d;
3987 struct policy_handle user_handle;
3988 uint32_t rid;
3989 struct lsa_String name;
3990 bool ret = true;
3991 int i;
3993 struct {
3994 uint32_t acct_flags;
3995 const char *account_name;
3996 NTSTATUS nt_status;
3997 } account_types[] = {
3998 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
3999 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4000 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4001 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4002 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4003 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4004 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
4005 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4006 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
4007 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
4008 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4009 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
4010 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4011 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
4012 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
4015 for (i = 0; account_types[i].account_name; i++) {
4016 TALLOC_CTX *user_ctx;
4017 uint32_t acct_flags = account_types[i].acct_flags;
4018 uint32_t access_granted;
4019 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
4020 init_lsa_String(&name, account_types[i].account_name);
4022 r.in.domain_handle = domain_handle;
4023 r.in.account_name = &name;
4024 r.in.acct_flags = acct_flags;
4025 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4026 r.out.user_handle = &user_handle;
4027 r.out.access_granted = &access_granted;
4028 r.out.rid = &rid;
4030 printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
4032 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4034 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4035 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4036 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
4037 continue;
4038 } else {
4039 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4040 nt_errstr(status));
4041 ret = false;
4042 continue;
4046 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4047 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4048 talloc_free(user_ctx);
4049 ret = false;
4050 continue;
4052 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4055 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
4056 printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4057 nt_errstr(status), nt_errstr(account_types[i].nt_status));
4058 ret = false;
4061 if (NT_STATUS_IS_OK(status)) {
4062 q.in.user_handle = &user_handle;
4063 q.in.level = 5;
4064 q.out.info = &info;
4066 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4067 if (!NT_STATUS_IS_OK(status)) {
4068 printf("QueryUserInfo level %u failed - %s\n",
4069 q.in.level, nt_errstr(status));
4070 ret = false;
4071 } else {
4072 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4073 if (acct_flags == ACB_NORMAL) {
4074 expected_flags |= ACB_PW_EXPIRED;
4076 if ((info->info5.acct_flags) != expected_flags) {
4077 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4078 info->info5.acct_flags,
4079 expected_flags);
4080 ret = false;
4082 switch (acct_flags) {
4083 case ACB_SVRTRUST:
4084 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
4085 printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4086 DOMAIN_RID_DCS, info->info5.primary_gid);
4087 ret = false;
4089 break;
4090 case ACB_WSTRUST:
4091 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
4092 printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4093 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
4094 ret = false;
4096 break;
4097 case ACB_NORMAL:
4098 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
4099 printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4100 DOMAIN_RID_USERS, info->info5.primary_gid);
4101 ret = false;
4103 break;
4107 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4108 acct_flags, name.string, which_ops,
4109 machine_credentials)) {
4110 ret = false;
4113 printf("Testing DeleteUser (createuser2 test)\n");
4115 d.in.user_handle = &user_handle;
4116 d.out.user_handle = &user_handle;
4118 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4119 if (!NT_STATUS_IS_OK(status)) {
4120 printf("DeleteUser failed - %s\n", nt_errstr(status));
4121 ret = false;
4124 talloc_free(user_ctx);
4127 return ret;
4130 static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4131 struct policy_handle *handle)
4133 NTSTATUS status;
4134 struct samr_QueryAliasInfo r;
4135 union samr_AliasInfo *info;
4136 uint16_t levels[] = {1, 2, 3};
4137 int i;
4138 bool ret = true;
4140 for (i=0;i<ARRAY_SIZE(levels);i++) {
4141 printf("Testing QueryAliasInfo level %u\n", levels[i]);
4143 r.in.alias_handle = handle;
4144 r.in.level = levels[i];
4145 r.out.info = &info;
4147 status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
4148 if (!NT_STATUS_IS_OK(status)) {
4149 printf("QueryAliasInfo level %u failed - %s\n",
4150 levels[i], nt_errstr(status));
4151 ret = false;
4155 return ret;
4158 static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4159 struct policy_handle *handle)
4161 NTSTATUS status;
4162 struct samr_QueryGroupInfo r;
4163 union samr_GroupInfo *info;
4164 uint16_t levels[] = {1, 2, 3, 4, 5};
4165 int i;
4166 bool ret = true;
4168 for (i=0;i<ARRAY_SIZE(levels);i++) {
4169 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4171 r.in.group_handle = handle;
4172 r.in.level = levels[i];
4173 r.out.info = &info;
4175 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
4176 if (!NT_STATUS_IS_OK(status)) {
4177 printf("QueryGroupInfo level %u failed - %s\n",
4178 levels[i], nt_errstr(status));
4179 ret = false;
4183 return ret;
4186 static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4187 struct policy_handle *handle)
4189 NTSTATUS status;
4190 struct samr_QueryGroupMember r;
4191 struct samr_RidTypeArray *rids = NULL;
4192 bool ret = true;
4194 printf("Testing QueryGroupMember\n");
4196 r.in.group_handle = handle;
4197 r.out.rids = &rids;
4199 status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r);
4200 if (!NT_STATUS_IS_OK(status)) {
4201 printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
4202 ret = false;
4205 return ret;
4209 static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4210 struct policy_handle *handle)
4212 NTSTATUS status;
4213 struct samr_QueryGroupInfo r;
4214 union samr_GroupInfo *info;
4215 struct samr_SetGroupInfo s;
4216 uint16_t levels[] = {1, 2, 3, 4};
4217 uint16_t set_ok[] = {0, 1, 1, 1};
4218 int i;
4219 bool ret = true;
4221 for (i=0;i<ARRAY_SIZE(levels);i++) {
4222 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4224 r.in.group_handle = handle;
4225 r.in.level = levels[i];
4226 r.out.info = &info;
4228 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
4229 if (!NT_STATUS_IS_OK(status)) {
4230 printf("QueryGroupInfo level %u failed - %s\n",
4231 levels[i], nt_errstr(status));
4232 ret = false;
4235 printf("Testing SetGroupInfo level %u\n", levels[i]);
4237 s.in.group_handle = handle;
4238 s.in.level = levels[i];
4239 s.in.info = *r.out.info;
4241 #if 0
4242 /* disabled this, as it changes the name only from the point of view of samr,
4243 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4244 the name is still reserved, so creating the old name fails, but deleting by the old name
4245 also fails */
4246 if (s.in.level == 2) {
4247 init_lsa_String(&s.in.info->string, "NewName");
4249 #endif
4251 if (s.in.level == 4) {
4252 init_lsa_String(&s.in.info->description, "test description");
4255 status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
4256 if (set_ok[i]) {
4257 if (!NT_STATUS_IS_OK(status)) {
4258 printf("SetGroupInfo level %u failed - %s\n",
4259 r.in.level, nt_errstr(status));
4260 ret = false;
4261 continue;
4263 } else {
4264 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4265 printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4266 r.in.level, nt_errstr(status));
4267 ret = false;
4268 continue;
4273 return ret;
4276 static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4277 struct policy_handle *handle)
4279 NTSTATUS status;
4280 struct samr_QueryUserInfo r;
4281 union samr_UserInfo *info;
4282 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4283 11, 12, 13, 14, 16, 17, 20, 21};
4284 int i;
4285 bool ret = true;
4287 for (i=0;i<ARRAY_SIZE(levels);i++) {
4288 printf("Testing QueryUserInfo level %u\n", levels[i]);
4290 r.in.user_handle = handle;
4291 r.in.level = levels[i];
4292 r.out.info = &info;
4294 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r);
4295 if (!NT_STATUS_IS_OK(status)) {
4296 printf("QueryUserInfo level %u failed - %s\n",
4297 levels[i], nt_errstr(status));
4298 ret = false;
4302 return ret;
4305 static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4306 struct policy_handle *handle)
4308 NTSTATUS status;
4309 struct samr_QueryUserInfo2 r;
4310 union samr_UserInfo *info;
4311 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4312 11, 12, 13, 14, 16, 17, 20, 21};
4313 int i;
4314 bool ret = true;
4316 for (i=0;i<ARRAY_SIZE(levels);i++) {
4317 printf("Testing QueryUserInfo2 level %u\n", levels[i]);
4319 r.in.user_handle = handle;
4320 r.in.level = levels[i];
4321 r.out.info = &info;
4323 status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r);
4324 if (!NT_STATUS_IS_OK(status)) {
4325 printf("QueryUserInfo2 level %u failed - %s\n",
4326 levels[i], nt_errstr(status));
4327 ret = false;
4331 return ret;
4334 static bool test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4335 struct policy_handle *handle, uint32_t rid)
4337 NTSTATUS status;
4338 struct samr_OpenUser r;
4339 struct policy_handle user_handle;
4340 bool ret = true;
4342 printf("Testing OpenUser(%u)\n", rid);
4344 r.in.domain_handle = handle;
4345 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4346 r.in.rid = rid;
4347 r.out.user_handle = &user_handle;
4349 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
4350 if (!NT_STATUS_IS_OK(status)) {
4351 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4352 return false;
4355 if (!test_QuerySecurity(p, mem_ctx, &user_handle)) {
4356 ret = false;
4359 if (!test_QueryUserInfo(p, mem_ctx, &user_handle)) {
4360 ret = false;
4363 if (!test_QueryUserInfo2(p, mem_ctx, &user_handle)) {
4364 ret = false;
4367 if (!test_GetUserPwInfo(p, mem_ctx, &user_handle)) {
4368 ret = false;
4371 if (!test_GetGroupsForUser(p,mem_ctx, &user_handle)) {
4372 ret = false;
4375 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
4376 ret = false;
4379 return ret;
4382 static bool test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4383 struct policy_handle *handle, uint32_t rid)
4385 NTSTATUS status;
4386 struct samr_OpenGroup r;
4387 struct policy_handle group_handle;
4388 bool ret = true;
4390 printf("Testing OpenGroup(%u)\n", rid);
4392 r.in.domain_handle = handle;
4393 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4394 r.in.rid = rid;
4395 r.out.group_handle = &group_handle;
4397 status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
4398 if (!NT_STATUS_IS_OK(status)) {
4399 printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
4400 return false;
4403 if (!test_QuerySecurity(p, mem_ctx, &group_handle)) {
4404 ret = false;
4407 if (!test_QueryGroupInfo(p, mem_ctx, &group_handle)) {
4408 ret = false;
4411 if (!test_QueryGroupMember(p, mem_ctx, &group_handle)) {
4412 ret = false;
4415 if (!test_samr_handle_Close(p, mem_ctx, &group_handle)) {
4416 ret = false;
4419 return ret;
4422 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4423 struct policy_handle *handle, uint32_t rid)
4425 NTSTATUS status;
4426 struct samr_OpenAlias r;
4427 struct policy_handle alias_handle;
4428 bool ret = true;
4430 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
4432 r.in.domain_handle = handle;
4433 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4434 r.in.rid = rid;
4435 r.out.alias_handle = &alias_handle;
4437 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4438 if (!NT_STATUS_IS_OK(status)) {
4439 printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
4440 return false;
4443 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
4444 ret = false;
4447 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
4448 ret = false;
4451 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
4452 ret = false;
4455 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
4456 ret = false;
4459 return ret;
4462 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
4463 struct policy_handle *handle, uint32_t rid,
4464 uint32_t acct_flag_mask)
4466 NTSTATUS status;
4467 struct samr_OpenUser r;
4468 struct samr_QueryUserInfo q;
4469 union samr_UserInfo *info;
4470 struct policy_handle user_handle;
4471 bool ret = true;
4473 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4475 r.in.domain_handle = handle;
4476 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4477 r.in.rid = rid;
4478 r.out.user_handle = &user_handle;
4480 status = dcerpc_samr_OpenUser(p, tctx, &r);
4481 if (!NT_STATUS_IS_OK(status)) {
4482 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4483 return false;
4486 q.in.user_handle = &user_handle;
4487 q.in.level = 16;
4488 q.out.info = &info;
4490 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4491 if (!NT_STATUS_IS_OK(status)) {
4492 printf("QueryUserInfo level 16 failed - %s\n",
4493 nt_errstr(status));
4494 ret = false;
4495 } else {
4496 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
4497 printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4498 acct_flag_mask, info->info16.acct_flags, rid);
4499 ret = false;
4503 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4504 ret = false;
4507 return ret;
4510 static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *tctx,
4511 struct policy_handle *handle)
4513 NTSTATUS status = STATUS_MORE_ENTRIES;
4514 struct samr_EnumDomainUsers r;
4515 uint32_t mask, resume_handle=0;
4516 int i, mask_idx;
4517 bool ret = true;
4518 struct samr_LookupNames n;
4519 struct samr_LookupRids lr ;
4520 struct lsa_Strings names;
4521 struct samr_Ids rids, types;
4522 struct samr_SamArray *sam = NULL;
4523 uint32_t num_entries = 0;
4525 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
4526 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
4527 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
4528 ACB_PWNOEXP, 0};
4530 printf("Testing EnumDomainUsers\n");
4532 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
4533 r.in.domain_handle = handle;
4534 r.in.resume_handle = &resume_handle;
4535 r.in.acct_flags = mask = masks[mask_idx];
4536 r.in.max_size = (uint32_t)-1;
4537 r.out.resume_handle = &resume_handle;
4538 r.out.num_entries = &num_entries;
4539 r.out.sam = &sam;
4541 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
4542 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
4543 !NT_STATUS_IS_OK(status)) {
4544 printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
4545 return false;
4548 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4550 if (sam->count == 0) {
4551 continue;
4554 for (i=0;i<sam->count;i++) {
4555 if (mask) {
4556 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
4557 ret = false;
4559 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
4560 ret = false;
4565 printf("Testing LookupNames\n");
4566 n.in.domain_handle = handle;
4567 n.in.num_names = sam->count;
4568 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
4569 n.out.rids = &rids;
4570 n.out.types = &types;
4571 for (i=0;i<sam->count;i++) {
4572 n.in.names[i].string = sam->entries[i].name.string;
4574 status = dcerpc_samr_LookupNames(p, tctx, &n);
4575 if (!NT_STATUS_IS_OK(status)) {
4576 printf("LookupNames failed - %s\n", nt_errstr(status));
4577 ret = false;
4581 printf("Testing LookupRids\n");
4582 lr.in.domain_handle = handle;
4583 lr.in.num_rids = sam->count;
4584 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
4585 lr.out.names = &names;
4586 lr.out.types = &types;
4587 for (i=0;i<sam->count;i++) {
4588 lr.in.rids[i] = sam->entries[i].idx;
4590 status = dcerpc_samr_LookupRids(p, tctx, &lr);
4591 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
4593 return ret;
4597 try blasting the server with a bunch of sync requests
4599 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
4600 struct policy_handle *handle)
4602 NTSTATUS status;
4603 struct samr_EnumDomainUsers r;
4604 uint32_t resume_handle=0;
4605 int i;
4606 #define ASYNC_COUNT 100
4607 struct rpc_request *req[ASYNC_COUNT];
4609 if (!torture_setting_bool(tctx, "dangerous", false)) {
4610 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
4613 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
4615 r.in.domain_handle = handle;
4616 r.in.resume_handle = &resume_handle;
4617 r.in.acct_flags = 0;
4618 r.in.max_size = (uint32_t)-1;
4619 r.out.resume_handle = &resume_handle;
4621 for (i=0;i<ASYNC_COUNT;i++) {
4622 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
4625 for (i=0;i<ASYNC_COUNT;i++) {
4626 status = dcerpc_ndr_request_recv(req[i]);
4627 if (!NT_STATUS_IS_OK(status)) {
4628 printf("EnumDomainUsers[%d] failed - %s\n",
4629 i, nt_errstr(status));
4630 return false;
4634 torture_comment(tctx, "%d async requests OK\n", i);
4636 return true;
4639 static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4640 struct policy_handle *handle)
4642 NTSTATUS status;
4643 struct samr_EnumDomainGroups r;
4644 uint32_t resume_handle=0;
4645 struct samr_SamArray *sam = NULL;
4646 uint32_t num_entries = 0;
4647 int i;
4648 bool ret = true;
4650 printf("Testing EnumDomainGroups\n");
4652 r.in.domain_handle = handle;
4653 r.in.resume_handle = &resume_handle;
4654 r.in.max_size = (uint32_t)-1;
4655 r.out.resume_handle = &resume_handle;
4656 r.out.num_entries = &num_entries;
4657 r.out.sam = &sam;
4659 status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
4660 if (!NT_STATUS_IS_OK(status)) {
4661 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
4662 return false;
4665 if (!sam) {
4666 return false;
4669 for (i=0;i<sam->count;i++) {
4670 if (!test_OpenGroup(p, mem_ctx, handle, sam->entries[i].idx)) {
4671 ret = false;
4675 return ret;
4678 static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4679 struct policy_handle *handle)
4681 NTSTATUS status;
4682 struct samr_EnumDomainAliases r;
4683 uint32_t resume_handle=0;
4684 struct samr_SamArray *sam = NULL;
4685 uint32_t num_entries = 0;
4686 int i;
4687 bool ret = true;
4689 printf("Testing EnumDomainAliases\n");
4691 r.in.domain_handle = handle;
4692 r.in.resume_handle = &resume_handle;
4693 r.in.max_size = (uint32_t)-1;
4694 r.out.sam = &sam;
4695 r.out.num_entries = &num_entries;
4696 r.out.resume_handle = &resume_handle;
4698 status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
4701 return false;
4704 if (!sam) {
4705 return false;
4708 for (i=0;i<sam->count;i++) {
4709 if (!test_OpenAlias(p, mem_ctx, handle, sam->entries[i].idx)) {
4710 ret = false;
4714 return ret;
4717 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4718 struct policy_handle *handle)
4720 NTSTATUS status;
4721 struct samr_GetDisplayEnumerationIndex r;
4722 bool ret = true;
4723 uint16_t levels[] = {1, 2, 3, 4, 5};
4724 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
4725 struct lsa_String name;
4726 uint32_t idx = 0;
4727 int i;
4729 for (i=0;i<ARRAY_SIZE(levels);i++) {
4730 printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
4732 init_lsa_String(&name, TEST_ACCOUNT_NAME);
4734 r.in.domain_handle = handle;
4735 r.in.level = levels[i];
4736 r.in.name = &name;
4737 r.out.idx = &idx;
4739 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
4741 if (ok_lvl[i] &&
4742 !NT_STATUS_IS_OK(status) &&
4743 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4744 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
4745 levels[i], nt_errstr(status));
4746 ret = false;
4749 init_lsa_String(&name, "zzzzzzzz");
4751 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
4753 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4754 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
4755 levels[i], nt_errstr(status));
4756 ret = false;
4760 return ret;
4763 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4764 struct policy_handle *handle)
4766 NTSTATUS status;
4767 struct samr_GetDisplayEnumerationIndex2 r;
4768 bool ret = true;
4769 uint16_t levels[] = {1, 2, 3, 4, 5};
4770 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
4771 struct lsa_String name;
4772 uint32_t idx = 0;
4773 int i;
4775 for (i=0;i<ARRAY_SIZE(levels);i++) {
4776 printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
4778 init_lsa_String(&name, TEST_ACCOUNT_NAME);
4780 r.in.domain_handle = handle;
4781 r.in.level = levels[i];
4782 r.in.name = &name;
4783 r.out.idx = &idx;
4785 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
4786 if (ok_lvl[i] &&
4787 !NT_STATUS_IS_OK(status) &&
4788 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4789 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
4790 levels[i], nt_errstr(status));
4791 ret = false;
4794 init_lsa_String(&name, "zzzzzzzz");
4796 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
4797 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4798 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
4799 levels[i], nt_errstr(status));
4800 ret = false;
4804 return ret;
4807 #define STRING_EQUAL_QUERY(s1, s2, user) \
4808 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
4809 /* odd, but valid */ \
4810 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
4811 printf("%s mismatch for %s: %s != %s (%s)\n", \
4812 #s1, user.string, s1.string, s2.string, __location__); \
4813 ret = false; \
4815 #define INT_EQUAL_QUERY(s1, s2, user) \
4816 if (s1 != s2) { \
4817 printf("%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
4818 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
4819 ret = false; \
4822 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4823 struct samr_QueryDisplayInfo *querydisplayinfo,
4824 bool *seen_testuser)
4826 struct samr_OpenUser r;
4827 struct samr_QueryUserInfo q;
4828 union samr_UserInfo *info;
4829 struct policy_handle user_handle;
4830 int i, ret = true;
4831 NTSTATUS status;
4832 r.in.domain_handle = querydisplayinfo->in.domain_handle;
4833 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4834 for (i = 0; ; i++) {
4835 switch (querydisplayinfo->in.level) {
4836 case 1:
4837 if (i >= querydisplayinfo->out.info->info1.count) {
4838 return ret;
4840 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
4841 break;
4842 case 2:
4843 if (i >= querydisplayinfo->out.info->info2.count) {
4844 return ret;
4846 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
4847 break;
4848 case 3:
4849 /* Groups */
4850 case 4:
4851 case 5:
4852 /* Not interested in validating just the account name */
4853 return true;
4856 r.out.user_handle = &user_handle;
4858 switch (querydisplayinfo->in.level) {
4859 case 1:
4860 case 2:
4861 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
4862 if (!NT_STATUS_IS_OK(status)) {
4863 printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
4864 return false;
4868 q.in.user_handle = &user_handle;
4869 q.in.level = 21;
4870 q.out.info = &info;
4871 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
4872 if (!NT_STATUS_IS_OK(status)) {
4873 printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
4874 return false;
4877 switch (querydisplayinfo->in.level) {
4878 case 1:
4879 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
4880 *seen_testuser = true;
4882 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
4883 info->info21.full_name, info->info21.account_name);
4884 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
4885 info->info21.account_name, info->info21.account_name);
4886 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
4887 info->info21.description, info->info21.account_name);
4888 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
4889 info->info21.rid, info->info21.account_name);
4890 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
4891 info->info21.acct_flags, info->info21.account_name);
4893 break;
4894 case 2:
4895 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
4896 info->info21.account_name, info->info21.account_name);
4897 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
4898 info->info21.description, info->info21.account_name);
4899 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
4900 info->info21.rid, info->info21.account_name);
4901 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
4902 info->info21.acct_flags, info->info21.account_name);
4904 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
4905 printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
4906 info->info21.account_name.string);
4909 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
4910 printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
4911 info->info21.account_name.string,
4912 querydisplayinfo->out.info->info2.entries[i].acct_flags,
4913 info->info21.acct_flags);
4914 return false;
4917 break;
4920 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
4921 return false;
4924 return ret;
4927 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4928 struct policy_handle *handle)
4930 NTSTATUS status;
4931 struct samr_QueryDisplayInfo r;
4932 struct samr_QueryDomainInfo dom_info;
4933 union samr_DomainInfo *info = NULL;
4934 bool ret = true;
4935 uint16_t levels[] = {1, 2, 3, 4, 5};
4936 int i;
4937 bool seen_testuser = false;
4938 uint32_t total_size;
4939 uint32_t returned_size;
4940 union samr_DispInfo disp_info;
4943 for (i=0;i<ARRAY_SIZE(levels);i++) {
4944 printf("Testing QueryDisplayInfo level %u\n", levels[i]);
4946 r.in.start_idx = 0;
4947 status = STATUS_MORE_ENTRIES;
4948 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
4949 r.in.domain_handle = handle;
4950 r.in.level = levels[i];
4951 r.in.max_entries = 2;
4952 r.in.buf_size = (uint32_t)-1;
4953 r.out.total_size = &total_size;
4954 r.out.returned_size = &returned_size;
4955 r.out.info = &disp_info;
4957 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
4958 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
4959 printf("QueryDisplayInfo level %u failed - %s\n",
4960 levels[i], nt_errstr(status));
4961 ret = false;
4963 switch (r.in.level) {
4964 case 1:
4965 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) {
4966 ret = false;
4968 r.in.start_idx += r.out.info->info1.count;
4969 break;
4970 case 2:
4971 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) {
4972 ret = false;
4974 r.in.start_idx += r.out.info->info2.count;
4975 break;
4976 case 3:
4977 r.in.start_idx += r.out.info->info3.count;
4978 break;
4979 case 4:
4980 r.in.start_idx += r.out.info->info4.count;
4981 break;
4982 case 5:
4983 r.in.start_idx += r.out.info->info5.count;
4984 break;
4987 dom_info.in.domain_handle = handle;
4988 dom_info.in.level = 2;
4989 dom_info.out.info = &info;
4991 /* Check number of users returned is correct */
4992 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info);
4993 if (!NT_STATUS_IS_OK(status)) {
4994 printf("QueryDomainInfo level %u failed - %s\n",
4995 r.in.level, nt_errstr(status));
4996 ret = false;
4997 break;
4999 switch (r.in.level) {
5000 case 1:
5001 case 4:
5002 if (info->general.num_users < r.in.start_idx) {
5003 printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
5004 r.in.start_idx, info->general.num_groups,
5005 info->general.domain_name.string);
5006 ret = false;
5008 if (!seen_testuser) {
5009 struct policy_handle user_handle;
5010 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
5011 printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
5012 info->general.domain_name.string);
5013 ret = false;
5014 test_samr_handle_Close(p, mem_ctx, &user_handle);
5017 break;
5018 case 3:
5019 case 5:
5020 if (info->general.num_groups != r.in.start_idx) {
5021 printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
5022 r.in.start_idx, info->general.num_groups,
5023 info->general.domain_name.string);
5024 ret = false;
5027 break;
5032 return ret;
5035 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
5036 struct policy_handle *handle)
5038 NTSTATUS status;
5039 struct samr_QueryDisplayInfo2 r;
5040 bool ret = true;
5041 uint16_t levels[] = {1, 2, 3, 4, 5};
5042 int i;
5043 uint32_t total_size;
5044 uint32_t returned_size;
5045 union samr_DispInfo info;
5047 for (i=0;i<ARRAY_SIZE(levels);i++) {
5048 printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
5050 r.in.domain_handle = handle;
5051 r.in.level = levels[i];
5052 r.in.start_idx = 0;
5053 r.in.max_entries = 1000;
5054 r.in.buf_size = (uint32_t)-1;
5055 r.out.total_size = &total_size;
5056 r.out.returned_size = &returned_size;
5057 r.out.info = &info;
5059 status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
5060 if (!NT_STATUS_IS_OK(status)) {
5061 printf("QueryDisplayInfo2 level %u failed - %s\n",
5062 levels[i], nt_errstr(status));
5063 ret = false;
5067 return ret;
5070 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
5071 struct policy_handle *handle)
5073 NTSTATUS status;
5074 struct samr_QueryDisplayInfo3 r;
5075 bool ret = true;
5076 uint16_t levels[] = {1, 2, 3, 4, 5};
5077 int i;
5078 uint32_t total_size;
5079 uint32_t returned_size;
5080 union samr_DispInfo info;
5082 for (i=0;i<ARRAY_SIZE(levels);i++) {
5083 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
5085 r.in.domain_handle = handle;
5086 r.in.level = levels[i];
5087 r.in.start_idx = 0;
5088 r.in.max_entries = 1000;
5089 r.in.buf_size = (uint32_t)-1;
5090 r.out.total_size = &total_size;
5091 r.out.returned_size = &returned_size;
5092 r.out.info = &info;
5094 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
5095 if (!NT_STATUS_IS_OK(status)) {
5096 printf("QueryDisplayInfo3 level %u failed - %s\n",
5097 levels[i], nt_errstr(status));
5098 ret = false;
5102 return ret;
5106 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
5107 struct policy_handle *handle)
5109 NTSTATUS status;
5110 struct samr_QueryDisplayInfo r;
5111 bool ret = true;
5112 uint32_t total_size;
5113 uint32_t returned_size;
5114 union samr_DispInfo info;
5116 printf("Testing QueryDisplayInfo continuation\n");
5118 r.in.domain_handle = handle;
5119 r.in.level = 1;
5120 r.in.start_idx = 0;
5121 r.in.max_entries = 1;
5122 r.in.buf_size = (uint32_t)-1;
5123 r.out.total_size = &total_size;
5124 r.out.returned_size = &returned_size;
5125 r.out.info = &info;
5127 do {
5128 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
5129 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
5130 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
5131 printf("expected idx %d but got %d\n",
5132 r.in.start_idx + 1,
5133 r.out.info->info1.entries[0].idx);
5134 break;
5137 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5138 !NT_STATUS_IS_OK(status)) {
5139 printf("QueryDisplayInfo level %u failed - %s\n",
5140 r.in.level, nt_errstr(status));
5141 ret = false;
5142 break;
5144 r.in.start_idx++;
5145 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
5146 NT_STATUS_IS_OK(status)) &&
5147 *r.out.returned_size != 0);
5149 return ret;
5152 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
5153 struct policy_handle *handle)
5155 NTSTATUS status;
5156 struct samr_QueryDomainInfo r;
5157 union samr_DomainInfo *info = NULL;
5158 struct samr_SetDomainInfo s;
5159 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5160 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5161 int i;
5162 bool ret = true;
5163 const char *domain_comment = talloc_asprintf(tctx,
5164 "Tortured by Samba4 RPC-SAMR: %s",
5165 timestring(tctx, time(NULL)));
5167 s.in.domain_handle = handle;
5168 s.in.level = 4;
5169 s.in.info = talloc(tctx, union samr_DomainInfo);
5171 s.in.info->oem.oem_information.string = domain_comment;
5172 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5173 if (!NT_STATUS_IS_OK(status)) {
5174 printf("SetDomainInfo level %u (set comment) failed - %s\n",
5175 s.in.level, nt_errstr(status));
5176 return false;
5179 for (i=0;i<ARRAY_SIZE(levels);i++) {
5180 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
5182 r.in.domain_handle = handle;
5183 r.in.level = levels[i];
5184 r.out.info = &info;
5186 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5187 if (!NT_STATUS_IS_OK(status)) {
5188 printf("QueryDomainInfo level %u failed - %s\n",
5189 r.in.level, nt_errstr(status));
5190 ret = false;
5191 continue;
5194 switch (levels[i]) {
5195 case 2:
5196 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
5197 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5198 levels[i], info->general.oem_information.string, domain_comment);
5199 ret = false;
5201 if (!info->general.primary.string) {
5202 printf("QueryDomainInfo level %u returned no PDC name\n",
5203 levels[i]);
5204 ret = false;
5205 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
5206 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
5207 printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5208 levels[i], info->general.primary.string, dcerpc_server_name(p));
5211 break;
5212 case 4:
5213 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
5214 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5215 levels[i], info->oem.oem_information.string, domain_comment);
5216 ret = false;
5218 break;
5219 case 6:
5220 if (!info->info6.primary.string) {
5221 printf("QueryDomainInfo level %u returned no PDC name\n",
5222 levels[i]);
5223 ret = false;
5225 break;
5226 case 11:
5227 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
5228 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5229 levels[i], info->general2.general.oem_information.string, domain_comment);
5230 ret = false;
5232 break;
5235 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
5237 s.in.domain_handle = handle;
5238 s.in.level = levels[i];
5239 s.in.info = info;
5241 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5242 if (set_ok[i]) {
5243 if (!NT_STATUS_IS_OK(status)) {
5244 printf("SetDomainInfo level %u failed - %s\n",
5245 r.in.level, nt_errstr(status));
5246 ret = false;
5247 continue;
5249 } else {
5250 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5251 printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5252 r.in.level, nt_errstr(status));
5253 ret = false;
5254 continue;
5258 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5259 if (!NT_STATUS_IS_OK(status)) {
5260 printf("QueryDomainInfo level %u failed - %s\n",
5261 r.in.level, nt_errstr(status));
5262 ret = false;
5263 continue;
5267 return ret;
5271 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
5272 struct policy_handle *handle)
5274 NTSTATUS status;
5275 struct samr_QueryDomainInfo2 r;
5276 union samr_DomainInfo *info = NULL;
5277 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5278 int i;
5279 bool ret = true;
5281 for (i=0;i<ARRAY_SIZE(levels);i++) {
5282 printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
5284 r.in.domain_handle = handle;
5285 r.in.level = levels[i];
5286 r.out.info = &info;
5288 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
5289 if (!NT_STATUS_IS_OK(status)) {
5290 printf("QueryDomainInfo2 level %u failed - %s\n",
5291 r.in.level, nt_errstr(status));
5292 ret = false;
5293 continue;
5297 return true;
5300 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5301 set of group names. */
5302 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
5303 struct policy_handle *handle)
5305 struct samr_EnumDomainGroups q1;
5306 struct samr_QueryDisplayInfo q2;
5307 NTSTATUS status;
5308 uint32_t resume_handle=0;
5309 struct samr_SamArray *sam = NULL;
5310 uint32_t num_entries = 0;
5311 int i;
5312 bool ret = true;
5313 uint32_t total_size;
5314 uint32_t returned_size;
5315 union samr_DispInfo info;
5317 int num_names = 0;
5318 const char **names = NULL;
5320 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
5322 q1.in.domain_handle = handle;
5323 q1.in.resume_handle = &resume_handle;
5324 q1.in.max_size = 5;
5325 q1.out.resume_handle = &resume_handle;
5326 q1.out.num_entries = &num_entries;
5327 q1.out.sam = &sam;
5329 status = STATUS_MORE_ENTRIES;
5330 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5331 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
5333 if (!NT_STATUS_IS_OK(status) &&
5334 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5335 break;
5337 for (i=0; i<*q1.out.num_entries; i++) {
5338 add_string_to_array(tctx,
5339 sam->entries[i].name.string,
5340 &names, &num_names);
5344 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
5346 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
5348 q2.in.domain_handle = handle;
5349 q2.in.level = 5;
5350 q2.in.start_idx = 0;
5351 q2.in.max_entries = 5;
5352 q2.in.buf_size = (uint32_t)-1;
5353 q2.out.total_size = &total_size;
5354 q2.out.returned_size = &returned_size;
5355 q2.out.info = &info;
5357 status = STATUS_MORE_ENTRIES;
5358 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5359 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
5361 if (!NT_STATUS_IS_OK(status) &&
5362 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5363 break;
5365 for (i=0; i<q2.out.info->info5.count; i++) {
5366 int j;
5367 const char *name = q2.out.info->info5.entries[i].account_name.string;
5368 bool found = false;
5369 for (j=0; j<num_names; j++) {
5370 if (names[j] == NULL)
5371 continue;
5372 if (strequal(names[j], name)) {
5373 names[j] = NULL;
5374 found = true;
5375 break;
5379 if (!found) {
5380 printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5381 name);
5382 ret = false;
5385 q2.in.start_idx += q2.out.info->info5.count;
5388 if (!NT_STATUS_IS_OK(status)) {
5389 printf("QueryDisplayInfo level 5 failed - %s\n",
5390 nt_errstr(status));
5391 ret = false;
5394 for (i=0; i<num_names; i++) {
5395 if (names[i] != NULL) {
5396 printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5397 names[i]);
5398 ret = false;
5402 return ret;
5405 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
5406 struct policy_handle *group_handle)
5408 struct samr_DeleteDomainGroup d;
5409 NTSTATUS status;
5411 torture_comment(tctx, "Testing DeleteDomainGroup\n");
5413 d.in.group_handle = group_handle;
5414 d.out.group_handle = group_handle;
5416 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
5417 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
5419 return true;
5422 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5423 struct policy_handle *domain_handle)
5425 struct samr_TestPrivateFunctionsDomain r;
5426 NTSTATUS status;
5427 bool ret = true;
5429 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
5431 r.in.domain_handle = domain_handle;
5433 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
5434 torture_assert_ntstatus_equal(tctx, NT_STATUS_NOT_IMPLEMENTED, status, "TestPrivateFunctionsDomain");
5436 return ret;
5439 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
5440 struct dom_sid *domain_sid,
5441 struct policy_handle *domain_handle)
5443 struct samr_RidToSid r;
5444 NTSTATUS status;
5445 bool ret = true;
5446 struct dom_sid *calc_sid, *out_sid;
5447 int rids[] = { 0, 42, 512, 10200 };
5448 int i;
5450 for (i=0;i<ARRAY_SIZE(rids);i++) {
5451 torture_comment(tctx, "Testing RidToSid\n");
5453 calc_sid = dom_sid_dup(tctx, domain_sid);
5454 r.in.domain_handle = domain_handle;
5455 r.in.rid = rids[i];
5456 r.out.sid = &out_sid;
5458 status = dcerpc_samr_RidToSid(p, tctx, &r);
5459 if (!NT_STATUS_IS_OK(status)) {
5460 printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
5461 ret = false;
5462 } else {
5463 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
5465 if (!dom_sid_equal(calc_sid, out_sid)) {
5466 printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
5467 dom_sid_string(tctx, out_sid),
5468 dom_sid_string(tctx, calc_sid));
5469 ret = false;
5474 return ret;
5477 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
5478 struct policy_handle *domain_handle)
5480 struct samr_GetBootKeyInformation r;
5481 NTSTATUS status;
5482 bool ret = true;
5483 uint32_t unknown = 0;
5485 torture_comment(tctx, "Testing GetBootKeyInformation\n");
5487 r.in.domain_handle = domain_handle;
5488 r.out.unknown = &unknown;
5490 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
5491 if (!NT_STATUS_IS_OK(status)) {
5492 /* w2k3 seems to fail this sometimes and pass it sometimes */
5493 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
5496 return ret;
5499 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
5500 struct policy_handle *domain_handle,
5501 struct policy_handle *group_handle)
5503 NTSTATUS status;
5504 struct samr_AddGroupMember r;
5505 struct samr_DeleteGroupMember d;
5506 struct samr_QueryGroupMember q;
5507 struct samr_RidTypeArray *rids = NULL;
5508 struct samr_SetMemberAttributesOfGroup s;
5509 uint32_t rid;
5511 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
5512 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
5514 r.in.group_handle = group_handle;
5515 r.in.rid = rid;
5516 r.in.flags = 0; /* ??? */
5518 torture_comment(tctx, "Testing AddGroupMember and DeleteGroupMember\n");
5520 d.in.group_handle = group_handle;
5521 d.in.rid = rid;
5523 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5524 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
5526 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5527 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5529 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5530 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
5532 if (torture_setting_bool(tctx, "samba4", false)) {
5533 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba4\n");
5534 } else {
5535 /* this one is quite strange. I am using random inputs in the
5536 hope of triggering an error that might give us a clue */
5538 s.in.group_handle = group_handle;
5539 s.in.unknown1 = random();
5540 s.in.unknown2 = random();
5542 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
5543 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
5546 q.in.group_handle = group_handle;
5547 q.out.rids = &rids;
5549 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5550 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5552 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5553 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
5555 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5556 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5558 return true;
5562 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
5563 struct torture_context *tctx,
5564 struct policy_handle *domain_handle,
5565 struct policy_handle *group_handle,
5566 struct dom_sid *domain_sid)
5568 NTSTATUS status;
5569 struct samr_CreateDomainGroup r;
5570 uint32_t rid;
5571 struct lsa_String name;
5572 bool ret = true;
5574 init_lsa_String(&name, TEST_GROUPNAME);
5576 r.in.domain_handle = domain_handle;
5577 r.in.name = &name;
5578 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5579 r.out.group_handle = group_handle;
5580 r.out.rid = &rid;
5582 printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
5584 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5586 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5587 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5588 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
5589 return true;
5590 } else {
5591 printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
5592 nt_errstr(status));
5593 return false;
5597 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
5598 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
5599 printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
5600 nt_errstr(status));
5601 return false;
5603 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5605 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5606 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
5608 printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
5609 nt_errstr(status));
5610 return false;
5612 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5614 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
5616 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
5617 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
5618 ret = false;
5621 if (!test_SetGroupInfo(p, tctx, group_handle)) {
5622 ret = false;
5625 return ret;
5630 its not totally clear what this does. It seems to accept any sid you like.
5632 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
5633 struct torture_context *tctx,
5634 struct policy_handle *domain_handle)
5636 NTSTATUS status;
5637 struct samr_RemoveMemberFromForeignDomain r;
5639 r.in.domain_handle = domain_handle;
5640 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
5642 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
5643 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
5645 return true;
5650 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
5651 struct policy_handle *handle);
5653 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5654 struct policy_handle *handle, struct dom_sid *sid,
5655 enum torture_samr_choice which_ops,
5656 struct cli_credentials *machine_credentials)
5658 NTSTATUS status;
5659 struct samr_OpenDomain r;
5660 struct policy_handle domain_handle;
5661 struct policy_handle alias_handle;
5662 struct policy_handle user_handle;
5663 struct policy_handle group_handle;
5664 bool ret = true;
5666 ZERO_STRUCT(alias_handle);
5667 ZERO_STRUCT(user_handle);
5668 ZERO_STRUCT(group_handle);
5669 ZERO_STRUCT(domain_handle);
5671 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
5673 r.in.connect_handle = handle;
5674 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5675 r.in.sid = sid;
5676 r.out.domain_handle = &domain_handle;
5678 status = dcerpc_samr_OpenDomain(p, tctx, &r);
5679 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
5681 /* run the domain tests with the main handle closed - this tests
5682 the servers reference counting */
5683 ret &= test_samr_handle_Close(p, tctx, handle);
5685 switch (which_ops) {
5686 case TORTURE_SAMR_USER_ATTRIBUTES:
5687 case TORTURE_SAMR_PASSWORDS:
5688 if (!torture_setting_bool(tctx, "samba3", false)) {
5689 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
5691 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
5692 /* This test needs 'complex' users to validate */
5693 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
5694 if (!ret) {
5695 printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
5697 break;
5698 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
5699 if (!torture_setting_bool(tctx, "samba3", false)) {
5700 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, machine_credentials);
5702 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, machine_credentials);
5703 if (!ret) {
5704 printf("Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
5706 break;
5707 case TORTURE_SAMR_OTHER:
5708 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
5709 if (!ret) {
5710 printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
5712 ret &= test_QuerySecurity(p, tctx, &domain_handle);
5713 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
5714 ret &= test_CreateAlias(p, tctx, &domain_handle, &alias_handle, sid);
5715 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle, sid);
5716 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
5717 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
5718 ret &= test_EnumDomainUsers(p, tctx, &domain_handle);
5719 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
5720 ret &= test_EnumDomainGroups(p, tctx, &domain_handle);
5721 ret &= test_EnumDomainAliases(p, tctx, &domain_handle);
5722 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
5723 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
5724 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
5726 if (torture_setting_bool(tctx, "samba4", false)) {
5727 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
5728 } else {
5729 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
5730 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
5732 ret &= test_GroupList(p, tctx, &domain_handle);
5733 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
5734 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
5735 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
5736 if (!ret) {
5737 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
5739 break;
5742 if (!policy_handle_empty(&user_handle) &&
5743 !test_DeleteUser(p, tctx, &user_handle)) {
5744 ret = false;
5747 if (!policy_handle_empty(&alias_handle) &&
5748 !test_DeleteAlias(p, tctx, &alias_handle)) {
5749 ret = false;
5752 if (!policy_handle_empty(&group_handle) &&
5753 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
5754 ret = false;
5757 ret &= test_samr_handle_Close(p, tctx, &domain_handle);
5759 /* reconnect the main handle */
5760 ret &= test_Connect(p, tctx, handle);
5762 if (!ret) {
5763 printf("Testing domain %s failed!\n", dom_sid_string(tctx, sid));
5766 return ret;
5769 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5770 struct policy_handle *handle, const char *domain,
5771 enum torture_samr_choice which_ops,
5772 struct cli_credentials *machine_credentials)
5774 NTSTATUS status;
5775 struct samr_LookupDomain r;
5776 struct dom_sid2 *sid = NULL;
5777 struct lsa_String n1;
5778 struct lsa_String n2;
5779 bool ret = true;
5781 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
5783 /* check for correct error codes */
5784 r.in.connect_handle = handle;
5785 r.in.domain_name = &n2;
5786 r.out.sid = &sid;
5787 n2.string = NULL;
5789 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5790 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
5792 init_lsa_String(&n2, "xxNODOMAINxx");
5794 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5795 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
5797 r.in.connect_handle = handle;
5799 init_lsa_String(&n1, domain);
5800 r.in.domain_name = &n1;
5802 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5803 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
5805 if (!test_GetDomPwInfo(p, tctx, &n1)) {
5806 ret = false;
5809 if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops,
5810 machine_credentials)) {
5811 ret = false;
5814 return ret;
5818 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
5819 struct policy_handle *handle, enum torture_samr_choice which_ops,
5820 struct cli_credentials *machine_credentials)
5822 NTSTATUS status;
5823 struct samr_EnumDomains r;
5824 uint32_t resume_handle = 0;
5825 uint32_t num_entries = 0;
5826 struct samr_SamArray *sam = NULL;
5827 int i;
5828 bool ret = true;
5830 r.in.connect_handle = handle;
5831 r.in.resume_handle = &resume_handle;
5832 r.in.buf_size = (uint32_t)-1;
5833 r.out.resume_handle = &resume_handle;
5834 r.out.num_entries = &num_entries;
5835 r.out.sam = &sam;
5837 status = dcerpc_samr_EnumDomains(p, tctx, &r);
5838 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
5840 if (!*r.out.sam) {
5841 return false;
5844 for (i=0;i<sam->count;i++) {
5845 if (!test_LookupDomain(p, tctx, handle,
5846 sam->entries[i].name.string, which_ops,
5847 machine_credentials)) {
5848 ret = false;
5852 status = dcerpc_samr_EnumDomains(p, tctx, &r);
5853 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
5855 return ret;
5859 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
5860 struct policy_handle *handle)
5862 NTSTATUS status;
5863 struct samr_Connect r;
5864 struct samr_Connect2 r2;
5865 struct samr_Connect3 r3;
5866 struct samr_Connect4 r4;
5867 struct samr_Connect5 r5;
5868 union samr_ConnectInfo info;
5869 struct policy_handle h;
5870 uint32_t level_out = 0;
5871 bool ret = true, got_handle = false;
5873 torture_comment(tctx, "testing samr_Connect\n");
5875 r.in.system_name = 0;
5876 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5877 r.out.connect_handle = &h;
5879 status = dcerpc_samr_Connect(p, tctx, &r);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
5882 ret = false;
5883 } else {
5884 got_handle = true;
5885 *handle = h;
5888 torture_comment(tctx, "testing samr_Connect2\n");
5890 r2.in.system_name = NULL;
5891 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5892 r2.out.connect_handle = &h;
5894 status = dcerpc_samr_Connect2(p, tctx, &r2);
5895 if (!NT_STATUS_IS_OK(status)) {
5896 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
5897 ret = false;
5898 } else {
5899 if (got_handle) {
5900 test_samr_handle_Close(p, tctx, handle);
5902 got_handle = true;
5903 *handle = h;
5906 torture_comment(tctx, "testing samr_Connect3\n");
5908 r3.in.system_name = NULL;
5909 r3.in.unknown = 0;
5910 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5911 r3.out.connect_handle = &h;
5913 status = dcerpc_samr_Connect3(p, tctx, &r3);
5914 if (!NT_STATUS_IS_OK(status)) {
5915 printf("Connect3 failed - %s\n", nt_errstr(status));
5916 ret = false;
5917 } else {
5918 if (got_handle) {
5919 test_samr_handle_Close(p, tctx, handle);
5921 got_handle = true;
5922 *handle = h;
5925 torture_comment(tctx, "testing samr_Connect4\n");
5927 r4.in.system_name = "";
5928 r4.in.client_version = 0;
5929 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5930 r4.out.connect_handle = &h;
5932 status = dcerpc_samr_Connect4(p, tctx, &r4);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 printf("Connect4 failed - %s\n", nt_errstr(status));
5935 ret = false;
5936 } else {
5937 if (got_handle) {
5938 test_samr_handle_Close(p, tctx, handle);
5940 got_handle = true;
5941 *handle = h;
5944 torture_comment(tctx, "testing samr_Connect5\n");
5946 info.info1.client_version = 0;
5947 info.info1.unknown2 = 0;
5949 r5.in.system_name = "";
5950 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5951 r5.in.level_in = 1;
5952 r5.out.level_out = &level_out;
5953 r5.in.info_in = &info;
5954 r5.out.info_out = &info;
5955 r5.out.connect_handle = &h;
5957 status = dcerpc_samr_Connect5(p, tctx, &r5);
5958 if (!NT_STATUS_IS_OK(status)) {
5959 printf("Connect5 failed - %s\n", nt_errstr(status));
5960 ret = false;
5961 } else {
5962 if (got_handle) {
5963 test_samr_handle_Close(p, tctx, handle);
5965 got_handle = true;
5966 *handle = h;
5969 return ret;
5973 bool torture_rpc_samr(struct torture_context *torture)
5975 NTSTATUS status;
5976 struct dcerpc_pipe *p;
5977 bool ret = true;
5978 struct policy_handle handle;
5980 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 return false;
5985 ret &= test_Connect(p, torture, &handle);
5987 ret &= test_QuerySecurity(p, torture, &handle);
5989 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
5991 ret &= test_SetDsrmPassword(p, torture, &handle);
5993 ret &= test_Shutdown(p, torture, &handle);
5995 ret &= test_samr_handle_Close(p, torture, &handle);
5997 return ret;
6001 bool torture_rpc_samr_users(struct torture_context *torture)
6003 NTSTATUS status;
6004 struct dcerpc_pipe *p;
6005 bool ret = true;
6006 struct policy_handle handle;
6008 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6009 if (!NT_STATUS_IS_OK(status)) {
6010 return false;
6013 ret &= test_Connect(p, torture, &handle);
6015 ret &= test_QuerySecurity(p, torture, &handle);
6017 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
6019 ret &= test_SetDsrmPassword(p, torture, &handle);
6021 ret &= test_Shutdown(p, torture, &handle);
6023 ret &= test_samr_handle_Close(p, torture, &handle);
6025 return ret;
6029 bool torture_rpc_samr_passwords(struct torture_context *torture)
6031 NTSTATUS status;
6032 struct dcerpc_pipe *p;
6033 bool ret = true;
6034 struct policy_handle handle;
6036 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6037 if (!NT_STATUS_IS_OK(status)) {
6038 return false;
6041 ret &= test_Connect(p, torture, &handle);
6043 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
6045 ret &= test_samr_handle_Close(p, torture, &handle);
6047 return ret;
6050 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
6051 struct dcerpc_pipe *p2,
6052 struct cli_credentials *machine_credentials)
6054 NTSTATUS status;
6055 struct dcerpc_pipe *p;
6056 bool ret = true;
6057 struct policy_handle handle;
6059 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6060 if (!NT_STATUS_IS_OK(status)) {
6061 return false;
6064 ret &= test_Connect(p, torture, &handle);
6066 ret &= test_EnumDomains(p, torture, &handle,
6067 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
6068 machine_credentials);
6070 ret &= test_samr_handle_Close(p, torture, &handle);
6072 return ret;
6075 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
6077 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
6078 struct torture_rpc_tcase *tcase;
6080 tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
6081 &ndr_table_samr,
6082 TEST_ACCOUNT_NAME_PWD);
6084 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
6085 torture_rpc_samr_pwdlastset);
6087 return suite;