s4:torture/rpc/samlogon.c: make use of dcerpc_binding_handle stubs
[Samba/nascimento.git] / source4 / torture / rpc / samr.c
blob9e2c8466de52dc636d0649a92861d3f39d0c279d
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for samr rpc operations
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7 Copyright (C) Guenther Deschner 2008-2010
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include <tevent.h>
26 #include "system/time.h"
27 #include "librpc/gen_ndr/lsa.h"
28 #include "librpc/gen_ndr/ndr_netlogon.h"
29 #include "librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "librpc/gen_ndr/ndr_samr_c.h"
31 #include "librpc/gen_ndr/ndr_lsa_c.h"
32 #include "../lib/crypto/crypto.h"
33 #include "libcli/auth/libcli_auth.h"
34 #include "libcli/security/security.h"
35 #include "torture/rpc/rpc.h"
36 #include "param/param.h"
37 #include "auth/gensec/gensec.h"
38 #include "auth/gensec/gensec_proto.h"
39 #include "../libcli/auth/schannel.h"
41 #include <unistd.h>
43 #define TEST_ACCOUNT_NAME "samrtorturetest"
44 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
45 #define TEST_ALIASNAME "samrtorturetestalias"
46 #define TEST_GROUPNAME "samrtorturetestgroup"
47 #define TEST_MACHINENAME "samrtestmach$"
48 #define TEST_DOMAINNAME "samrtestdom$"
50 enum torture_samr_choice {
51 TORTURE_SAMR_PASSWORDS,
52 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
53 TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
54 TORTURE_SAMR_PASSWORDS_LOCKOUT,
55 TORTURE_SAMR_USER_ATTRIBUTES,
56 TORTURE_SAMR_USER_PRIVILEGES,
57 TORTURE_SAMR_OTHER,
58 TORTURE_SAMR_MANY_ACCOUNTS,
59 TORTURE_SAMR_MANY_GROUPS,
60 TORTURE_SAMR_MANY_ALIASES
63 struct torture_samr_context {
64 struct policy_handle handle;
65 struct cli_credentials *machine_credentials;
66 enum torture_samr_choice choice;
67 uint32_t num_objects_large_dc;
70 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
71 struct torture_context *tctx,
72 struct policy_handle *handle);
74 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
75 struct torture_context *tctx,
76 struct policy_handle *handle);
78 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
79 struct torture_context *tctx,
80 struct policy_handle *handle);
82 static bool test_ChangePassword(struct dcerpc_pipe *p,
83 struct torture_context *tctx,
84 const char *acct_name,
85 struct policy_handle *domain_handle, char **password);
87 static void init_lsa_String(struct lsa_String *string, const char *s)
89 string->string = s;
92 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
94 string->string = s;
97 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
99 string->length = length;
100 string->size = length;
101 string->array = (uint16_t *)discard_const(s);
104 bool test_samr_handle_Close(struct dcerpc_binding_handle *b,
105 struct torture_context *tctx,
106 struct policy_handle *handle)
108 NTSTATUS status;
109 struct samr_Close r;
111 r.in.handle = handle;
112 r.out.handle = handle;
114 status = dcerpc_samr_Close_r(b, tctx, &r);
115 torture_assert_ntstatus_ok(tctx, status, "Close");
117 return true;
120 static bool test_Shutdown(struct dcerpc_binding_handle *b,
121 struct torture_context *tctx,
122 struct policy_handle *handle)
124 NTSTATUS status;
125 struct samr_Shutdown r;
127 if (!torture_setting_bool(tctx, "dangerous", false)) {
128 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
129 return true;
132 r.in.connect_handle = handle;
134 torture_comment(tctx, "testing samr_Shutdown\n");
136 status = dcerpc_samr_Shutdown_r(b, tctx, &r);
137 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
139 return true;
142 static bool test_SetDsrmPassword(struct dcerpc_binding_handle *b,
143 struct torture_context *tctx,
144 struct policy_handle *handle)
146 NTSTATUS status;
147 struct samr_SetDsrmPassword r;
148 struct lsa_String string;
149 struct samr_Password hash;
151 if (!torture_setting_bool(tctx, "dangerous", false)) {
152 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
155 E_md4hash("TeSTDSRM123", hash.hash);
157 init_lsa_String(&string, "Administrator");
159 r.in.name = &string;
160 r.in.unknown = 0;
161 r.in.hash = &hash;
163 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
165 status = dcerpc_samr_SetDsrmPassword_r(b, tctx, &r);
166 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
168 return true;
172 static bool test_QuerySecurity(struct dcerpc_binding_handle *b,
173 struct torture_context *tctx,
174 struct policy_handle *handle)
176 NTSTATUS status;
177 struct samr_QuerySecurity r;
178 struct samr_SetSecurity s;
179 struct sec_desc_buf *sdbuf = NULL;
181 r.in.handle = handle;
182 r.in.sec_info = 7;
183 r.out.sdbuf = &sdbuf;
185 status = dcerpc_samr_QuerySecurity_r(b, tctx, &r);
186 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
188 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
190 s.in.handle = handle;
191 s.in.sec_info = 7;
192 s.in.sdbuf = sdbuf;
194 if (torture_setting_bool(tctx, "samba4", false)) {
195 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
198 status = dcerpc_samr_SetSecurity_r(b, tctx, &s);
199 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
201 status = dcerpc_samr_QuerySecurity_r(b, tctx, &r);
202 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
204 return true;
208 static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_context *tctx,
209 struct policy_handle *handle, uint32_t base_acct_flags,
210 const char *base_account_name)
212 NTSTATUS status;
213 struct samr_SetUserInfo s;
214 struct samr_SetUserInfo2 s2;
215 struct samr_QueryUserInfo q;
216 struct samr_QueryUserInfo q0;
217 union samr_UserInfo u;
218 union samr_UserInfo *info;
219 bool ret = true;
220 const char *test_account_name;
222 uint32_t user_extra_flags = 0;
224 if (!torture_setting_bool(tctx, "samba3", false)) {
225 if (base_acct_flags == ACB_NORMAL) {
226 /* When created, accounts are expired by default */
227 user_extra_flags = ACB_PW_EXPIRED;
231 s.in.user_handle = handle;
232 s.in.info = &u;
234 s2.in.user_handle = handle;
235 s2.in.info = &u;
237 q.in.user_handle = handle;
238 q.out.info = &info;
239 q0 = q;
241 #define TESTCALL(call, r) \
242 status = dcerpc_samr_ ##call## _r(b, tctx, &r); \
243 if (!NT_STATUS_IS_OK(status)) { \
244 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
245 r.in.level, nt_errstr(status), __location__); \
246 ret = false; \
247 break; \
250 #define STRING_EQUAL(s1, s2, field) \
251 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
252 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
253 #field, s2, __location__); \
254 ret = false; \
255 break; \
258 #define MEM_EQUAL(s1, s2, length, field) \
259 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
260 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
261 #field, (const char *)s2, __location__); \
262 ret = false; \
263 break; \
266 #define INT_EQUAL(i1, i2, field) \
267 if (i1 != i2) { \
268 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
269 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
270 ret = false; \
271 break; \
274 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
275 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
276 q.in.level = lvl1; \
277 TESTCALL(QueryUserInfo, q) \
278 s.in.level = lvl1; \
279 s2.in.level = lvl1; \
280 u = *info; \
281 if (lvl1 == 21) { \
282 ZERO_STRUCT(u.info21); \
283 u.info21.fields_present = fpval; \
285 init_lsa_String(&u.info ## lvl1.field1, value); \
286 TESTCALL(SetUserInfo, s) \
287 TESTCALL(SetUserInfo2, s2) \
288 init_lsa_String(&u.info ## lvl1.field1, ""); \
289 TESTCALL(QueryUserInfo, q); \
290 u = *info; \
291 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
292 q.in.level = lvl2; \
293 TESTCALL(QueryUserInfo, q) \
294 u = *info; \
295 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
296 } while (0)
298 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
299 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
300 q.in.level = lvl1; \
301 TESTCALL(QueryUserInfo, q) \
302 s.in.level = lvl1; \
303 s2.in.level = lvl1; \
304 u = *info; \
305 if (lvl1 == 21) { \
306 ZERO_STRUCT(u.info21); \
307 u.info21.fields_present = fpval; \
309 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
310 TESTCALL(SetUserInfo, s) \
311 TESTCALL(SetUserInfo2, s2) \
312 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
313 TESTCALL(QueryUserInfo, q); \
314 u = *info; \
315 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
316 q.in.level = lvl2; \
317 TESTCALL(QueryUserInfo, q) \
318 u = *info; \
319 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
320 } while (0)
322 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
323 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
324 q.in.level = lvl1; \
325 TESTCALL(QueryUserInfo, q) \
326 s.in.level = lvl1; \
327 s2.in.level = lvl1; \
328 u = *info; \
329 if (lvl1 == 21) { \
330 uint8_t *bits = u.info21.logon_hours.bits; \
331 ZERO_STRUCT(u.info21); \
332 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
333 u.info21.logon_hours.units_per_week = 168; \
334 u.info21.logon_hours.bits = bits; \
336 u.info21.fields_present = fpval; \
338 u.info ## lvl1.field1 = value; \
339 TESTCALL(SetUserInfo, s) \
340 TESTCALL(SetUserInfo2, s2) \
341 u.info ## lvl1.field1 = 0; \
342 TESTCALL(QueryUserInfo, q); \
343 u = *info; \
344 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
345 q.in.level = lvl2; \
346 TESTCALL(QueryUserInfo, q) \
347 u = *info; \
348 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
349 } while (0)
351 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
352 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
353 } while (0)
355 q0.in.level = 12;
356 do { TESTCALL(QueryUserInfo, q0) } while (0);
358 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
359 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
360 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
361 SAMR_FIELD_COMMENT);
363 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
364 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
365 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
366 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
367 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
368 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
369 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
370 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
371 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
372 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
373 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
374 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
375 test_account_name = base_account_name;
376 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
377 SAMR_FIELD_ACCOUNT_NAME);
379 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
380 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
381 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
382 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
383 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
384 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
385 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
386 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
387 SAMR_FIELD_FULL_NAME);
389 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
390 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
391 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
392 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
393 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
394 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
395 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
396 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
397 SAMR_FIELD_FULL_NAME);
399 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
400 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
401 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
402 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
403 SAMR_FIELD_LOGON_SCRIPT);
405 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
406 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
407 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
408 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
409 SAMR_FIELD_PROFILE_PATH);
411 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
412 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
413 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
414 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
415 SAMR_FIELD_HOME_DIRECTORY);
416 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
417 SAMR_FIELD_HOME_DIRECTORY);
419 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
420 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
421 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
422 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
423 SAMR_FIELD_HOME_DRIVE);
424 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
425 SAMR_FIELD_HOME_DRIVE);
427 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
428 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
429 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
430 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
431 SAMR_FIELD_DESCRIPTION);
433 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
434 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
435 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
436 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
437 SAMR_FIELD_WORKSTATIONS);
438 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
439 SAMR_FIELD_WORKSTATIONS);
440 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
441 SAMR_FIELD_WORKSTATIONS);
442 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
443 SAMR_FIELD_WORKSTATIONS);
445 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
446 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
447 SAMR_FIELD_PARAMETERS);
448 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
449 SAMR_FIELD_PARAMETERS);
450 /* also empty user parameters are allowed */
451 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
452 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
453 SAMR_FIELD_PARAMETERS);
454 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
455 SAMR_FIELD_PARAMETERS);
457 /* Samba 3 cannot store country_code and copy_page atm. - gd */
458 if (!torture_setting_bool(tctx, "samba3", false)) {
459 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
460 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
461 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
462 SAMR_FIELD_COUNTRY_CODE);
463 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
464 SAMR_FIELD_COUNTRY_CODE);
466 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
467 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
468 SAMR_FIELD_CODE_PAGE);
469 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
470 SAMR_FIELD_CODE_PAGE);
473 if (!torture_setting_bool(tctx, "samba3", false)) {
474 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
475 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
476 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
477 SAMR_FIELD_ACCT_EXPIRY);
478 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
479 SAMR_FIELD_ACCT_EXPIRY);
480 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
481 SAMR_FIELD_ACCT_EXPIRY);
482 } else {
483 /* Samba 3 can only store seconds / time_t in passdb - gd */
484 NTTIME nt;
485 unix_to_nt_time(&nt, time(NULL) + __LINE__);
486 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
487 unix_to_nt_time(&nt, time(NULL) + __LINE__);
488 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
489 unix_to_nt_time(&nt, time(NULL) + __LINE__);
490 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
491 unix_to_nt_time(&nt, time(NULL) + __LINE__);
492 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
493 unix_to_nt_time(&nt, time(NULL) + __LINE__);
494 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
497 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
498 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
499 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
500 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
501 SAMR_FIELD_LOGON_HOURS);
503 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
504 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
505 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
507 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
508 (base_acct_flags | ACB_DISABLED),
509 (base_acct_flags | ACB_DISABLED | user_extra_flags),
512 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
513 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
514 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
515 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
517 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
518 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
519 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
523 /* The 'autolock' flag doesn't stick - check this */
524 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
525 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
526 (base_acct_flags | ACB_DISABLED | user_extra_flags),
528 #if 0
529 /* Removing the 'disabled' flag doesn't stick - check this */
530 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
531 (base_acct_flags),
532 (base_acct_flags | ACB_DISABLED | user_extra_flags),
534 #endif
536 /* Samba3 cannot store these atm */
537 if (!torture_setting_bool(tctx, "samba3", false)) {
538 /* The 'store plaintext' flag does stick */
539 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
540 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
541 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
543 /* The 'use DES' flag does stick */
544 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
545 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
546 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
548 /* The 'don't require kerberos pre-authentication flag does stick */
549 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
550 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
551 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
553 /* The 'no kerberos PAC required' flag sticks */
554 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
555 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
556 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
559 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
560 (base_acct_flags | ACB_DISABLED),
561 (base_acct_flags | ACB_DISABLED | user_extra_flags),
562 SAMR_FIELD_ACCT_FLAGS);
564 #if 0
565 /* these fail with win2003 - it appears you can't set the primary gid?
566 the set succeeds, but the gid isn't changed. Very weird! */
567 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
568 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
569 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
570 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
571 #endif
573 return ret;
577 generate a random password for password change tests
579 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
581 size_t len = MAX(8, min_len);
582 char *s = generate_random_password(mem_ctx, len, len+6);
583 return s;
586 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
588 char *s = samr_rand_pass_silent(mem_ctx, min_len);
589 printf("Generated password '%s'\n", s);
590 return s;
595 generate a random password for password change tests
597 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
599 int i;
600 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
601 generate_random_buffer(password.data, password.length);
603 for (i=0; i < len; i++) {
604 if (((uint16_t *)password.data)[i] == 0) {
605 ((uint16_t *)password.data)[i] = 1;
609 return password;
613 generate a random password for password change tests (fixed length)
615 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
617 char *s = generate_random_password(mem_ctx, len, len);
618 printf("Generated password '%s'\n", s);
619 return s;
622 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
623 struct policy_handle *handle, char **password)
625 NTSTATUS status;
626 struct samr_SetUserInfo s;
627 union samr_UserInfo u;
628 bool ret = true;
629 DATA_BLOB session_key;
630 char *newpass;
631 struct dcerpc_binding_handle *b = p->binding_handle;
632 struct samr_GetUserPwInfo pwp;
633 struct samr_PwInfo info;
634 int policy_min_pw_len = 0;
635 pwp.in.user_handle = handle;
636 pwp.out.info = &info;
638 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp);
639 if (NT_STATUS_IS_OK(status)) {
640 policy_min_pw_len = pwp.out.info->min_password_length;
642 newpass = samr_rand_pass(tctx, policy_min_pw_len);
644 s.in.user_handle = handle;
645 s.in.info = &u;
646 s.in.level = 24;
648 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
649 u.info24.password_expired = 0;
651 status = dcerpc_fetch_session_key(p, &session_key);
652 if (!NT_STATUS_IS_OK(status)) {
653 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
654 s.in.level, nt_errstr(status));
655 return false;
658 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
660 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
662 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
663 if (!NT_STATUS_IS_OK(status)) {
664 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
665 s.in.level, nt_errstr(status));
666 ret = false;
667 } else {
668 *password = newpass;
671 return ret;
675 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
676 struct policy_handle *handle, uint32_t fields_present,
677 char **password)
679 NTSTATUS status;
680 struct samr_SetUserInfo s;
681 union samr_UserInfo u;
682 bool ret = true;
683 DATA_BLOB session_key;
684 struct dcerpc_binding_handle *b = p->binding_handle;
685 char *newpass;
686 struct samr_GetUserPwInfo pwp;
687 struct samr_PwInfo info;
688 int policy_min_pw_len = 0;
689 pwp.in.user_handle = handle;
690 pwp.out.info = &info;
692 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp);
693 if (NT_STATUS_IS_OK(status)) {
694 policy_min_pw_len = pwp.out.info->min_password_length;
696 newpass = samr_rand_pass(tctx, policy_min_pw_len);
698 s.in.user_handle = handle;
699 s.in.info = &u;
700 s.in.level = 23;
702 ZERO_STRUCT(u);
704 u.info23.info.fields_present = fields_present;
706 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
708 status = dcerpc_fetch_session_key(p, &session_key);
709 if (!NT_STATUS_IS_OK(status)) {
710 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
711 s.in.level, nt_errstr(status));
712 return false;
715 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
717 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
719 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
720 if (!NT_STATUS_IS_OK(status)) {
721 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
722 s.in.level, nt_errstr(status));
723 ret = false;
724 } else {
725 *password = newpass;
728 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
730 status = dcerpc_fetch_session_key(p, &session_key);
731 if (!NT_STATUS_IS_OK(status)) {
732 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
733 s.in.level, nt_errstr(status));
734 return false;
737 /* This should break the key nicely */
738 session_key.length--;
739 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
741 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
743 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
744 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
745 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
746 s.in.level, nt_errstr(status));
747 ret = false;
750 return ret;
754 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
755 struct policy_handle *handle, bool makeshort,
756 char **password)
758 NTSTATUS status;
759 struct samr_SetUserInfo s;
760 union samr_UserInfo u;
761 bool ret = true;
762 DATA_BLOB session_key;
763 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
764 uint8_t confounder[16];
765 char *newpass;
766 struct dcerpc_binding_handle *b = p->binding_handle;
767 struct MD5Context ctx;
768 struct samr_GetUserPwInfo pwp;
769 struct samr_PwInfo info;
770 int policy_min_pw_len = 0;
771 pwp.in.user_handle = handle;
772 pwp.out.info = &info;
774 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp);
775 if (NT_STATUS_IS_OK(status)) {
776 policy_min_pw_len = pwp.out.info->min_password_length;
778 if (makeshort && policy_min_pw_len) {
779 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
780 } else {
781 newpass = samr_rand_pass(tctx, policy_min_pw_len);
784 s.in.user_handle = handle;
785 s.in.info = &u;
786 s.in.level = 26;
788 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
789 u.info26.password_expired = 0;
791 status = dcerpc_fetch_session_key(p, &session_key);
792 if (!NT_STATUS_IS_OK(status)) {
793 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
794 s.in.level, nt_errstr(status));
795 return false;
798 generate_random_buffer((uint8_t *)confounder, 16);
800 MD5Init(&ctx);
801 MD5Update(&ctx, confounder, 16);
802 MD5Update(&ctx, session_key.data, session_key.length);
803 MD5Final(confounded_session_key.data, &ctx);
805 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
806 memcpy(&u.info26.password.data[516], confounder, 16);
808 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
810 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
811 if (!NT_STATUS_IS_OK(status)) {
812 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
813 s.in.level, nt_errstr(status));
814 ret = false;
815 } else {
816 *password = newpass;
819 /* This should break the key nicely */
820 confounded_session_key.data[0]++;
822 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
823 memcpy(&u.info26.password.data[516], confounder, 16);
825 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
827 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
828 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
829 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
830 s.in.level, nt_errstr(status));
831 ret = false;
832 } else {
833 *password = newpass;
836 return ret;
839 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
840 struct policy_handle *handle, uint32_t fields_present,
841 char **password)
843 NTSTATUS status;
844 struct samr_SetUserInfo s;
845 union samr_UserInfo u;
846 bool ret = true;
847 DATA_BLOB session_key;
848 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
849 struct MD5Context ctx;
850 uint8_t confounder[16];
851 char *newpass;
852 struct dcerpc_binding_handle *b = p->binding_handle;
853 struct samr_GetUserPwInfo pwp;
854 struct samr_PwInfo info;
855 int policy_min_pw_len = 0;
856 pwp.in.user_handle = handle;
857 pwp.out.info = &info;
859 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp);
860 if (NT_STATUS_IS_OK(status)) {
861 policy_min_pw_len = pwp.out.info->min_password_length;
863 newpass = samr_rand_pass(tctx, policy_min_pw_len);
865 s.in.user_handle = handle;
866 s.in.info = &u;
867 s.in.level = 25;
869 ZERO_STRUCT(u);
871 u.info25.info.fields_present = fields_present;
873 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
875 status = dcerpc_fetch_session_key(p, &session_key);
876 if (!NT_STATUS_IS_OK(status)) {
877 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
878 s.in.level, nt_errstr(status));
879 return false;
882 generate_random_buffer((uint8_t *)confounder, 16);
884 MD5Init(&ctx);
885 MD5Update(&ctx, confounder, 16);
886 MD5Update(&ctx, session_key.data, session_key.length);
887 MD5Final(confounded_session_key.data, &ctx);
889 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
890 memcpy(&u.info25.password.data[516], confounder, 16);
892 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
894 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
895 if (!NT_STATUS_IS_OK(status)) {
896 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
897 s.in.level, nt_errstr(status));
898 ret = false;
899 } else {
900 *password = newpass;
903 /* This should break the key nicely */
904 confounded_session_key.data[0]++;
906 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
907 memcpy(&u.info25.password.data[516], confounder, 16);
909 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
911 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
912 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
913 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
914 s.in.level, nt_errstr(status));
915 ret = false;
918 return ret;
921 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
922 struct policy_handle *handle, char **password)
924 NTSTATUS status;
925 struct samr_SetUserInfo s;
926 union samr_UserInfo u;
927 bool ret = true;
928 DATA_BLOB session_key;
929 char *newpass;
930 struct dcerpc_binding_handle *b = p->binding_handle;
931 struct samr_GetUserPwInfo pwp;
932 struct samr_PwInfo info;
933 int policy_min_pw_len = 0;
934 uint8_t lm_hash[16], nt_hash[16];
936 pwp.in.user_handle = handle;
937 pwp.out.info = &info;
939 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp);
940 if (NT_STATUS_IS_OK(status)) {
941 policy_min_pw_len = pwp.out.info->min_password_length;
943 newpass = samr_rand_pass(tctx, policy_min_pw_len);
945 s.in.user_handle = handle;
946 s.in.info = &u;
947 s.in.level = 18;
949 ZERO_STRUCT(u);
951 u.info18.nt_pwd_active = true;
952 u.info18.lm_pwd_active = true;
954 E_md4hash(newpass, nt_hash);
955 E_deshash(newpass, lm_hash);
957 status = dcerpc_fetch_session_key(p, &session_key);
958 if (!NT_STATUS_IS_OK(status)) {
959 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
960 s.in.level, nt_errstr(status));
961 return false;
965 DATA_BLOB in,out;
966 in = data_blob_const(nt_hash, 16);
967 out = data_blob_talloc_zero(tctx, 16);
968 sess_crypt_blob(&out, &in, &session_key, true);
969 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
972 DATA_BLOB in,out;
973 in = data_blob_const(lm_hash, 16);
974 out = data_blob_talloc_zero(tctx, 16);
975 sess_crypt_blob(&out, &in, &session_key, true);
976 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
979 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
981 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
982 if (!NT_STATUS_IS_OK(status)) {
983 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
984 s.in.level, nt_errstr(status));
985 ret = false;
986 } else {
987 *password = newpass;
990 return ret;
993 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
994 struct policy_handle *handle, uint32_t fields_present,
995 char **password)
997 NTSTATUS status;
998 struct samr_SetUserInfo s;
999 union samr_UserInfo u;
1000 bool ret = true;
1001 DATA_BLOB session_key;
1002 char *newpass;
1003 struct dcerpc_binding_handle *b = p->binding_handle;
1004 struct samr_GetUserPwInfo pwp;
1005 struct samr_PwInfo info;
1006 int policy_min_pw_len = 0;
1007 uint8_t lm_hash[16], nt_hash[16];
1009 pwp.in.user_handle = handle;
1010 pwp.out.info = &info;
1012 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp);
1013 if (NT_STATUS_IS_OK(status)) {
1014 policy_min_pw_len = pwp.out.info->min_password_length;
1016 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1018 s.in.user_handle = handle;
1019 s.in.info = &u;
1020 s.in.level = 21;
1022 E_md4hash(newpass, nt_hash);
1023 E_deshash(newpass, lm_hash);
1025 ZERO_STRUCT(u);
1027 u.info21.fields_present = fields_present;
1029 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1030 u.info21.lm_owf_password.length = 16;
1031 u.info21.lm_owf_password.size = 16;
1032 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1033 u.info21.lm_password_set = true;
1036 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1037 u.info21.nt_owf_password.length = 16;
1038 u.info21.nt_owf_password.size = 16;
1039 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1040 u.info21.nt_password_set = true;
1043 status = dcerpc_fetch_session_key(p, &session_key);
1044 if (!NT_STATUS_IS_OK(status)) {
1045 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1046 s.in.level, nt_errstr(status));
1047 return false;
1050 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1051 DATA_BLOB in,out;
1052 in = data_blob_const(u.info21.lm_owf_password.array,
1053 u.info21.lm_owf_password.length);
1054 out = data_blob_talloc_zero(tctx, 16);
1055 sess_crypt_blob(&out, &in, &session_key, true);
1056 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1059 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1060 DATA_BLOB in,out;
1061 in = data_blob_const(u.info21.nt_owf_password.array,
1062 u.info21.nt_owf_password.length);
1063 out = data_blob_talloc_zero(tctx, 16);
1064 sess_crypt_blob(&out, &in, &session_key, true);
1065 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1068 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1070 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
1071 if (!NT_STATUS_IS_OK(status)) {
1072 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1073 s.in.level, nt_errstr(status));
1074 ret = false;
1075 } else {
1076 *password = newpass;
1079 /* try invalid length */
1080 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1082 u.info21.nt_owf_password.length++;
1084 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
1086 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1087 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1088 s.in.level, nt_errstr(status));
1089 ret = false;
1093 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1095 u.info21.lm_owf_password.length++;
1097 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
1099 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1100 torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1101 s.in.level, nt_errstr(status));
1102 ret = false;
1106 return ret;
1109 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1110 struct torture_context *tctx,
1111 struct policy_handle *handle,
1112 uint16_t level,
1113 uint32_t fields_present,
1114 char **password, uint8_t password_expired,
1115 bool use_setinfo2,
1116 bool *matched_expected_error)
1118 NTSTATUS status;
1119 NTSTATUS expected_error = NT_STATUS_OK;
1120 struct samr_SetUserInfo s;
1121 struct samr_SetUserInfo2 s2;
1122 union samr_UserInfo u;
1123 bool ret = true;
1124 DATA_BLOB session_key;
1125 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1126 struct MD5Context ctx;
1127 uint8_t confounder[16];
1128 char *newpass;
1129 struct dcerpc_binding_handle *b = p->binding_handle;
1130 struct samr_GetUserPwInfo pwp;
1131 struct samr_PwInfo info;
1132 int policy_min_pw_len = 0;
1133 const char *comment = NULL;
1134 uint8_t lm_hash[16], nt_hash[16];
1136 pwp.in.user_handle = handle;
1137 pwp.out.info = &info;
1139 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp);
1140 if (NT_STATUS_IS_OK(status)) {
1141 policy_min_pw_len = pwp.out.info->min_password_length;
1143 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1145 if (use_setinfo2) {
1146 s2.in.user_handle = handle;
1147 s2.in.info = &u;
1148 s2.in.level = level;
1149 } else {
1150 s.in.user_handle = handle;
1151 s.in.info = &u;
1152 s.in.level = level;
1155 if (fields_present & SAMR_FIELD_COMMENT) {
1156 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1159 ZERO_STRUCT(u);
1161 switch (level) {
1162 case 18:
1163 E_md4hash(newpass, nt_hash);
1164 E_deshash(newpass, lm_hash);
1166 u.info18.nt_pwd_active = true;
1167 u.info18.lm_pwd_active = true;
1168 u.info18.password_expired = password_expired;
1170 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1171 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1173 break;
1174 case 21:
1175 E_md4hash(newpass, nt_hash);
1176 E_deshash(newpass, lm_hash);
1178 u.info21.fields_present = fields_present;
1179 u.info21.password_expired = password_expired;
1180 u.info21.comment.string = comment;
1182 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1183 u.info21.lm_owf_password.length = 16;
1184 u.info21.lm_owf_password.size = 16;
1185 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1186 u.info21.lm_password_set = true;
1189 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1190 u.info21.nt_owf_password.length = 16;
1191 u.info21.nt_owf_password.size = 16;
1192 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1193 u.info21.nt_password_set = true;
1196 break;
1197 case 23:
1198 u.info23.info.fields_present = fields_present;
1199 u.info23.info.password_expired = password_expired;
1200 u.info23.info.comment.string = comment;
1202 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1204 break;
1205 case 24:
1206 u.info24.password_expired = password_expired;
1208 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1210 break;
1211 case 25:
1212 u.info25.info.fields_present = fields_present;
1213 u.info25.info.password_expired = password_expired;
1214 u.info25.info.comment.string = comment;
1216 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1218 break;
1219 case 26:
1220 u.info26.password_expired = password_expired;
1222 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1224 break;
1227 status = dcerpc_fetch_session_key(p, &session_key);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1230 s.in.level, nt_errstr(status));
1231 return false;
1234 generate_random_buffer((uint8_t *)confounder, 16);
1236 MD5Init(&ctx);
1237 MD5Update(&ctx, confounder, 16);
1238 MD5Update(&ctx, session_key.data, session_key.length);
1239 MD5Final(confounded_session_key.data, &ctx);
1241 switch (level) {
1242 case 18:
1244 DATA_BLOB in,out;
1245 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1246 out = data_blob_talloc_zero(tctx, 16);
1247 sess_crypt_blob(&out, &in, &session_key, true);
1248 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1251 DATA_BLOB in,out;
1252 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1253 out = data_blob_talloc_zero(tctx, 16);
1254 sess_crypt_blob(&out, &in, &session_key, true);
1255 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1258 break;
1259 case 21:
1260 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1261 DATA_BLOB in,out;
1262 in = data_blob_const(u.info21.lm_owf_password.array,
1263 u.info21.lm_owf_password.length);
1264 out = data_blob_talloc_zero(tctx, 16);
1265 sess_crypt_blob(&out, &in, &session_key, true);
1266 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1268 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1269 DATA_BLOB in,out;
1270 in = data_blob_const(u.info21.nt_owf_password.array,
1271 u.info21.nt_owf_password.length);
1272 out = data_blob_talloc_zero(tctx, 16);
1273 sess_crypt_blob(&out, &in, &session_key, true);
1274 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1276 break;
1277 case 23:
1278 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1279 break;
1280 case 24:
1281 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1282 break;
1283 case 25:
1284 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1285 memcpy(&u.info25.password.data[516], confounder, 16);
1286 break;
1287 case 26:
1288 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1289 memcpy(&u.info26.password.data[516], confounder, 16);
1290 break;
1293 if (use_setinfo2) {
1294 status = dcerpc_samr_SetUserInfo2_r(b, tctx, &s2);
1295 } else {
1296 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
1299 if (!NT_STATUS_IS_OK(status)) {
1300 if (fields_present == 0) {
1301 expected_error = NT_STATUS_INVALID_PARAMETER;
1303 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1304 expected_error = NT_STATUS_ACCESS_DENIED;
1308 if (!NT_STATUS_IS_OK(expected_error)) {
1309 if (use_setinfo2) {
1310 torture_assert_ntstatus_equal(tctx,
1311 s2.out.result,
1312 expected_error, "SetUserInfo2 failed");
1313 } else {
1314 torture_assert_ntstatus_equal(tctx,
1315 s.out.result,
1316 expected_error, "SetUserInfo failed");
1318 *matched_expected_error = true;
1319 return true;
1322 if (!NT_STATUS_IS_OK(status)) {
1323 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1324 use_setinfo2 ? "2":"", level, nt_errstr(status));
1325 ret = false;
1326 } else {
1327 *password = newpass;
1330 return ret;
1333 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1334 struct torture_context *tctx,
1335 struct policy_handle *handle)
1337 NTSTATUS status;
1338 struct samr_SetAliasInfo r;
1339 struct samr_QueryAliasInfo q;
1340 union samr_AliasInfo *info;
1341 uint16_t levels[] = {2, 3};
1342 int i;
1343 bool ret = true;
1345 /* Ignoring switch level 1, as that includes the number of members for the alias
1346 * and setting this to a wrong value might have negative consequences
1349 for (i=0;i<ARRAY_SIZE(levels);i++) {
1350 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1352 r.in.alias_handle = handle;
1353 r.in.level = levels[i];
1354 r.in.info = talloc(tctx, union samr_AliasInfo);
1355 switch (r.in.level) {
1356 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1357 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1358 "Test Description, should test I18N as well"); break;
1359 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1362 status = dcerpc_samr_SetAliasInfo_r(b, tctx, &r);
1363 if (!NT_STATUS_IS_OK(status)) {
1364 torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1365 levels[i], nt_errstr(status));
1366 ret = false;
1369 q.in.alias_handle = handle;
1370 q.in.level = levels[i];
1371 q.out.info = &info;
1373 status = dcerpc_samr_QueryAliasInfo_r(b, tctx, &q);
1374 if (!NT_STATUS_IS_OK(status)) {
1375 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1376 levels[i], nt_errstr(status));
1377 ret = false;
1381 return ret;
1384 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1385 struct torture_context *tctx,
1386 struct policy_handle *user_handle)
1388 struct samr_GetGroupsForUser r;
1389 struct samr_RidWithAttributeArray *rids = NULL;
1390 NTSTATUS status;
1392 torture_comment(tctx, "testing GetGroupsForUser\n");
1394 r.in.user_handle = user_handle;
1395 r.out.rids = &rids;
1397 status = dcerpc_samr_GetGroupsForUser_r(b, tctx, &r);
1398 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1400 return true;
1404 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1405 struct lsa_String *domain_name)
1407 NTSTATUS status;
1408 struct samr_GetDomPwInfo r;
1409 struct samr_PwInfo info;
1410 struct dcerpc_binding_handle *b = p->binding_handle;
1412 r.in.domain_name = domain_name;
1413 r.out.info = &info;
1415 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1417 status = dcerpc_samr_GetDomPwInfo_r(b, tctx, &r);
1418 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1420 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1421 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1423 status = dcerpc_samr_GetDomPwInfo_r(b, tctx, &r);
1424 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1426 r.in.domain_name->string = "\\\\__NONAME__";
1427 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1429 status = dcerpc_samr_GetDomPwInfo_r(b, tctx, &r);
1430 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1432 r.in.domain_name->string = "\\\\Builtin";
1433 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1435 status = dcerpc_samr_GetDomPwInfo_r(b, tctx, &r);
1436 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1438 return true;
1441 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1442 struct torture_context *tctx,
1443 struct policy_handle *handle)
1445 NTSTATUS status;
1446 struct samr_GetUserPwInfo r;
1447 struct samr_PwInfo info;
1449 torture_comment(tctx, "Testing GetUserPwInfo\n");
1451 r.in.user_handle = handle;
1452 r.out.info = &info;
1454 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &r);
1455 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1457 return true;
1460 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1461 struct torture_context *tctx,
1462 struct policy_handle *domain_handle, const char *name,
1463 uint32_t *rid)
1465 NTSTATUS status;
1466 struct samr_LookupNames n;
1467 struct lsa_String sname[2];
1468 struct samr_Ids rids, types;
1470 init_lsa_String(&sname[0], name);
1472 n.in.domain_handle = domain_handle;
1473 n.in.num_names = 1;
1474 n.in.names = sname;
1475 n.out.rids = &rids;
1476 n.out.types = &types;
1477 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1478 if (NT_STATUS_IS_OK(status)) {
1479 *rid = n.out.rids->ids[0];
1480 } else {
1481 return status;
1484 init_lsa_String(&sname[1], "xxNONAMExx");
1485 n.in.num_names = 2;
1486 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1487 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1488 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(status));
1489 if (NT_STATUS_IS_OK(status)) {
1490 return NT_STATUS_UNSUCCESSFUL;
1492 return status;
1495 n.in.num_names = 0;
1496 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1497 if (!NT_STATUS_IS_OK(status)) {
1498 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1499 return status;
1502 init_lsa_String(&sname[0], "xxNONAMExx");
1503 n.in.num_names = 1;
1504 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1505 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1506 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1507 if (NT_STATUS_IS_OK(status)) {
1508 return NT_STATUS_UNSUCCESSFUL;
1510 return status;
1513 init_lsa_String(&sname[0], "xxNONAMExx");
1514 init_lsa_String(&sname[1], "xxNONAME2xx");
1515 n.in.num_names = 2;
1516 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1517 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1518 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1519 if (NT_STATUS_IS_OK(status)) {
1520 return NT_STATUS_UNSUCCESSFUL;
1522 return status;
1525 return NT_STATUS_OK;
1528 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1529 struct torture_context *tctx,
1530 struct policy_handle *domain_handle,
1531 const char *name, struct policy_handle *user_handle)
1533 NTSTATUS status;
1534 struct samr_OpenUser r;
1535 uint32_t rid;
1537 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1538 if (!NT_STATUS_IS_OK(status)) {
1539 return status;
1542 r.in.domain_handle = domain_handle;
1543 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1544 r.in.rid = rid;
1545 r.out.user_handle = user_handle;
1546 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1547 if (!NT_STATUS_IS_OK(status)) {
1548 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1551 return status;
1554 #if 0
1555 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1556 struct torture_context *tctx,
1557 struct policy_handle *handle)
1559 NTSTATUS status;
1560 struct samr_ChangePasswordUser r;
1561 bool ret = true;
1562 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1563 struct policy_handle user_handle;
1564 char *oldpass = "test";
1565 char *newpass = "test2";
1566 uint8_t old_nt_hash[16], new_nt_hash[16];
1567 uint8_t old_lm_hash[16], new_lm_hash[16];
1569 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1570 if (!NT_STATUS_IS_OK(status)) {
1571 return false;
1574 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1576 torture_comment(tctx, "old password: %s\n", oldpass);
1577 torture_comment(tctx, "new password: %s\n", newpass);
1579 E_md4hash(oldpass, old_nt_hash);
1580 E_md4hash(newpass, new_nt_hash);
1581 E_deshash(oldpass, old_lm_hash);
1582 E_deshash(newpass, new_lm_hash);
1584 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1585 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1586 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1587 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1588 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1589 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1591 r.in.handle = &user_handle;
1592 r.in.lm_present = 1;
1593 r.in.old_lm_crypted = &hash1;
1594 r.in.new_lm_crypted = &hash2;
1595 r.in.nt_present = 1;
1596 r.in.old_nt_crypted = &hash3;
1597 r.in.new_nt_crypted = &hash4;
1598 r.in.cross1_present = 1;
1599 r.in.nt_cross = &hash5;
1600 r.in.cross2_present = 1;
1601 r.in.lm_cross = &hash6;
1603 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1604 if (!NT_STATUS_IS_OK(status)) {
1605 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
1606 ret = false;
1609 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1610 ret = false;
1613 return ret;
1615 #endif
1617 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1618 struct torture_context *tctx,
1619 const char *acct_name,
1620 struct policy_handle *handle, char **password)
1622 NTSTATUS status;
1623 struct samr_ChangePasswordUser r;
1624 bool ret = true;
1625 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1626 struct policy_handle user_handle;
1627 char *oldpass;
1628 uint8_t old_nt_hash[16], new_nt_hash[16];
1629 uint8_t old_lm_hash[16], new_lm_hash[16];
1630 bool changed = true;
1632 char *newpass;
1633 struct samr_GetUserPwInfo pwp;
1634 struct samr_PwInfo info;
1635 int policy_min_pw_len = 0;
1637 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1638 if (!NT_STATUS_IS_OK(status)) {
1639 return false;
1641 pwp.in.user_handle = &user_handle;
1642 pwp.out.info = &info;
1644 status = dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp);
1645 if (NT_STATUS_IS_OK(status)) {
1646 policy_min_pw_len = pwp.out.info->min_password_length;
1648 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1650 torture_comment(tctx, "Testing ChangePasswordUser\n");
1652 torture_assert(tctx, *password != NULL,
1653 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1655 oldpass = *password;
1657 E_md4hash(oldpass, old_nt_hash);
1658 E_md4hash(newpass, new_nt_hash);
1659 E_deshash(oldpass, old_lm_hash);
1660 E_deshash(newpass, new_lm_hash);
1662 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1663 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1664 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1665 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1666 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1667 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1669 r.in.user_handle = &user_handle;
1670 r.in.lm_present = 1;
1671 /* Break the LM hash */
1672 hash1.hash[0]++;
1673 r.in.old_lm_crypted = &hash1;
1674 r.in.new_lm_crypted = &hash2;
1675 r.in.nt_present = 1;
1676 r.in.old_nt_crypted = &hash3;
1677 r.in.new_nt_crypted = &hash4;
1678 r.in.cross1_present = 1;
1679 r.in.nt_cross = &hash5;
1680 r.in.cross2_present = 1;
1681 r.in.lm_cross = &hash6;
1683 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1684 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1685 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1687 /* Unbreak the LM hash */
1688 hash1.hash[0]--;
1690 r.in.user_handle = &user_handle;
1691 r.in.lm_present = 1;
1692 r.in.old_lm_crypted = &hash1;
1693 r.in.new_lm_crypted = &hash2;
1694 /* Break the NT hash */
1695 hash3.hash[0]--;
1696 r.in.nt_present = 1;
1697 r.in.old_nt_crypted = &hash3;
1698 r.in.new_nt_crypted = &hash4;
1699 r.in.cross1_present = 1;
1700 r.in.nt_cross = &hash5;
1701 r.in.cross2_present = 1;
1702 r.in.lm_cross = &hash6;
1704 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1705 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1706 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1708 /* Unbreak the NT hash */
1709 hash3.hash[0]--;
1711 r.in.user_handle = &user_handle;
1712 r.in.lm_present = 1;
1713 r.in.old_lm_crypted = &hash1;
1714 r.in.new_lm_crypted = &hash2;
1715 r.in.nt_present = 1;
1716 r.in.old_nt_crypted = &hash3;
1717 r.in.new_nt_crypted = &hash4;
1718 r.in.cross1_present = 1;
1719 r.in.nt_cross = &hash5;
1720 r.in.cross2_present = 1;
1721 /* Break the LM cross */
1722 hash6.hash[0]++;
1723 r.in.lm_cross = &hash6;
1725 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1726 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1727 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1728 ret = false;
1731 /* Unbreak the LM cross */
1732 hash6.hash[0]--;
1734 r.in.user_handle = &user_handle;
1735 r.in.lm_present = 1;
1736 r.in.old_lm_crypted = &hash1;
1737 r.in.new_lm_crypted = &hash2;
1738 r.in.nt_present = 1;
1739 r.in.old_nt_crypted = &hash3;
1740 r.in.new_nt_crypted = &hash4;
1741 r.in.cross1_present = 1;
1742 /* Break the NT cross */
1743 hash5.hash[0]++;
1744 r.in.nt_cross = &hash5;
1745 r.in.cross2_present = 1;
1746 r.in.lm_cross = &hash6;
1748 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1749 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1750 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1751 ret = false;
1754 /* Unbreak the NT cross */
1755 hash5.hash[0]--;
1758 /* Reset the hashes to not broken values */
1759 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1760 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1761 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1762 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1763 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1764 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1766 r.in.user_handle = &user_handle;
1767 r.in.lm_present = 1;
1768 r.in.old_lm_crypted = &hash1;
1769 r.in.new_lm_crypted = &hash2;
1770 r.in.nt_present = 1;
1771 r.in.old_nt_crypted = &hash3;
1772 r.in.new_nt_crypted = &hash4;
1773 r.in.cross1_present = 1;
1774 r.in.nt_cross = &hash5;
1775 r.in.cross2_present = 0;
1776 r.in.lm_cross = NULL;
1778 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1779 if (NT_STATUS_IS_OK(status)) {
1780 changed = true;
1781 *password = newpass;
1782 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1783 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1784 ret = false;
1787 oldpass = newpass;
1788 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1790 E_md4hash(oldpass, old_nt_hash);
1791 E_md4hash(newpass, new_nt_hash);
1792 E_deshash(oldpass, old_lm_hash);
1793 E_deshash(newpass, new_lm_hash);
1796 /* Reset the hashes to not broken values */
1797 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1798 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1799 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1800 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1801 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1802 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1804 r.in.user_handle = &user_handle;
1805 r.in.lm_present = 1;
1806 r.in.old_lm_crypted = &hash1;
1807 r.in.new_lm_crypted = &hash2;
1808 r.in.nt_present = 1;
1809 r.in.old_nt_crypted = &hash3;
1810 r.in.new_nt_crypted = &hash4;
1811 r.in.cross1_present = 0;
1812 r.in.nt_cross = NULL;
1813 r.in.cross2_present = 1;
1814 r.in.lm_cross = &hash6;
1816 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1817 if (NT_STATUS_IS_OK(status)) {
1818 changed = true;
1819 *password = newpass;
1820 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1821 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1822 ret = false;
1825 oldpass = newpass;
1826 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1828 E_md4hash(oldpass, old_nt_hash);
1829 E_md4hash(newpass, new_nt_hash);
1830 E_deshash(oldpass, old_lm_hash);
1831 E_deshash(newpass, new_lm_hash);
1834 /* Reset the hashes to not broken values */
1835 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1836 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1837 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1838 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1839 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1840 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1842 r.in.user_handle = &user_handle;
1843 r.in.lm_present = 1;
1844 r.in.old_lm_crypted = &hash1;
1845 r.in.new_lm_crypted = &hash2;
1846 r.in.nt_present = 1;
1847 r.in.old_nt_crypted = &hash3;
1848 r.in.new_nt_crypted = &hash4;
1849 r.in.cross1_present = 1;
1850 r.in.nt_cross = &hash5;
1851 r.in.cross2_present = 1;
1852 r.in.lm_cross = &hash6;
1854 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1855 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1856 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1857 } else if (!NT_STATUS_IS_OK(status)) {
1858 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(status));
1859 ret = false;
1860 } else {
1861 changed = true;
1862 *password = newpass;
1865 r.in.user_handle = &user_handle;
1866 r.in.lm_present = 1;
1867 r.in.old_lm_crypted = &hash1;
1868 r.in.new_lm_crypted = &hash2;
1869 r.in.nt_present = 1;
1870 r.in.old_nt_crypted = &hash3;
1871 r.in.new_nt_crypted = &hash4;
1872 r.in.cross1_present = 1;
1873 r.in.nt_cross = &hash5;
1874 r.in.cross2_present = 1;
1875 r.in.lm_cross = &hash6;
1877 if (changed) {
1878 status = dcerpc_samr_ChangePasswordUser_r(b, tctx, &r);
1879 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1880 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1881 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1882 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1883 ret = false;
1888 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
1889 ret = false;
1892 return ret;
1896 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
1897 struct torture_context *tctx,
1898 const char *acct_name,
1899 struct policy_handle *handle, char **password)
1901 NTSTATUS status;
1902 struct samr_OemChangePasswordUser2 r;
1903 bool ret = true;
1904 struct samr_Password lm_verifier;
1905 struct samr_CryptPassword lm_pass;
1906 struct lsa_AsciiString server, account, account_bad;
1907 char *oldpass;
1908 char *newpass;
1909 struct dcerpc_binding_handle *b = p->binding_handle;
1910 uint8_t old_lm_hash[16], new_lm_hash[16];
1912 struct samr_GetDomPwInfo dom_pw_info;
1913 struct samr_PwInfo info;
1914 int policy_min_pw_len = 0;
1916 struct lsa_String domain_name;
1918 domain_name.string = "";
1919 dom_pw_info.in.domain_name = &domain_name;
1920 dom_pw_info.out.info = &info;
1922 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1924 torture_assert(tctx, *password != NULL,
1925 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1927 oldpass = *password;
1929 status = dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info);
1930 if (NT_STATUS_IS_OK(status)) {
1931 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1934 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1936 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1937 account.string = acct_name;
1939 E_deshash(oldpass, old_lm_hash);
1940 E_deshash(newpass, new_lm_hash);
1942 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1943 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1944 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1946 r.in.server = &server;
1947 r.in.account = &account;
1948 r.in.password = &lm_pass;
1949 r.in.hash = &lm_verifier;
1951 /* Break the verification */
1952 lm_verifier.hash[0]++;
1954 status = dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r);
1956 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1957 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1958 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1959 nt_errstr(status));
1960 ret = false;
1963 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1964 /* Break the old password */
1965 old_lm_hash[0]++;
1966 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1967 /* unbreak it for the next operation */
1968 old_lm_hash[0]--;
1969 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1971 r.in.server = &server;
1972 r.in.account = &account;
1973 r.in.password = &lm_pass;
1974 r.in.hash = &lm_verifier;
1976 status = dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r);
1978 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1979 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1980 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1981 nt_errstr(status));
1982 ret = false;
1985 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1986 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1988 r.in.server = &server;
1989 r.in.account = &account;
1990 r.in.password = &lm_pass;
1991 r.in.hash = NULL;
1993 status = dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r);
1995 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1996 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1997 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1998 nt_errstr(status));
1999 ret = false;
2002 /* This shouldn't be a valid name */
2003 account_bad.string = TEST_ACCOUNT_NAME "XX";
2004 r.in.account = &account_bad;
2006 status = dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r);
2008 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
2009 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2010 nt_errstr(status));
2011 ret = false;
2014 /* This shouldn't be a valid name */
2015 account_bad.string = TEST_ACCOUNT_NAME "XX";
2016 r.in.account = &account_bad;
2017 r.in.password = &lm_pass;
2018 r.in.hash = &lm_verifier;
2020 status = dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r);
2022 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2023 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2024 nt_errstr(status));
2025 ret = false;
2028 /* This shouldn't be a valid name */
2029 account_bad.string = TEST_ACCOUNT_NAME "XX";
2030 r.in.account = &account_bad;
2031 r.in.password = NULL;
2032 r.in.hash = &lm_verifier;
2034 status = dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r);
2036 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
2037 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2038 nt_errstr(status));
2039 ret = false;
2042 E_deshash(oldpass, old_lm_hash);
2043 E_deshash(newpass, new_lm_hash);
2045 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2046 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2047 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2049 r.in.server = &server;
2050 r.in.account = &account;
2051 r.in.password = &lm_pass;
2052 r.in.hash = &lm_verifier;
2054 status = dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r);
2055 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2056 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2057 } else if (!NT_STATUS_IS_OK(status)) {
2058 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
2059 ret = false;
2060 } else {
2061 *password = newpass;
2064 return ret;
2068 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2069 const char *acct_name,
2070 char **password,
2071 char *newpass, bool allow_password_restriction)
2073 NTSTATUS status;
2074 struct samr_ChangePasswordUser2 r;
2075 bool ret = true;
2076 struct lsa_String server, account;
2077 struct samr_CryptPassword nt_pass, lm_pass;
2078 struct samr_Password nt_verifier, lm_verifier;
2079 char *oldpass;
2080 struct dcerpc_binding_handle *b = p->binding_handle;
2081 uint8_t old_nt_hash[16], new_nt_hash[16];
2082 uint8_t old_lm_hash[16], new_lm_hash[16];
2084 struct samr_GetDomPwInfo dom_pw_info;
2085 struct samr_PwInfo info;
2087 struct lsa_String domain_name;
2089 domain_name.string = "";
2090 dom_pw_info.in.domain_name = &domain_name;
2091 dom_pw_info.out.info = &info;
2093 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2095 torture_assert(tctx, *password != NULL,
2096 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2097 oldpass = *password;
2099 if (!newpass) {
2100 int policy_min_pw_len = 0;
2101 status = dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info);
2102 if (NT_STATUS_IS_OK(status)) {
2103 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2106 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2109 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2110 init_lsa_String(&account, acct_name);
2112 E_md4hash(oldpass, old_nt_hash);
2113 E_md4hash(newpass, new_nt_hash);
2115 E_deshash(oldpass, old_lm_hash);
2116 E_deshash(newpass, new_lm_hash);
2118 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2119 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2120 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2122 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2123 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2124 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2126 r.in.server = &server;
2127 r.in.account = &account;
2128 r.in.nt_password = &nt_pass;
2129 r.in.nt_verifier = &nt_verifier;
2130 r.in.lm_change = 1;
2131 r.in.lm_password = &lm_pass;
2132 r.in.lm_verifier = &lm_verifier;
2134 status = dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r);
2135 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2136 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2137 } else if (!NT_STATUS_IS_OK(status)) {
2138 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2139 ret = false;
2140 } else {
2141 *password = newpass;
2144 return ret;
2148 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2149 const char *account_string,
2150 int policy_min_pw_len,
2151 char **password,
2152 const char *newpass,
2153 NTTIME last_password_change,
2154 bool handle_reject_reason)
2156 NTSTATUS status;
2157 struct samr_ChangePasswordUser3 r;
2158 bool ret = true;
2159 struct lsa_String server, account, account_bad;
2160 struct samr_CryptPassword nt_pass, lm_pass;
2161 struct samr_Password nt_verifier, lm_verifier;
2162 char *oldpass;
2163 struct dcerpc_binding_handle *b = p->binding_handle;
2164 uint8_t old_nt_hash[16], new_nt_hash[16];
2165 uint8_t old_lm_hash[16], new_lm_hash[16];
2166 NTTIME t;
2167 struct samr_DomInfo1 *dominfo = NULL;
2168 struct userPwdChangeFailureInformation *reject = NULL;
2170 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2172 if (newpass == NULL) {
2173 do {
2174 if (policy_min_pw_len == 0) {
2175 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2176 } else {
2177 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2179 } while (check_password_quality(newpass) == false);
2180 } else {
2181 torture_comment(tctx, "Using password '%s'\n", newpass);
2184 torture_assert(tctx, *password != NULL,
2185 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2187 oldpass = *password;
2188 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2189 init_lsa_String(&account, account_string);
2191 E_md4hash(oldpass, old_nt_hash);
2192 E_md4hash(newpass, new_nt_hash);
2194 E_deshash(oldpass, old_lm_hash);
2195 E_deshash(newpass, new_lm_hash);
2197 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2198 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2199 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2201 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2202 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2203 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2205 /* Break the verification */
2206 nt_verifier.hash[0]++;
2208 r.in.server = &server;
2209 r.in.account = &account;
2210 r.in.nt_password = &nt_pass;
2211 r.in.nt_verifier = &nt_verifier;
2212 r.in.lm_change = 1;
2213 r.in.lm_password = &lm_pass;
2214 r.in.lm_verifier = &lm_verifier;
2215 r.in.password3 = NULL;
2216 r.out.dominfo = &dominfo;
2217 r.out.reject = &reject;
2219 status = dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r);
2220 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2221 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2222 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2223 nt_errstr(status));
2224 ret = false;
2227 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2228 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2229 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2231 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2232 /* Break the NT hash */
2233 old_nt_hash[0]++;
2234 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2235 /* Unbreak it again */
2236 old_nt_hash[0]--;
2237 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2239 r.in.server = &server;
2240 r.in.account = &account;
2241 r.in.nt_password = &nt_pass;
2242 r.in.nt_verifier = &nt_verifier;
2243 r.in.lm_change = 1;
2244 r.in.lm_password = &lm_pass;
2245 r.in.lm_verifier = &lm_verifier;
2246 r.in.password3 = NULL;
2247 r.out.dominfo = &dominfo;
2248 r.out.reject = &reject;
2250 status = dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r);
2251 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2252 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2253 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2254 nt_errstr(status));
2255 ret = false;
2258 /* This shouldn't be a valid name */
2259 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2261 r.in.account = &account_bad;
2262 status = dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r);
2263 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2264 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2265 nt_errstr(status));
2266 ret = false;
2269 E_md4hash(oldpass, old_nt_hash);
2270 E_md4hash(newpass, new_nt_hash);
2272 E_deshash(oldpass, old_lm_hash);
2273 E_deshash(newpass, new_lm_hash);
2275 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2276 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2277 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2279 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2280 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2281 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2283 r.in.server = &server;
2284 r.in.account = &account;
2285 r.in.nt_password = &nt_pass;
2286 r.in.nt_verifier = &nt_verifier;
2287 r.in.lm_change = 1;
2288 r.in.lm_password = &lm_pass;
2289 r.in.lm_verifier = &lm_verifier;
2290 r.in.password3 = NULL;
2291 r.out.dominfo = &dominfo;
2292 r.out.reject = &reject;
2294 unix_to_nt_time(&t, time(NULL));
2296 status = dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r);
2298 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2299 && dominfo
2300 && reject
2301 && handle_reject_reason
2302 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2303 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2305 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2306 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2307 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2308 return false;
2312 /* We tested the order of precendence which is as follows:
2314 * pwd min_age
2315 * pwd length
2316 * pwd complexity
2317 * pwd history
2319 Guenther */
2321 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2322 (last_password_change + dominfo->min_password_age > t)) {
2324 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2325 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2326 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2327 return false;
2330 } else if ((dominfo->min_password_length > 0) &&
2331 (strlen(newpass) < dominfo->min_password_length)) {
2333 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2334 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2335 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2336 return false;
2339 } else if ((dominfo->password_history_length > 0) &&
2340 strequal(oldpass, newpass)) {
2342 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2343 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2344 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2345 return false;
2347 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2349 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2350 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2351 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2352 return false;
2357 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2358 /* retry with adjusted size */
2359 return test_ChangePasswordUser3(p, tctx, account_string,
2360 dominfo->min_password_length,
2361 password, NULL, 0, false);
2365 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2366 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2367 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2368 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2369 return false;
2371 /* Perhaps the server has a 'min password age' set? */
2373 } else {
2374 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2375 *password = talloc_strdup(tctx, newpass);
2378 return ret;
2381 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2382 const char *account_string,
2383 struct policy_handle *handle,
2384 char **password)
2386 NTSTATUS status;
2387 struct samr_ChangePasswordUser3 r;
2388 struct samr_SetUserInfo s;
2389 union samr_UserInfo u;
2390 DATA_BLOB session_key;
2391 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2392 uint8_t confounder[16];
2393 struct MD5Context ctx;
2395 bool ret = true;
2396 struct lsa_String server, account;
2397 struct samr_CryptPassword nt_pass;
2398 struct samr_Password nt_verifier;
2399 DATA_BLOB new_random_pass;
2400 char *newpass;
2401 char *oldpass;
2402 struct dcerpc_binding_handle *b = p->binding_handle;
2403 uint8_t old_nt_hash[16], new_nt_hash[16];
2404 NTTIME t;
2405 struct samr_DomInfo1 *dominfo = NULL;
2406 struct userPwdChangeFailureInformation *reject = NULL;
2408 new_random_pass = samr_very_rand_pass(tctx, 128);
2410 torture_assert(tctx, *password != NULL,
2411 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2413 oldpass = *password;
2414 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2415 init_lsa_String(&account, account_string);
2417 s.in.user_handle = handle;
2418 s.in.info = &u;
2419 s.in.level = 25;
2421 ZERO_STRUCT(u);
2423 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2425 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2427 status = dcerpc_fetch_session_key(p, &session_key);
2428 if (!NT_STATUS_IS_OK(status)) {
2429 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2430 s.in.level, nt_errstr(status));
2431 return false;
2434 generate_random_buffer((uint8_t *)confounder, 16);
2436 MD5Init(&ctx);
2437 MD5Update(&ctx, confounder, 16);
2438 MD5Update(&ctx, session_key.data, session_key.length);
2439 MD5Final(confounded_session_key.data, &ctx);
2441 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2442 memcpy(&u.info25.password.data[516], confounder, 16);
2444 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2446 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2449 s.in.level, nt_errstr(status));
2450 ret = false;
2453 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2455 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2457 new_random_pass = samr_very_rand_pass(tctx, 128);
2459 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2461 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2462 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2463 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2465 r.in.server = &server;
2466 r.in.account = &account;
2467 r.in.nt_password = &nt_pass;
2468 r.in.nt_verifier = &nt_verifier;
2469 r.in.lm_change = 0;
2470 r.in.lm_password = NULL;
2471 r.in.lm_verifier = NULL;
2472 r.in.password3 = NULL;
2473 r.out.dominfo = &dominfo;
2474 r.out.reject = &reject;
2476 unix_to_nt_time(&t, time(NULL));
2478 status = dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r);
2480 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2481 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2482 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2483 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2484 return false;
2486 /* Perhaps the server has a 'min password age' set? */
2488 } else if (!NT_STATUS_IS_OK(status)) {
2489 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2490 ret = false;
2493 newpass = samr_rand_pass(tctx, 128);
2495 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2497 E_md4hash(newpass, new_nt_hash);
2499 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2500 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2501 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2503 r.in.server = &server;
2504 r.in.account = &account;
2505 r.in.nt_password = &nt_pass;
2506 r.in.nt_verifier = &nt_verifier;
2507 r.in.lm_change = 0;
2508 r.in.lm_password = NULL;
2509 r.in.lm_verifier = NULL;
2510 r.in.password3 = NULL;
2511 r.out.dominfo = &dominfo;
2512 r.out.reject = &reject;
2514 unix_to_nt_time(&t, time(NULL));
2516 status = dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r);
2518 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2519 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2520 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2521 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2522 return false;
2524 /* Perhaps the server has a 'min password age' set? */
2526 } else {
2527 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2528 *password = talloc_strdup(tctx, newpass);
2531 return ret;
2535 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2536 struct torture_context *tctx,
2537 struct policy_handle *alias_handle)
2539 struct samr_GetMembersInAlias r;
2540 struct lsa_SidArray sids;
2541 NTSTATUS status;
2543 torture_comment(tctx, "Testing GetMembersInAlias\n");
2545 r.in.alias_handle = alias_handle;
2546 r.out.sids = &sids;
2548 status = dcerpc_samr_GetMembersInAlias_r(b, tctx, &r);
2549 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2551 return true;
2554 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2555 struct torture_context *tctx,
2556 struct policy_handle *alias_handle,
2557 const struct dom_sid *domain_sid)
2559 struct samr_AddAliasMember r;
2560 struct samr_DeleteAliasMember d;
2561 NTSTATUS status;
2562 struct dom_sid *sid;
2564 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2566 torture_comment(tctx, "testing AddAliasMember\n");
2567 r.in.alias_handle = alias_handle;
2568 r.in.sid = sid;
2570 status = dcerpc_samr_AddAliasMember_r(b, tctx, &r);
2571 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2573 d.in.alias_handle = alias_handle;
2574 d.in.sid = sid;
2576 status = dcerpc_samr_DeleteAliasMember_r(b, tctx, &d);
2577 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2579 return true;
2582 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2583 struct torture_context *tctx,
2584 struct policy_handle *alias_handle)
2586 struct samr_AddMultipleMembersToAlias a;
2587 struct samr_RemoveMultipleMembersFromAlias r;
2588 NTSTATUS status;
2589 struct lsa_SidArray sids;
2591 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2592 a.in.alias_handle = alias_handle;
2593 a.in.sids = &sids;
2595 sids.num_sids = 3;
2596 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2598 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2599 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2600 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2602 status = dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a);
2603 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2606 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2607 r.in.alias_handle = alias_handle;
2608 r.in.sids = &sids;
2610 status = dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r);
2611 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2613 /* strange! removing twice doesn't give any error */
2614 status = dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r);
2615 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2617 /* but removing an alias that isn't there does */
2618 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2620 status = dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r);
2621 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2623 return true;
2626 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2627 struct torture_context *tctx,
2628 struct policy_handle *domain_handle)
2630 struct samr_GetAliasMembership r;
2631 struct lsa_SidArray sids;
2632 struct samr_Ids rids;
2633 NTSTATUS status;
2635 torture_comment(tctx, "Testing GetAliasMembership\n");
2637 if (torture_setting_bool(tctx, "samba4", false)) {
2638 torture_skip(tctx, "skipping GetAliasMembership against s4");
2641 r.in.domain_handle = domain_handle;
2642 r.in.sids = &sids;
2643 r.out.rids = &rids;
2645 sids.num_sids = 0;
2646 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2648 status = dcerpc_samr_GetAliasMembership_r(b, tctx, &r);
2649 torture_assert_ntstatus_ok(tctx, status,
2650 "samr_GetAliasMembership failed");
2652 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2653 "protocol misbehaviour");
2655 sids.num_sids = 1;
2656 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2657 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2659 status = dcerpc_samr_GetAliasMembership_r(b, tctx, &r);
2660 torture_assert_ntstatus_ok(tctx, status,
2661 "samr_GetAliasMembership failed");
2663 #if 0
2664 /* only true for w2k8 it seems
2665 * win7, xp, w2k3 will return a 0 length array pointer */
2667 if (rids.ids && (rids.count == 0)) {
2668 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2670 #endif
2671 if (!rids.ids && rids.count) {
2672 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2675 return true;
2678 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2679 struct torture_context *tctx,
2680 struct policy_handle *user_handle)
2682 struct samr_TestPrivateFunctionsUser r;
2683 NTSTATUS status;
2685 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2687 r.in.user_handle = user_handle;
2689 status = dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r);
2690 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2692 return true;
2695 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2696 struct torture_context *tctx,
2697 struct policy_handle *handle,
2698 bool use_info2,
2699 NTTIME *pwdlastset)
2701 NTSTATUS status;
2702 uint16_t levels[] = { /* 3, */ 5, 21 };
2703 int i;
2704 NTTIME pwdlastset3 = 0;
2705 NTTIME pwdlastset5 = 0;
2706 NTTIME pwdlastset21 = 0;
2708 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2709 use_info2 ? "2":"");
2711 for (i=0; i<ARRAY_SIZE(levels); i++) {
2713 struct samr_QueryUserInfo r;
2714 struct samr_QueryUserInfo2 r2;
2715 union samr_UserInfo *info;
2717 if (use_info2) {
2718 r2.in.user_handle = handle;
2719 r2.in.level = levels[i];
2720 r2.out.info = &info;
2721 status = dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2);
2723 } else {
2724 r.in.user_handle = handle;
2725 r.in.level = levels[i];
2726 r.out.info = &info;
2727 status = dcerpc_samr_QueryUserInfo_r(b, tctx, &r);
2730 if (!NT_STATUS_IS_OK(status) &&
2731 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2732 torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2733 use_info2 ? "2":"", levels[i], nt_errstr(status));
2734 return false;
2737 switch (levels[i]) {
2738 case 3:
2739 pwdlastset3 = info->info3.last_password_change;
2740 break;
2741 case 5:
2742 pwdlastset5 = info->info5.last_password_change;
2743 break;
2744 case 21:
2745 pwdlastset21 = info->info21.last_password_change;
2746 break;
2747 default:
2748 return false;
2751 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2752 "pwdlastset mixup"); */
2753 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2754 "pwdlastset mixup");
2756 *pwdlastset = pwdlastset21;
2758 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2760 return true;
2763 static bool test_SamLogon(struct torture_context *tctx,
2764 struct dcerpc_pipe *p,
2765 struct cli_credentials *test_credentials,
2766 NTSTATUS expected_result,
2767 bool interactive)
2769 NTSTATUS status;
2770 struct netr_LogonSamLogonEx r;
2771 union netr_LogonLevel logon;
2772 union netr_Validation validation;
2773 uint8_t authoritative;
2774 struct netr_IdentityInfo identity;
2775 struct netr_NetworkInfo ninfo;
2776 struct netr_PasswordInfo pinfo;
2777 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2778 int flags = CLI_CRED_NTLM_AUTH;
2779 uint32_t samlogon_flags = 0;
2780 struct netlogon_creds_CredentialState *creds;
2781 struct netr_Authenticator a;
2782 struct dcerpc_binding_handle *b = p->binding_handle;
2784 torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2786 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2787 flags |= CLI_CRED_LANMAN_AUTH;
2790 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2791 flags |= CLI_CRED_NTLMv2_AUTH;
2794 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2795 &identity.account_name.string,
2796 &identity.domain_name.string);
2798 identity.parameter_control =
2799 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2800 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2801 identity.logon_id_low = 0;
2802 identity.logon_id_high = 0;
2803 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2805 if (interactive) {
2806 netlogon_creds_client_authenticator(creds, &a);
2808 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
2809 ZERO_STRUCT(pinfo.lmpassword.hash);
2811 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
2813 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
2814 netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
2815 netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
2816 } else {
2817 netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
2818 netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
2821 pinfo.identity_info = identity;
2822 logon.password = &pinfo;
2824 r.in.logon_level = NetlogonInteractiveInformation;
2825 } else {
2826 generate_random_buffer(ninfo.challenge,
2827 sizeof(ninfo.challenge));
2828 chal = data_blob_const(ninfo.challenge,
2829 sizeof(ninfo.challenge));
2831 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2832 cli_credentials_get_domain(test_credentials));
2834 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2835 &flags,
2836 chal,
2837 names_blob,
2838 &lm_resp, &nt_resp,
2839 NULL, NULL);
2840 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2842 ninfo.lm.data = lm_resp.data;
2843 ninfo.lm.length = lm_resp.length;
2845 ninfo.nt.data = nt_resp.data;
2846 ninfo.nt.length = nt_resp.length;
2848 ninfo.identity_info = identity;
2849 logon.network = &ninfo;
2851 r.in.logon_level = NetlogonNetworkInformation;
2854 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2855 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2856 r.in.logon = &logon;
2857 r.in.flags = &samlogon_flags;
2858 r.out.flags = &samlogon_flags;
2859 r.out.validation = &validation;
2860 r.out.authoritative = &authoritative;
2862 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
2864 r.in.validation_level = 6;
2866 status = dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r);
2867 if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2868 r.in.validation_level = 3;
2869 status = dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r);
2871 if (!NT_STATUS_IS_OK(status)) {
2872 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogonEx failed");
2873 return true;
2874 } else {
2875 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogonEx failed");
2878 return true;
2881 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2882 struct dcerpc_pipe *p,
2883 struct cli_credentials *machine_creds,
2884 const char *acct_name,
2885 const char *password,
2886 NTSTATUS expected_samlogon_result,
2887 bool interactive)
2889 bool ret = true;
2890 struct cli_credentials *test_credentials;
2892 test_credentials = cli_credentials_init(tctx);
2894 cli_credentials_set_workstation(test_credentials,
2895 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2896 cli_credentials_set_domain(test_credentials,
2897 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2898 cli_credentials_set_username(test_credentials,
2899 acct_name, CRED_SPECIFIED);
2900 cli_credentials_set_password(test_credentials,
2901 password, CRED_SPECIFIED);
2903 torture_comment(tctx, "testing samlogon (%s) as %s password: %s\n",
2904 interactive ? "interactive" : "network", acct_name, password);
2906 if (!test_SamLogon(tctx, p, test_credentials,
2907 expected_samlogon_result, interactive)) {
2908 torture_warning(tctx, "new password did not work\n");
2909 ret = false;
2912 return ret;
2915 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2916 struct dcerpc_pipe *np,
2917 struct torture_context *tctx,
2918 struct policy_handle *handle,
2919 uint16_t level,
2920 uint32_t fields_present,
2921 uint8_t password_expired,
2922 bool *matched_expected_error,
2923 bool use_setinfo2,
2924 const char *acct_name,
2925 char **password,
2926 struct cli_credentials *machine_creds,
2927 bool use_queryinfo2,
2928 NTTIME *pwdlastset,
2929 NTSTATUS expected_samlogon_result)
2931 const char *fields = NULL;
2932 bool ret = true;
2933 struct dcerpc_binding_handle *b = p->binding_handle;
2935 switch (level) {
2936 case 21:
2937 case 23:
2938 case 25:
2939 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2940 fields_present);
2941 break;
2942 default:
2943 break;
2946 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2947 "(password_expired: %d) %s\n",
2948 use_setinfo2 ? "2":"", level, password_expired,
2949 fields ? fields : "");
2951 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2952 fields_present,
2953 password,
2954 password_expired,
2955 use_setinfo2,
2956 matched_expected_error)) {
2957 ret = false;
2960 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
2961 use_queryinfo2,
2962 pwdlastset)) {
2963 ret = false;
2966 if (*matched_expected_error == true) {
2967 return ret;
2970 if (!test_SamLogon_with_creds(tctx, np,
2971 machine_creds,
2972 acct_name,
2973 *password,
2974 expected_samlogon_result,
2975 false)) {
2976 ret = false;
2979 return ret;
2982 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
2983 struct cli_credentials *credentials,
2984 struct dcerpc_pipe **p)
2986 struct dcerpc_binding *b;
2988 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
2989 "failed to get rpc binding");
2991 /* We have to use schannel, otherwise the SamLogonEx fails
2992 * with INTERNAL_ERROR */
2994 b->flags &= ~DCERPC_AUTH_OPTIONS;
2995 b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
2997 torture_assert_ntstatus_ok(tctx,
2998 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
2999 credentials, tctx->ev, tctx->lp_ctx),
3000 "failed to bind to netlogon");
3002 return true;
3005 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3006 struct torture_context *tctx,
3007 uint32_t acct_flags,
3008 const char *acct_name,
3009 struct policy_handle *handle,
3010 char **password,
3011 struct cli_credentials *machine_credentials)
3013 int s = 0, q = 0, f = 0, l = 0, z = 0;
3014 bool ret = true;
3015 int delay = 50000;
3016 bool set_levels[] = { false, true };
3017 bool query_levels[] = { false, true };
3018 uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3019 uint32_t nonzeros[] = { 1, 24 };
3020 uint32_t fields_present[] = {
3022 SAMR_FIELD_EXPIRED_FLAG,
3023 SAMR_FIELD_LAST_PWD_CHANGE,
3024 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3025 SAMR_FIELD_COMMENT,
3026 SAMR_FIELD_NT_PASSWORD_PRESENT,
3027 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3028 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3029 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3030 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3031 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3032 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3034 struct dcerpc_pipe *np = NULL;
3036 if (torture_setting_bool(tctx, "samba3", false)) {
3037 delay = 999999;
3038 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3039 delay);
3042 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3044 /* set to 1 to enable testing for all possible opcode
3045 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3046 combinations */
3047 #if 0
3048 #define TEST_ALL_LEVELS 1
3049 #define TEST_SET_LEVELS 1
3050 #define TEST_QUERY_LEVELS 1
3051 #endif
3052 #ifdef TEST_ALL_LEVELS
3053 for (l=0; l<ARRAY_SIZE(levels); l++) {
3054 #else
3055 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3056 #endif
3057 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3058 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3059 #ifdef TEST_SET_LEVELS
3060 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3061 #endif
3062 #ifdef TEST_QUERY_LEVELS
3063 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3064 #endif
3065 NTTIME pwdlastset_old = 0;
3066 NTTIME pwdlastset_new = 0;
3067 bool matched_expected_error = false;
3068 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3070 torture_comment(tctx, "------------------------------\n"
3071 "Testing pwdLastSet attribute for flags: 0x%08x "
3072 "(s: %d (l: %d), q: %d)\n",
3073 acct_flags, s, levels[l], q);
3075 switch (levels[l]) {
3076 case 21:
3077 case 23:
3078 case 25:
3079 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3080 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3081 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3083 break;
3087 /* set #1 */
3089 /* set a password and force password change (pwdlastset 0) by
3090 * setting the password expired flag to a non-0 value */
3092 if (!test_SetPassword_level(p, np, tctx, handle,
3093 levels[l],
3094 fields_present[f],
3095 nonzeros[z],
3096 &matched_expected_error,
3097 set_levels[s],
3098 acct_name,
3099 password,
3100 machine_credentials,
3101 query_levels[q],
3102 &pwdlastset_old,
3103 expected_samlogon_result)) {
3104 ret = false;
3107 if (matched_expected_error == true) {
3108 /* skipping on expected failure */
3109 continue;
3112 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3113 * set without the SAMR_FIELD_EXPIRED_FLAG */
3115 switch (levels[l]) {
3116 case 21:
3117 case 23:
3118 case 25:
3119 if ((pwdlastset_new != 0) &&
3120 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3121 torture_comment(tctx, "not considering a non-0 "
3122 "pwdLastSet as a an error as the "
3123 "SAMR_FIELD_EXPIRED_FLAG has not "
3124 "been set\n");
3125 break;
3127 default:
3128 if (pwdlastset_new != 0) {
3129 torture_warning(tctx, "pwdLastSet test failed: "
3130 "expected pwdLastSet 0 but got %lld\n",
3131 pwdlastset_old);
3132 ret = false;
3134 break;
3137 switch (levels[l]) {
3138 case 21:
3139 case 23:
3140 case 25:
3141 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3142 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3143 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3144 (pwdlastset_old >= pwdlastset_new)) {
3145 torture_warning(tctx, "pwdlastset not increasing\n");
3146 ret = false;
3148 break;
3149 default:
3150 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3151 (pwdlastset_old >= pwdlastset_new)) {
3152 torture_warning(tctx, "pwdlastset not increasing\n");
3153 ret = false;
3155 break;
3158 usleep(delay);
3160 /* set #2 */
3162 /* set a password, pwdlastset needs to get updated (increased
3163 * value), password_expired value used here is 0 */
3165 if (!test_SetPassword_level(p, np, tctx, handle,
3166 levels[l],
3167 fields_present[f],
3169 &matched_expected_error,
3170 set_levels[s],
3171 acct_name,
3172 password,
3173 machine_credentials,
3174 query_levels[q],
3175 &pwdlastset_new,
3176 expected_samlogon_result)) {
3177 ret = false;
3180 /* when a password has been changed, pwdlastset must not be 0 afterwards
3181 * and must be larger then the old value */
3183 switch (levels[l]) {
3184 case 21:
3185 case 23:
3186 case 25:
3188 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3189 * password has been changed, old and new pwdlastset
3190 * need to be the same value */
3192 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3193 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3194 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3196 torture_assert_int_equal(tctx, pwdlastset_old,
3197 pwdlastset_new, "pwdlastset must be equal");
3198 break;
3200 default:
3201 if (pwdlastset_old >= pwdlastset_new) {
3202 torture_warning(tctx, "pwdLastSet test failed: "
3203 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3204 pwdlastset_old, pwdlastset_new);
3205 ret = false;
3207 if (pwdlastset_new == 0) {
3208 torture_warning(tctx, "pwdLastSet test failed: "
3209 "expected non-0 pwdlastset, got: %lld\n",
3210 pwdlastset_new);
3211 ret = false;
3215 switch (levels[l]) {
3216 case 21:
3217 case 23:
3218 case 25:
3219 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3220 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3221 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3222 (pwdlastset_old >= pwdlastset_new)) {
3223 torture_warning(tctx, "pwdlastset not increasing\n");
3224 ret = false;
3226 break;
3227 default:
3228 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3229 (pwdlastset_old >= pwdlastset_new)) {
3230 torture_warning(tctx, "pwdlastset not increasing\n");
3231 ret = false;
3233 break;
3236 pwdlastset_old = pwdlastset_new;
3238 usleep(delay);
3240 /* set #2b */
3242 /* set a password, pwdlastset needs to get updated (increased
3243 * value), password_expired value used here is 0 */
3245 if (!test_SetPassword_level(p, np, tctx, handle,
3246 levels[l],
3247 fields_present[f],
3249 &matched_expected_error,
3250 set_levels[s],
3251 acct_name,
3252 password,
3253 machine_credentials,
3254 query_levels[q],
3255 &pwdlastset_new,
3256 expected_samlogon_result)) {
3257 ret = false;
3260 /* when a password has been changed, pwdlastset must not be 0 afterwards
3261 * and must be larger then the old value */
3263 switch (levels[l]) {
3264 case 21:
3265 case 23:
3266 case 25:
3268 /* if no password has been changed, old and new pwdlastset
3269 * need to be the same value */
3271 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3272 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3274 torture_assert_int_equal(tctx, pwdlastset_old,
3275 pwdlastset_new, "pwdlastset must be equal");
3276 break;
3278 default:
3279 if (pwdlastset_old >= pwdlastset_new) {
3280 torture_warning(tctx, "pwdLastSet test failed: "
3281 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3282 pwdlastset_old, pwdlastset_new);
3283 ret = false;
3285 if (pwdlastset_new == 0) {
3286 torture_warning(tctx, "pwdLastSet test failed: "
3287 "expected non-0 pwdlastset, got: %lld\n",
3288 pwdlastset_new);
3289 ret = false;
3293 /* set #3 */
3295 /* set a password and force password change (pwdlastset 0) by
3296 * setting the password expired flag to a non-0 value */
3298 if (!test_SetPassword_level(p, np, tctx, handle,
3299 levels[l],
3300 fields_present[f],
3301 nonzeros[z],
3302 &matched_expected_error,
3303 set_levels[s],
3304 acct_name,
3305 password,
3306 machine_credentials,
3307 query_levels[q],
3308 &pwdlastset_new,
3309 expected_samlogon_result)) {
3310 ret = false;
3313 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3314 * set without the SAMR_FIELD_EXPIRED_FLAG */
3316 switch (levels[l]) {
3317 case 21:
3318 case 23:
3319 case 25:
3320 if ((pwdlastset_new != 0) &&
3321 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3322 torture_comment(tctx, "not considering a non-0 "
3323 "pwdLastSet as a an error as the "
3324 "SAMR_FIELD_EXPIRED_FLAG has not "
3325 "been set\n");
3326 break;
3329 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3330 * password has been changed, old and new pwdlastset
3331 * need to be the same value */
3333 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3334 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3335 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3337 torture_assert_int_equal(tctx, pwdlastset_old,
3338 pwdlastset_new, "pwdlastset must be equal");
3339 break;
3341 default:
3343 if (pwdlastset_old == pwdlastset_new) {
3344 torture_warning(tctx, "pwdLastSet test failed: "
3345 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3346 pwdlastset_old, pwdlastset_new);
3347 ret = false;
3350 if (pwdlastset_new != 0) {
3351 torture_warning(tctx, "pwdLastSet test failed: "
3352 "expected pwdLastSet 0, got %lld\n",
3353 pwdlastset_old);
3354 ret = false;
3356 break;
3359 switch (levels[l]) {
3360 case 21:
3361 case 23:
3362 case 25:
3363 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3364 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3365 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3366 (pwdlastset_old >= pwdlastset_new)) {
3367 torture_warning(tctx, "pwdlastset not increasing\n");
3368 ret = false;
3370 break;
3371 default:
3372 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3373 (pwdlastset_old >= pwdlastset_new)) {
3374 torture_warning(tctx, "pwdlastset not increasing\n");
3375 ret = false;
3377 break;
3380 /* if the level we are testing does not have a fields_present
3381 * field, skip all fields present tests by setting f to to
3382 * arraysize */
3383 switch (levels[l]) {
3384 case 18:
3385 case 24:
3386 case 26:
3387 f = ARRAY_SIZE(fields_present);
3388 break;
3391 #ifdef TEST_QUERY_LEVELS
3393 #endif
3394 #ifdef TEST_SET_LEVELS
3396 #endif
3397 } /* fields present */
3398 } /* nonzeros */
3399 } /* levels */
3401 #undef TEST_SET_LEVELS
3402 #undef TEST_QUERY_LEVELS
3404 talloc_free(np);
3406 return ret;
3409 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3410 struct torture_context *tctx,
3411 struct policy_handle *handle,
3412 uint32_t *badpwdcount)
3414 union samr_UserInfo *info;
3415 struct samr_QueryUserInfo r;
3417 r.in.user_handle = handle;
3418 r.in.level = 3;
3419 r.out.info = &info;
3421 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3423 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3424 "failed to query userinfo");
3426 *badpwdcount = info->info3.bad_password_count;
3428 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3430 return true;
3433 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3434 struct torture_context *tctx,
3435 struct policy_handle *user_handle,
3436 uint32_t acct_flags)
3438 struct samr_SetUserInfo r;
3439 union samr_UserInfo user_info;
3441 torture_comment(tctx, "Testing SetUserInfo level 16\n");
3443 user_info.info16.acct_flags = acct_flags;
3445 r.in.user_handle = user_handle;
3446 r.in.level = 16;
3447 r.in.info = &user_info;
3449 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3450 "failed to set account flags");
3452 return true;
3455 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3456 struct torture_context *tctx,
3457 struct policy_handle *user_handle,
3458 uint32_t acct_flags,
3459 char **password)
3461 struct dcerpc_binding_handle *b = p->binding_handle;
3463 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3464 "failed to set password");
3466 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3468 torture_assert(tctx,
3469 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3470 acct_flags & ~ACB_DISABLED),
3471 "failed to enable user");
3473 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3474 "failed to set password");
3476 return true;
3479 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3480 struct torture_context *tctx,
3481 struct policy_handle *domain_handle,
3482 enum samr_DomainInfoClass level,
3483 union samr_DomainInfo *info)
3485 struct samr_SetDomainInfo r;
3487 r.in.domain_handle = domain_handle;
3488 r.in.level = level;
3489 r.in.info = info;
3491 torture_assert_ntstatus_ok(tctx,
3492 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3493 "failed to set domain info");
3495 return true;
3498 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3499 struct torture_context *tctx,
3500 struct policy_handle *domain_handle,
3501 enum samr_DomainInfoClass level,
3502 union samr_DomainInfo *info,
3503 NTSTATUS expected)
3505 struct samr_SetDomainInfo r;
3507 r.in.domain_handle = domain_handle;
3508 r.in.level = level;
3509 r.in.info = info;
3511 torture_assert_ntstatus_equal(tctx,
3512 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3513 expected,
3514 "");
3516 return true;
3519 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3520 struct torture_context *tctx,
3521 struct policy_handle *domain_handle,
3522 enum samr_DomainInfoClass level,
3523 union samr_DomainInfo **q_info)
3525 struct samr_QueryDomainInfo2 r;
3527 r.in.domain_handle = domain_handle;
3528 r.in.level = level;
3529 r.out.info = q_info;
3531 torture_assert_ntstatus_ok(tctx,
3532 dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3533 "failed to query domain info");
3535 return true;
3538 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3539 struct dcerpc_pipe *np,
3540 struct torture_context *tctx,
3541 uint32_t acct_flags,
3542 const char *acct_name,
3543 struct policy_handle *domain_handle,
3544 struct policy_handle *user_handle,
3545 char **password,
3546 struct cli_credentials *machine_credentials,
3547 const char *comment,
3548 bool disable,
3549 bool interactive,
3550 NTSTATUS expected_success_status,
3551 struct samr_DomInfo1 *info1,
3552 struct samr_DomInfo12 *info12)
3554 union samr_DomainInfo info;
3555 char **passwords;
3556 int i;
3557 uint32_t badpwdcount, tmp;
3558 uint32_t password_history_length = 12;
3559 uint32_t lockout_threshold = 15;
3560 struct dcerpc_binding_handle *b = p->binding_handle;
3562 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3564 torture_assert(tctx, password_history_length < lockout_threshold,
3565 "password history length needs to be smaller than account lockout threshold for this test");
3568 /* set policies */
3570 info.info1 = *info1;
3571 info.info1.password_history_length = password_history_length;
3573 torture_assert(tctx,
3574 test_SetDomainInfo(b, tctx, domain_handle,
3575 DomainPasswordInformation, &info),
3576 "failed to set password history length");
3578 info.info12 = *info12;
3579 info.info12.lockout_threshold = lockout_threshold;
3581 torture_assert(tctx,
3582 test_SetDomainInfo(b, tctx, domain_handle,
3583 DomainLockoutInformation, &info),
3584 "failed to set lockout threshold");
3586 /* reset bad pwd count */
3588 torture_assert(tctx,
3589 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3592 /* enable or disable account */
3593 if (disable) {
3594 torture_assert(tctx,
3595 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3596 acct_flags | ACB_DISABLED),
3597 "failed to disable user");
3598 } else {
3599 torture_assert(tctx,
3600 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3601 acct_flags & ~ACB_DISABLED),
3602 "failed to enable user");
3606 /* setup password history */
3608 passwords = talloc_array(tctx, char *, password_history_length);
3610 for (i=0; i < password_history_length; i++) {
3612 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3613 "failed to set password");
3614 passwords[i] = talloc_strdup(tctx, *password);
3616 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3617 acct_name, passwords[i],
3618 expected_success_status, interactive)) {
3619 torture_fail(tctx, "failed to auth with latest password");
3622 torture_assert(tctx,
3623 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3625 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3629 /* test with wrong password */
3631 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3632 acct_name, "random_crap",
3633 NT_STATUS_WRONG_PASSWORD, interactive)) {
3634 torture_fail(tctx, "succeeded to authenticate with wrong password");
3637 torture_assert(tctx,
3638 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3640 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3643 /* test with latest good password */
3645 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3646 passwords[password_history_length-1],
3647 expected_success_status, interactive)) {
3648 torture_fail(tctx, "succeeded to authenticate with wrong password");
3651 torture_assert(tctx,
3652 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3654 if (disable) {
3655 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3656 } else {
3657 /* only enabled accounts get the bad pwd count reset upon
3658 * successful logon */
3659 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3662 tmp = badpwdcount;
3665 /* test password history */
3667 for (i=0; i < password_history_length; i++) {
3669 torture_comment(tctx, "Testing bad password count behavior with "
3670 "password #%d of #%d\n", i, password_history_length);
3672 /* - network samlogon will succeed auth and not
3673 * increase badpwdcount for 2 last entries
3674 * - interactive samlogon only for the last one */
3676 if (i == password_history_length - 1 ||
3677 (i == password_history_length - 2 && !interactive)) {
3679 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3680 acct_name, passwords[i],
3681 expected_success_status, interactive)) {
3682 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3685 torture_assert(tctx,
3686 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3688 if (disable) {
3689 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3690 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3691 } else {
3692 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3693 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3696 tmp = badpwdcount;
3698 continue;
3701 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3702 acct_name, passwords[i],
3703 NT_STATUS_WRONG_PASSWORD, interactive)) {
3704 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3707 torture_assert(tctx,
3708 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3710 /* - network samlogon will fail auth but not increase
3711 * badpwdcount for 3rd last entry
3712 * - interactive samlogon for 3rd and 2nd last entry */
3714 if (i == password_history_length - 3 ||
3715 (i == password_history_length - 2 && interactive)) {
3716 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3717 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3718 } else {
3719 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3720 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3723 tmp = badpwdcount;
3726 return true;
3729 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3730 struct torture_context *tctx,
3731 uint32_t acct_flags,
3732 const char *acct_name,
3733 struct policy_handle *domain_handle,
3734 struct policy_handle *user_handle,
3735 char **password,
3736 struct cli_credentials *machine_credentials)
3738 union samr_DomainInfo *q_info, s_info;
3739 struct samr_DomInfo1 info1, _info1;
3740 struct samr_DomInfo12 info12, _info12;
3741 bool ret = true;
3742 struct dcerpc_binding_handle *b = p->binding_handle;
3743 struct dcerpc_pipe *np;
3744 int i;
3746 struct {
3747 const char *comment;
3748 bool disabled;
3749 bool interactive;
3750 NTSTATUS expected_success_status;
3751 } creds[] = {
3753 .comment = "network logon (disabled account)",
3754 .disabled = true,
3755 .interactive = false,
3756 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3759 .comment = "network logon (enabled account)",
3760 .disabled = false,
3761 .interactive = false,
3762 .expected_success_status= NT_STATUS_OK
3765 .comment = "interactive logon (disabled account)",
3766 .disabled = true,
3767 .interactive = true,
3768 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3771 .comment = "interactive logon (enabled account)",
3772 .disabled = false,
3773 .interactive = true,
3774 .expected_success_status= NT_STATUS_OK
3778 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3780 /* backup old policies */
3782 torture_assert(tctx,
3783 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3784 DomainPasswordInformation, &q_info),
3785 "failed to query domain info level 1");
3787 info1 = q_info->info1;
3788 _info1 = info1;
3790 torture_assert(tctx,
3791 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3792 DomainLockoutInformation, &q_info),
3793 "failed to query domain info level 12");
3795 info12 = q_info->info12;
3796 _info12 = info12;
3798 /* run tests */
3800 for (i=0; i < ARRAY_SIZE(creds); i++) {
3802 /* skip trust tests for now */
3803 if (acct_flags & ACB_WSTRUST ||
3804 acct_flags & ACB_SVRTRUST ||
3805 acct_flags & ACB_DOMTRUST) {
3806 continue;
3809 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
3810 domain_handle, user_handle, password,
3811 machine_credentials,
3812 creds[i].comment,
3813 creds[i].disabled,
3814 creds[i].interactive,
3815 creds[i].expected_success_status,
3816 &_info1, &_info12);
3817 if (!ret) {
3818 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
3819 } else {
3820 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
3824 /* restore policies */
3826 s_info.info1 = info1;
3828 torture_assert(tctx,
3829 test_SetDomainInfo(b, tctx, domain_handle,
3830 DomainPasswordInformation, &s_info),
3831 "failed to set password information");
3833 s_info.info12 = info12;
3835 torture_assert(tctx,
3836 test_SetDomainInfo(b, tctx, domain_handle,
3837 DomainLockoutInformation, &s_info),
3838 "failed to set lockout information");
3840 return ret;
3843 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3844 struct torture_context *tctx,
3845 struct policy_handle *handle,
3846 uint32_t *acct_flags)
3848 union samr_UserInfo *info;
3849 struct samr_QueryUserInfo r;
3851 r.in.user_handle = handle;
3852 r.in.level = 16;
3853 r.out.info = &info;
3855 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3857 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3858 "failed to query userinfo");
3860 *acct_flags = info->info16.acct_flags;
3862 torture_comment(tctx, " (acct_flags: 0x%08x)\n", *acct_flags);
3864 return true;
3867 static bool test_Password_lockout(struct dcerpc_pipe *p,
3868 struct dcerpc_pipe *np,
3869 struct torture_context *tctx,
3870 uint32_t acct_flags,
3871 const char *acct_name,
3872 struct policy_handle *domain_handle,
3873 struct policy_handle *user_handle,
3874 char **password,
3875 struct cli_credentials *machine_credentials,
3876 const char *comment,
3877 bool disable,
3878 bool interactive,
3879 NTSTATUS expected_success_status,
3880 struct samr_DomInfo1 *info1,
3881 struct samr_DomInfo12 *info12)
3883 union samr_DomainInfo info;
3884 uint32_t badpwdcount;
3885 uint32_t password_history_length = 1;
3886 uint64_t lockout_threshold = 1;
3887 uint32_t lockout_seconds = 5;
3888 uint64_t delta_time_factor = 10 * 1000 * 1000;
3889 struct dcerpc_binding_handle *b = p->binding_handle;
3891 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
3893 /* set policies */
3895 info.info1 = *info1;
3897 torture_comment(tctx, "setting password history lenght.\n");
3898 info.info1.password_history_length = password_history_length;
3900 torture_assert(tctx,
3901 test_SetDomainInfo(b, tctx, domain_handle,
3902 DomainPasswordInformation, &info),
3903 "failed to set password history length");
3905 info.info12 = *info12;
3906 info.info12.lockout_threshold = lockout_threshold;
3908 /* set lockout duration < lockout window: should fail */
3909 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3910 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
3912 torture_assert(tctx,
3913 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
3914 DomainLockoutInformation, &info,
3915 NT_STATUS_INVALID_PARAMETER),
3916 "setting lockout duration < lockout window gave unexpected result");
3918 info.info12.lockout_duration = 0;
3919 info.info12.lockout_window = 0;
3921 torture_assert(tctx,
3922 test_SetDomainInfo(b, tctx, domain_handle,
3923 DomainLockoutInformation, &info),
3924 "failed to set lockout window and duration to 0");
3927 /* set lockout duration of 5 seconds */
3928 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3929 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
3931 torture_assert(tctx,
3932 test_SetDomainInfo(b, tctx, domain_handle,
3933 DomainLockoutInformation, &info),
3934 "failed to set lockout window and duration to 5 seconds");
3936 /* reset bad pwd count */
3938 torture_assert(tctx,
3939 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3942 /* enable or disable account */
3944 if (disable) {
3945 torture_assert(tctx,
3946 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3947 acct_flags | ACB_DISABLED),
3948 "failed to disable user");
3949 } else {
3950 torture_assert(tctx,
3951 test_SetUserInfo_acct_flags(b, tctx, user_handle,
3952 acct_flags & ~ACB_DISABLED),
3953 "failed to enable user");
3957 /* test logon with right password */
3959 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3960 acct_name, *password,
3961 expected_success_status, interactive)) {
3962 torture_fail(tctx, "failed to auth with latest password");
3965 torture_assert(tctx,
3966 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3967 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3970 /* test with wrong password ==> lockout */
3972 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3973 acct_name, "random_crap",
3974 NT_STATUS_WRONG_PASSWORD, interactive)) {
3975 torture_fail(tctx, "succeeded to authenticate with wrong password");
3978 torture_assert(tctx,
3979 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3980 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3982 torture_assert(tctx,
3983 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
3984 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3985 "expected account to be locked");
3988 /* test with good password */
3990 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3991 *password,
3992 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
3994 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
3997 /* bad pwd count should not get updated */
3998 torture_assert(tctx,
3999 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4000 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4002 /* curiously, windows does _not_ set the autlock flag */
4003 torture_assert(tctx,
4004 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4005 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4006 "expected account to be locked");
4009 /* with bad password */
4011 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4012 acct_name, "random_crap2",
4013 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4015 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4018 /* bad pwd count should not get updated */
4019 torture_assert(tctx,
4020 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4021 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4023 /* curiously, windows does _not_ set the autlock flag */
4024 torture_assert(tctx,
4025 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4026 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4027 "expected account to be locked");
4030 /* let lockout duration expire ==> unlock */
4032 torture_comment(tctx, "let lockout duration expire...\n");
4033 sleep(lockout_seconds + 1);
4035 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4036 *password,
4037 expected_success_status, interactive))
4039 torture_fail(tctx, "failed to authenticate after lockout expired");
4042 torture_assert(tctx,
4043 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4044 torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4045 "expected account not to be locked");
4047 return true;
4050 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4051 struct torture_context *tctx,
4052 uint32_t acct_flags,
4053 const char *acct_name,
4054 struct policy_handle *domain_handle,
4055 struct policy_handle *user_handle,
4056 char **password,
4057 struct cli_credentials *machine_credentials)
4059 union samr_DomainInfo *q_info, s_info;
4060 struct samr_DomInfo1 info1, _info1;
4061 struct samr_DomInfo12 info12, _info12;
4062 bool ret = true;
4063 struct dcerpc_binding_handle *b = p->binding_handle;
4064 struct dcerpc_pipe *np;
4065 int i;
4067 struct {
4068 const char *comment;
4069 bool disabled;
4070 bool interactive;
4071 NTSTATUS expected_success_status;
4072 } creds[] = {
4074 .comment = "network logon (disabled account)",
4075 .disabled = true,
4076 .interactive = false,
4077 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4080 .comment = "network logon (enabled account)",
4081 .disabled = false,
4082 .interactive = false,
4083 .expected_success_status= NT_STATUS_OK
4086 .comment = "interactive logon (disabled account)",
4087 .disabled = true,
4088 .interactive = true,
4089 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4092 .comment = "interactive logon (enabled account)",
4093 .disabled = false,
4094 .interactive = true,
4095 .expected_success_status= NT_STATUS_OK
4099 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4101 /* backup old policies */
4103 torture_assert(tctx,
4104 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4105 DomainPasswordInformation, &q_info),
4106 "failed to query domain info level 1");
4108 info1 = q_info->info1;
4109 _info1 = info1;
4111 torture_assert(tctx,
4112 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4113 DomainLockoutInformation, &q_info),
4114 "failed to query domain info level 12");
4116 info12 = q_info->info12;
4117 _info12 = info12;
4119 /* run tests */
4121 for (i=0; i < ARRAY_SIZE(creds); i++) {
4123 /* skip trust tests for now */
4124 if (acct_flags & ACB_WSTRUST ||
4125 acct_flags & ACB_SVRTRUST ||
4126 acct_flags & ACB_DOMTRUST) {
4127 continue;
4130 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4131 domain_handle, user_handle, password,
4132 machine_credentials,
4133 creds[i].comment,
4134 creds[i].disabled,
4135 creds[i].interactive,
4136 creds[i].expected_success_status,
4137 &_info1, &_info12);
4138 if (!ret) {
4139 torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4140 } else {
4141 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4145 /* restore policies */
4147 s_info.info1 = info1;
4149 torture_assert(tctx,
4150 test_SetDomainInfo(b, tctx, domain_handle,
4151 DomainPasswordInformation, &s_info),
4152 "failed to set password information");
4154 s_info.info12 = info12;
4156 torture_assert(tctx,
4157 test_SetDomainInfo(b, tctx, domain_handle,
4158 DomainLockoutInformation, &s_info),
4159 "failed to set lockout information");
4161 return ret;
4164 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4165 struct dcerpc_pipe *lp,
4166 struct torture_context *tctx,
4167 struct policy_handle *domain_handle,
4168 struct policy_handle *lsa_handle,
4169 struct policy_handle *user_handle,
4170 const struct dom_sid *domain_sid,
4171 uint32_t rid,
4172 struct cli_credentials *machine_credentials)
4174 NTSTATUS status;
4175 bool ret = true;
4176 struct dcerpc_binding_handle *b = p->binding_handle;
4177 struct dcerpc_binding_handle *lb = lp->binding_handle;
4179 struct policy_handle lsa_acct_handle;
4180 struct dom_sid *user_sid;
4182 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4185 struct lsa_EnumAccountRights r;
4186 struct lsa_RightSet rights;
4188 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4190 r.in.handle = lsa_handle;
4191 r.in.sid = user_sid;
4192 r.out.rights = &rights;
4194 status = dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r);
4195 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4196 "Expected enum rights for account to fail");
4200 struct lsa_RightSet rights;
4201 struct lsa_StringLarge names[2];
4202 struct lsa_AddAccountRights r;
4204 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4206 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4207 init_lsa_StringLarge(&names[1], NULL);
4209 rights.count = 1;
4210 rights.names = names;
4212 r.in.handle = lsa_handle;
4213 r.in.sid = user_sid;
4214 r.in.rights = &rights;
4216 status = dcerpc_lsa_AddAccountRights_r(lb, tctx, &r);
4217 torture_assert_ntstatus_ok(tctx, status,
4218 "Failed to add privileges");
4222 struct lsa_EnumAccounts r;
4223 uint32_t resume_handle = 0;
4224 struct lsa_SidArray lsa_sid_array;
4225 int i;
4226 bool found_sid = false;
4228 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4230 r.in.handle = lsa_handle;
4231 r.in.num_entries = 0x1000;
4232 r.in.resume_handle = &resume_handle;
4233 r.out.sids = &lsa_sid_array;
4234 r.out.resume_handle = &resume_handle;
4236 status = dcerpc_lsa_EnumAccounts_r(lb, tctx, &r);
4237 torture_assert_ntstatus_ok(tctx, status,
4238 "Failed to enum accounts");
4240 for (i=0; i < lsa_sid_array.num_sids; i++) {
4241 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4242 found_sid = true;
4246 torture_assert(tctx, found_sid,
4247 "failed to list privileged account");
4251 struct lsa_EnumAccountRights r;
4252 struct lsa_RightSet user_rights;
4254 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4256 r.in.handle = lsa_handle;
4257 r.in.sid = user_sid;
4258 r.out.rights = &user_rights;
4260 status = dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r);
4261 torture_assert_ntstatus_ok(tctx, status,
4262 "Failed to enum rights for account");
4264 if (user_rights.count < 1) {
4265 torture_warning(tctx, "failed to find newly added rights");
4266 return false;
4271 struct lsa_OpenAccount r;
4273 torture_comment(tctx, "Testing LSA OpenAccount\n");
4275 r.in.handle = lsa_handle;
4276 r.in.sid = user_sid;
4277 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4278 r.out.acct_handle = &lsa_acct_handle;
4280 status = dcerpc_lsa_OpenAccount_r(lb, tctx, &r);
4281 torture_assert_ntstatus_ok(tctx, status,
4282 "Failed to open lsa account");
4286 struct lsa_GetSystemAccessAccount r;
4287 uint32_t access_mask;
4289 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4291 r.in.handle = &lsa_acct_handle;
4292 r.out.access_mask = &access_mask;
4294 status = dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r);
4295 torture_assert_ntstatus_ok(tctx, status,
4296 "Failed to get lsa system access account");
4300 struct lsa_Close r;
4302 torture_comment(tctx, "Testing LSA Close\n");
4304 r.in.handle = &lsa_acct_handle;
4305 r.out.handle = &lsa_acct_handle;
4307 status = dcerpc_lsa_Close_r(lb, tctx, &r);
4308 torture_assert_ntstatus_ok(tctx, status,
4309 "Failed to close lsa");
4313 struct samr_DeleteUser r;
4315 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4317 r.in.user_handle = user_handle;
4318 r.out.user_handle = user_handle;
4320 status = dcerpc_samr_DeleteUser_r(b, tctx, &r);
4321 torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
4325 struct lsa_EnumAccounts r;
4326 uint32_t resume_handle = 0;
4327 struct lsa_SidArray lsa_sid_array;
4328 int i;
4329 bool found_sid = false;
4331 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4333 r.in.handle = lsa_handle;
4334 r.in.num_entries = 0x1000;
4335 r.in.resume_handle = &resume_handle;
4336 r.out.sids = &lsa_sid_array;
4337 r.out.resume_handle = &resume_handle;
4339 status = dcerpc_lsa_EnumAccounts_r(lb, tctx, &r);
4340 torture_assert_ntstatus_ok(tctx, status,
4341 "Failed to enum accounts");
4343 for (i=0; i < lsa_sid_array.num_sids; i++) {
4344 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4345 found_sid = true;
4349 torture_assert(tctx, found_sid,
4350 "failed to list privileged account");
4354 struct lsa_EnumAccountRights r;
4355 struct lsa_RightSet user_rights;
4357 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4359 r.in.handle = lsa_handle;
4360 r.in.sid = user_sid;
4361 r.out.rights = &user_rights;
4363 status = dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r);
4364 torture_assert_ntstatus_ok(tctx, status,
4365 "Failed to enum rights for account");
4367 if (user_rights.count < 1) {
4368 torture_warning(tctx, "failed to find newly added rights");
4369 return false;
4374 struct lsa_OpenAccount r;
4376 torture_comment(tctx, "Testing LSA OpenAccount\n");
4378 r.in.handle = lsa_handle;
4379 r.in.sid = user_sid;
4380 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4381 r.out.acct_handle = &lsa_acct_handle;
4383 status = dcerpc_lsa_OpenAccount_r(lb, tctx, &r);
4384 torture_assert_ntstatus_ok(tctx, status,
4385 "Failed to open lsa account");
4389 struct lsa_GetSystemAccessAccount r;
4390 uint32_t access_mask;
4392 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4394 r.in.handle = &lsa_acct_handle;
4395 r.out.access_mask = &access_mask;
4397 status = dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r);
4398 torture_assert_ntstatus_ok(tctx, status,
4399 "Failed to get lsa system access account");
4403 struct lsa_DeleteObject r;
4405 torture_comment(tctx, "Testing LSA DeleteObject\n");
4407 r.in.handle = &lsa_acct_handle;
4408 r.out.handle = &lsa_acct_handle;
4410 status = dcerpc_lsa_DeleteObject_r(lb, tctx, &r);
4411 torture_assert_ntstatus_ok(tctx, status,
4412 "Failed to delete object");
4416 struct lsa_EnumAccounts r;
4417 uint32_t resume_handle = 0;
4418 struct lsa_SidArray lsa_sid_array;
4419 int i;
4420 bool found_sid = false;
4422 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4424 r.in.handle = lsa_handle;
4425 r.in.num_entries = 0x1000;
4426 r.in.resume_handle = &resume_handle;
4427 r.out.sids = &lsa_sid_array;
4428 r.out.resume_handle = &resume_handle;
4430 status = dcerpc_lsa_EnumAccounts_r(lb, tctx, &r);
4431 torture_assert_ntstatus_ok(tctx, status,
4432 "Failed to enum accounts");
4434 for (i=0; i < lsa_sid_array.num_sids; i++) {
4435 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4436 found_sid = true;
4440 torture_assert(tctx, !found_sid,
4441 "should not have listed privileged account");
4445 struct lsa_EnumAccountRights r;
4446 struct lsa_RightSet user_rights;
4448 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4450 r.in.handle = lsa_handle;
4451 r.in.sid = user_sid;
4452 r.out.rights = &user_rights;
4454 status = dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r);
4455 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4456 "Failed to enum rights for account");
4459 return ret;
4462 static bool test_user_ops(struct dcerpc_pipe *p,
4463 struct torture_context *tctx,
4464 struct policy_handle *user_handle,
4465 struct policy_handle *domain_handle,
4466 const struct dom_sid *domain_sid,
4467 uint32_t base_acct_flags,
4468 const char *base_acct_name, enum torture_samr_choice which_ops,
4469 struct cli_credentials *machine_credentials)
4471 char *password = NULL;
4472 struct samr_QueryUserInfo q;
4473 union samr_UserInfo *info;
4474 NTSTATUS status;
4475 struct dcerpc_binding_handle *b = p->binding_handle;
4477 bool ret = true;
4478 int i;
4479 uint32_t rid;
4480 const uint32_t password_fields[] = {
4481 SAMR_FIELD_NT_PASSWORD_PRESENT,
4482 SAMR_FIELD_LM_PASSWORD_PRESENT,
4483 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4487 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4488 if (!NT_STATUS_IS_OK(status)) {
4489 ret = false;
4492 switch (which_ops) {
4493 case TORTURE_SAMR_USER_ATTRIBUTES:
4494 if (!test_QuerySecurity(b, tctx, user_handle)) {
4495 ret = false;
4498 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4499 ret = false;
4502 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4503 ret = false;
4506 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4507 base_acct_name)) {
4508 ret = false;
4511 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4512 ret = false;
4515 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4516 ret = false;
4519 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4520 ret = false;
4522 break;
4523 case TORTURE_SAMR_PASSWORDS:
4524 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4525 char simple_pass[9];
4526 char *v = generate_random_str(tctx, 1);
4528 ZERO_STRUCT(simple_pass);
4529 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4531 torture_comment(tctx, "Testing machine account password policy rules\n");
4533 /* Workstation trust accounts don't seem to need to honour password quality policy */
4534 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4535 ret = false;
4538 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4539 ret = false;
4542 /* reset again, to allow another 'user' password change */
4543 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4544 ret = false;
4547 /* Try a 'short' password */
4548 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4549 ret = false;
4552 /* Try a compleatly random password */
4553 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4554 ret = false;
4558 for (i = 0; password_fields[i]; i++) {
4559 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4560 ret = false;
4563 /* check it was set right */
4564 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4565 ret = false;
4569 for (i = 0; password_fields[i]; i++) {
4570 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4571 ret = false;
4574 /* check it was set right */
4575 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4576 ret = false;
4580 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4581 ret = false;
4584 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4585 ret = false;
4588 if (torture_setting_bool(tctx, "samba4", false)) {
4589 torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
4590 } else {
4592 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4593 ret = false;
4596 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4597 ret = false;
4600 for (i = 0; password_fields[i]; i++) {
4602 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4603 /* we need to skip as that would break
4604 * the ChangePasswordUser3 verify */
4605 continue;
4608 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4609 ret = false;
4612 /* check it was set right */
4613 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4614 ret = false;
4619 q.in.user_handle = user_handle;
4620 q.in.level = 5;
4621 q.out.info = &info;
4623 status = dcerpc_samr_QueryUserInfo_r(b, tctx, &q);
4624 if (!NT_STATUS_IS_OK(status)) {
4625 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4626 q.in.level, nt_errstr(status));
4627 ret = false;
4628 } else {
4629 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4630 if ((info->info5.acct_flags) != expected_flags) {
4631 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4632 info->info5.acct_flags,
4633 expected_flags);
4634 /* FIXME: GD */
4635 if (!torture_setting_bool(tctx, "samba3", false)) {
4636 ret = false;
4639 if (info->info5.rid != rid) {
4640 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4641 info->info5.rid, rid);
4646 break;
4648 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4650 /* test last password change timestamp behaviour */
4651 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4652 base_acct_name,
4653 user_handle, &password,
4654 machine_credentials)) {
4655 ret = false;
4658 if (ret == true) {
4659 torture_comment(tctx, "pwdLastSet test succeeded\n");
4660 } else {
4661 torture_warning(tctx, "pwdLastSet test failed\n");
4664 break;
4666 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4668 /* test bad pwd count change behaviour */
4669 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4670 base_acct_name,
4671 domain_handle,
4672 user_handle, &password,
4673 machine_credentials)) {
4674 ret = false;
4677 if (ret == true) {
4678 torture_comment(tctx, "badPwdCount test succeeded\n");
4679 } else {
4680 torture_warning(tctx, "badPwdCount test failed\n");
4683 break;
4685 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4687 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4688 base_acct_name,
4689 domain_handle,
4690 user_handle, &password,
4691 machine_credentials))
4693 ret = false;
4696 if (ret == true) {
4697 torture_comment(tctx, "lockout test succeeded\n");
4698 } else {
4699 torture_warning(tctx, "lockout test failed\n");
4702 break;
4705 case TORTURE_SAMR_USER_PRIVILEGES: {
4707 struct dcerpc_pipe *lp;
4708 struct policy_handle *lsa_handle;
4709 struct dcerpc_binding_handle *lb;
4711 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4712 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4713 lb = lp->binding_handle;
4715 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4716 ret = false;
4719 if (!test_DeleteUser_with_privs(p, lp, tctx,
4720 domain_handle, lsa_handle, user_handle,
4721 domain_sid, rid,
4722 machine_credentials)) {
4723 ret = false;
4726 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4727 ret = false;
4730 if (!ret) {
4731 torture_warning(tctx, "privileged user delete test failed\n");
4734 break;
4736 case TORTURE_SAMR_OTHER:
4737 case TORTURE_SAMR_MANY_ACCOUNTS:
4738 case TORTURE_SAMR_MANY_GROUPS:
4739 case TORTURE_SAMR_MANY_ALIASES:
4740 /* We just need the account to exist */
4741 break;
4743 return ret;
4746 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4747 struct torture_context *tctx,
4748 struct policy_handle *alias_handle,
4749 const struct dom_sid *domain_sid)
4751 bool ret = true;
4753 if (!torture_setting_bool(tctx, "samba3", false)) {
4754 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4755 ret = false;
4759 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4760 ret = false;
4763 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4764 ret = false;
4767 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
4768 ret = false;
4771 if (torture_setting_bool(tctx, "samba3", false) ||
4772 torture_setting_bool(tctx, "samba4", false)) {
4773 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4774 return ret;
4777 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
4778 ret = false;
4781 return ret;
4785 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
4786 struct torture_context *tctx,
4787 struct policy_handle *user_handle)
4789 struct samr_DeleteUser d;
4790 NTSTATUS status;
4791 torture_comment(tctx, "Testing DeleteUser\n");
4793 d.in.user_handle = user_handle;
4794 d.out.user_handle = user_handle;
4796 status = dcerpc_samr_DeleteUser_r(b, tctx, &d);
4797 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
4799 return true;
4802 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
4803 struct torture_context *tctx,
4804 struct policy_handle *handle, const char *name)
4806 NTSTATUS status;
4807 struct samr_DeleteUser d;
4808 struct policy_handle user_handle;
4809 uint32_t rid;
4811 status = test_LookupName(b, tctx, handle, name, &rid);
4812 if (!NT_STATUS_IS_OK(status)) {
4813 goto failed;
4816 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
4817 if (!NT_STATUS_IS_OK(status)) {
4818 goto failed;
4821 d.in.user_handle = &user_handle;
4822 d.out.user_handle = &user_handle;
4823 status = dcerpc_samr_DeleteUser_r(b, tctx, &d);
4824 if (!NT_STATUS_IS_OK(status)) {
4825 goto failed;
4828 return true;
4830 failed:
4831 torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
4832 return false;
4836 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
4837 struct torture_context *tctx,
4838 struct policy_handle *handle, const char *name)
4840 NTSTATUS status;
4841 struct samr_OpenGroup r;
4842 struct samr_DeleteDomainGroup d;
4843 struct policy_handle group_handle;
4844 uint32_t rid;
4846 status = test_LookupName(b, tctx, handle, name, &rid);
4847 if (!NT_STATUS_IS_OK(status)) {
4848 goto failed;
4851 r.in.domain_handle = handle;
4852 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4853 r.in.rid = rid;
4854 r.out.group_handle = &group_handle;
4855 status = dcerpc_samr_OpenGroup_r(b, tctx, &r);
4856 if (!NT_STATUS_IS_OK(status)) {
4857 goto failed;
4860 d.in.group_handle = &group_handle;
4861 d.out.group_handle = &group_handle;
4862 status = dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d);
4863 if (!NT_STATUS_IS_OK(status)) {
4864 goto failed;
4867 return true;
4869 failed:
4870 torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
4871 return false;
4875 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
4876 struct torture_context *tctx,
4877 struct policy_handle *domain_handle,
4878 const char *name)
4880 NTSTATUS status;
4881 struct samr_OpenAlias r;
4882 struct samr_DeleteDomAlias d;
4883 struct policy_handle alias_handle;
4884 uint32_t rid;
4886 torture_comment(tctx, "testing DeleteAlias_byname\n");
4888 status = test_LookupName(b, tctx, domain_handle, name, &rid);
4889 if (!NT_STATUS_IS_OK(status)) {
4890 goto failed;
4893 r.in.domain_handle = domain_handle;
4894 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4895 r.in.rid = rid;
4896 r.out.alias_handle = &alias_handle;
4897 status = dcerpc_samr_OpenAlias_r(b, tctx, &r);
4898 if (!NT_STATUS_IS_OK(status)) {
4899 goto failed;
4902 d.in.alias_handle = &alias_handle;
4903 d.out.alias_handle = &alias_handle;
4904 status = dcerpc_samr_DeleteDomAlias_r(b, tctx, &d);
4905 if (!NT_STATUS_IS_OK(status)) {
4906 goto failed;
4909 return true;
4911 failed:
4912 torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
4913 return false;
4916 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
4917 struct torture_context *tctx,
4918 struct policy_handle *alias_handle)
4920 struct samr_DeleteDomAlias d;
4921 NTSTATUS status;
4922 bool ret = true;
4924 torture_comment(tctx, "Testing DeleteAlias\n");
4926 d.in.alias_handle = alias_handle;
4927 d.out.alias_handle = alias_handle;
4929 status = dcerpc_samr_DeleteDomAlias_r(b, tctx, &d);
4930 if (!NT_STATUS_IS_OK(status)) {
4931 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(status));
4932 ret = false;
4935 return ret;
4938 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
4939 struct torture_context *tctx,
4940 struct policy_handle *domain_handle,
4941 const char *alias_name,
4942 struct policy_handle *alias_handle,
4943 const struct dom_sid *domain_sid,
4944 bool test_alias)
4946 NTSTATUS status;
4947 struct samr_CreateDomAlias r;
4948 struct lsa_String name;
4949 uint32_t rid;
4950 bool ret = true;
4952 init_lsa_String(&name, alias_name);
4953 r.in.domain_handle = domain_handle;
4954 r.in.alias_name = &name;
4955 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4956 r.out.alias_handle = alias_handle;
4957 r.out.rid = &rid;
4959 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
4961 status = dcerpc_samr_CreateDomAlias_r(b, tctx, &r);
4963 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4964 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4965 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
4966 return true;
4967 } else {
4968 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
4969 nt_errstr(status));
4970 return false;
4974 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
4975 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
4976 return false;
4978 status = dcerpc_samr_CreateDomAlias_r(b, tctx, &r);
4981 if (!NT_STATUS_IS_OK(status)) {
4982 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(status));
4983 return false;
4986 if (!test_alias) {
4987 return ret;
4990 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
4991 ret = false;
4994 return ret;
4997 static bool test_ChangePassword(struct dcerpc_pipe *p,
4998 struct torture_context *tctx,
4999 const char *acct_name,
5000 struct policy_handle *domain_handle, char **password)
5002 bool ret = true;
5003 struct dcerpc_binding_handle *b = p->binding_handle;
5005 if (!*password) {
5006 return false;
5009 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5010 ret = false;
5013 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5014 ret = false;
5017 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5018 ret = false;
5021 /* test what happens when setting the old password again */
5022 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5023 ret = false;
5027 char simple_pass[9];
5028 char *v = generate_random_str(tctx, 1);
5030 ZERO_STRUCT(simple_pass);
5031 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5033 /* test what happens when picking a simple password */
5034 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5035 ret = false;
5039 /* set samr_SetDomainInfo level 1 with min_length 5 */
5041 struct samr_QueryDomainInfo r;
5042 union samr_DomainInfo *info = NULL;
5043 struct samr_SetDomainInfo s;
5044 uint16_t len_old, len;
5045 uint32_t pwd_prop_old;
5046 int64_t min_pwd_age_old;
5047 NTSTATUS status;
5049 len = 5;
5051 r.in.domain_handle = domain_handle;
5052 r.in.level = 1;
5053 r.out.info = &info;
5055 torture_comment(tctx, "testing samr_QueryDomainInfo level 1\n");
5056 status = dcerpc_samr_QueryDomainInfo_r(b, tctx, &r);
5057 if (!NT_STATUS_IS_OK(status)) {
5058 return false;
5061 s.in.domain_handle = domain_handle;
5062 s.in.level = 1;
5063 s.in.info = info;
5065 /* remember the old min length, so we can reset it */
5066 len_old = s.in.info->info1.min_password_length;
5067 s.in.info->info1.min_password_length = len;
5068 pwd_prop_old = s.in.info->info1.password_properties;
5069 /* turn off password complexity checks for this test */
5070 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5072 min_pwd_age_old = s.in.info->info1.min_password_age;
5073 s.in.info->info1.min_password_age = 0;
5075 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
5076 status = dcerpc_samr_SetDomainInfo_r(b, tctx, &s);
5077 if (!NT_STATUS_IS_OK(status)) {
5078 return false;
5081 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5083 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5084 ret = false;
5087 s.in.info->info1.min_password_length = len_old;
5088 s.in.info->info1.password_properties = pwd_prop_old;
5089 s.in.info->info1.min_password_age = min_pwd_age_old;
5091 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
5092 status = dcerpc_samr_SetDomainInfo_r(b, tctx, &s);
5093 if (!NT_STATUS_IS_OK(status)) {
5094 return false;
5100 NTSTATUS status;
5101 struct samr_OpenUser r;
5102 struct samr_QueryUserInfo q;
5103 union samr_UserInfo *info;
5104 struct samr_LookupNames n;
5105 struct policy_handle user_handle;
5106 struct samr_Ids rids, types;
5108 n.in.domain_handle = domain_handle;
5109 n.in.num_names = 1;
5110 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5111 n.in.names[0].string = acct_name;
5112 n.out.rids = &rids;
5113 n.out.types = &types;
5115 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
5116 if (!NT_STATUS_IS_OK(status)) {
5117 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5118 return false;
5121 r.in.domain_handle = domain_handle;
5122 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5123 r.in.rid = n.out.rids->ids[0];
5124 r.out.user_handle = &user_handle;
5126 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
5129 return false;
5132 q.in.user_handle = &user_handle;
5133 q.in.level = 5;
5134 q.out.info = &info;
5136 status = dcerpc_samr_QueryUserInfo_r(b, tctx, &q);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(status));
5139 return false;
5142 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5144 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5145 info->info5.last_password_change, true)) {
5146 ret = false;
5150 /* we change passwords twice - this has the effect of verifying
5151 they were changed correctly for the final call */
5152 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5153 ret = false;
5156 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5157 ret = false;
5160 return ret;
5163 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5164 struct policy_handle *domain_handle,
5165 const char *user_name,
5166 struct policy_handle *user_handle_out,
5167 struct dom_sid *domain_sid,
5168 enum torture_samr_choice which_ops,
5169 struct cli_credentials *machine_credentials,
5170 bool test_user)
5173 TALLOC_CTX *user_ctx;
5175 NTSTATUS status;
5176 struct samr_CreateUser r;
5177 struct samr_QueryUserInfo q;
5178 union samr_UserInfo *info;
5179 struct samr_DeleteUser d;
5180 uint32_t rid;
5182 /* This call creates a 'normal' account - check that it really does */
5183 const uint32_t acct_flags = ACB_NORMAL;
5184 struct lsa_String name;
5185 bool ret = true;
5186 struct dcerpc_binding_handle *b = p->binding_handle;
5188 struct policy_handle user_handle;
5189 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5190 init_lsa_String(&name, user_name);
5192 r.in.domain_handle = domain_handle;
5193 r.in.account_name = &name;
5194 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5195 r.out.user_handle = &user_handle;
5196 r.out.rid = &rid;
5198 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5200 status = dcerpc_samr_CreateUser_r(b, user_ctx, &r);
5202 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5203 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5204 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5205 return true;
5206 } else {
5207 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5208 nt_errstr(status));
5209 return false;
5213 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5214 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5215 talloc_free(user_ctx);
5216 return false;
5218 status = dcerpc_samr_CreateUser_r(b, user_ctx, &r);
5221 if (!NT_STATUS_IS_OK(status)) {
5222 talloc_free(user_ctx);
5223 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(status));
5224 return false;
5227 if (!test_user) {
5228 if (user_handle_out) {
5229 *user_handle_out = user_handle;
5231 return ret;
5235 q.in.user_handle = &user_handle;
5236 q.in.level = 16;
5237 q.out.info = &info;
5239 status = dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q);
5240 if (!NT_STATUS_IS_OK(status)) {
5241 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5242 q.in.level, nt_errstr(status));
5243 ret = false;
5244 } else {
5245 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5246 torture_warning(tctx, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5247 info->info16.acct_flags,
5248 acct_flags);
5249 ret = false;
5253 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5254 domain_sid, acct_flags, name.string, which_ops,
5255 machine_credentials)) {
5256 ret = false;
5259 if (user_handle_out) {
5260 *user_handle_out = user_handle;
5261 } else {
5262 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5264 d.in.user_handle = &user_handle;
5265 d.out.user_handle = &user_handle;
5267 status = dcerpc_samr_DeleteUser_r(b, user_ctx, &d);
5268 if (!NT_STATUS_IS_OK(status)) {
5269 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
5270 ret = false;
5276 talloc_free(user_ctx);
5278 return ret;
5282 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5283 struct policy_handle *domain_handle,
5284 struct dom_sid *domain_sid,
5285 enum torture_samr_choice which_ops,
5286 struct cli_credentials *machine_credentials)
5288 NTSTATUS status;
5289 struct samr_CreateUser2 r;
5290 struct samr_QueryUserInfo q;
5291 union samr_UserInfo *info;
5292 struct samr_DeleteUser d;
5293 struct policy_handle user_handle;
5294 uint32_t rid;
5295 struct lsa_String name;
5296 bool ret = true;
5297 int i;
5298 struct dcerpc_binding_handle *b = p->binding_handle;
5300 struct {
5301 uint32_t acct_flags;
5302 const char *account_name;
5303 NTSTATUS nt_status;
5304 } account_types[] = {
5305 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5306 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5307 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5308 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5309 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5310 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5311 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5312 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5313 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5314 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5315 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5316 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5317 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5318 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5319 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5322 for (i = 0; account_types[i].account_name; i++) {
5323 TALLOC_CTX *user_ctx;
5324 uint32_t acct_flags = account_types[i].acct_flags;
5325 uint32_t access_granted;
5326 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5327 init_lsa_String(&name, account_types[i].account_name);
5329 r.in.domain_handle = domain_handle;
5330 r.in.account_name = &name;
5331 r.in.acct_flags = acct_flags;
5332 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5333 r.out.user_handle = &user_handle;
5334 r.out.access_granted = &access_granted;
5335 r.out.rid = &rid;
5337 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5339 status = dcerpc_samr_CreateUser2_r(b, user_ctx, &r);
5341 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5342 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5343 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5344 continue;
5345 } else {
5346 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5347 nt_errstr(status));
5348 ret = false;
5349 continue;
5353 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5354 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5355 talloc_free(user_ctx);
5356 ret = false;
5357 continue;
5359 status = dcerpc_samr_CreateUser2_r(b, user_ctx, &r);
5362 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
5363 torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5364 nt_errstr(status), nt_errstr(account_types[i].nt_status));
5365 ret = false;
5368 if (NT_STATUS_IS_OK(status)) {
5369 q.in.user_handle = &user_handle;
5370 q.in.level = 5;
5371 q.out.info = &info;
5373 status = dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q);
5374 if (!NT_STATUS_IS_OK(status)) {
5375 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5376 q.in.level, nt_errstr(status));
5377 ret = false;
5378 } else {
5379 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5380 if (acct_flags == ACB_NORMAL) {
5381 expected_flags |= ACB_PW_EXPIRED;
5383 if ((info->info5.acct_flags) != expected_flags) {
5384 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5385 info->info5.acct_flags,
5386 expected_flags);
5387 ret = false;
5389 switch (acct_flags) {
5390 case ACB_SVRTRUST:
5391 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5392 torture_warning(tctx, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5393 DOMAIN_RID_DCS, info->info5.primary_gid);
5394 ret = false;
5396 break;
5397 case ACB_WSTRUST:
5398 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5399 torture_warning(tctx, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5400 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5401 ret = false;
5403 break;
5404 case ACB_NORMAL:
5405 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5406 torture_warning(tctx, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5407 DOMAIN_RID_USERS, info->info5.primary_gid);
5408 ret = false;
5410 break;
5414 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5415 domain_sid, acct_flags, name.string, which_ops,
5416 machine_credentials)) {
5417 ret = false;
5420 if (!policy_handle_empty(&user_handle)) {
5421 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5423 d.in.user_handle = &user_handle;
5424 d.out.user_handle = &user_handle;
5426 status = dcerpc_samr_DeleteUser_r(b, user_ctx, &d);
5427 if (!NT_STATUS_IS_OK(status)) {
5428 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
5429 ret = false;
5433 talloc_free(user_ctx);
5436 return ret;
5439 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5440 struct torture_context *tctx,
5441 struct policy_handle *handle)
5443 NTSTATUS status;
5444 struct samr_QueryAliasInfo r;
5445 union samr_AliasInfo *info;
5446 uint16_t levels[] = {1, 2, 3};
5447 int i;
5448 bool ret = true;
5450 for (i=0;i<ARRAY_SIZE(levels);i++) {
5451 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5453 r.in.alias_handle = handle;
5454 r.in.level = levels[i];
5455 r.out.info = &info;
5457 status = dcerpc_samr_QueryAliasInfo_r(b, tctx, &r);
5458 if (!NT_STATUS_IS_OK(status)) {
5459 torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5460 levels[i], nt_errstr(status));
5461 ret = false;
5465 return ret;
5468 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5469 struct torture_context *tctx,
5470 struct policy_handle *handle)
5472 NTSTATUS status;
5473 struct samr_QueryGroupInfo r;
5474 union samr_GroupInfo *info;
5475 uint16_t levels[] = {1, 2, 3, 4, 5};
5476 int i;
5477 bool ret = true;
5479 for (i=0;i<ARRAY_SIZE(levels);i++) {
5480 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5482 r.in.group_handle = handle;
5483 r.in.level = levels[i];
5484 r.out.info = &info;
5486 status = dcerpc_samr_QueryGroupInfo_r(b, tctx, &r);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5489 levels[i], nt_errstr(status));
5490 ret = false;
5494 return ret;
5497 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5498 struct torture_context *tctx,
5499 struct policy_handle *handle)
5501 NTSTATUS status;
5502 struct samr_QueryGroupMember r;
5503 struct samr_RidTypeArray *rids = NULL;
5504 bool ret = true;
5506 torture_comment(tctx, "Testing QueryGroupMember\n");
5508 r.in.group_handle = handle;
5509 r.out.rids = &rids;
5511 status = dcerpc_samr_QueryGroupMember_r(b, tctx, &r);
5512 if (!NT_STATUS_IS_OK(status)) {
5513 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(status));
5514 ret = false;
5517 return ret;
5521 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5522 struct torture_context *tctx,
5523 struct policy_handle *handle)
5525 NTSTATUS status;
5526 struct samr_QueryGroupInfo r;
5527 union samr_GroupInfo *info;
5528 struct samr_SetGroupInfo s;
5529 uint16_t levels[] = {1, 2, 3, 4};
5530 uint16_t set_ok[] = {0, 1, 1, 1};
5531 int i;
5532 bool ret = true;
5534 for (i=0;i<ARRAY_SIZE(levels);i++) {
5535 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5537 r.in.group_handle = handle;
5538 r.in.level = levels[i];
5539 r.out.info = &info;
5541 status = dcerpc_samr_QueryGroupInfo_r(b, tctx, &r);
5542 if (!NT_STATUS_IS_OK(status)) {
5543 torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5544 levels[i], nt_errstr(status));
5545 ret = false;
5548 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5550 s.in.group_handle = handle;
5551 s.in.level = levels[i];
5552 s.in.info = *r.out.info;
5554 #if 0
5555 /* disabled this, as it changes the name only from the point of view of samr,
5556 but leaves the name from the point of view of w2k3 internals (and ldap). This means
5557 the name is still reserved, so creating the old name fails, but deleting by the old name
5558 also fails */
5559 if (s.in.level == 2) {
5560 init_lsa_String(&s.in.info->string, "NewName");
5562 #endif
5564 if (s.in.level == 4) {
5565 init_lsa_String(&s.in.info->description, "test description");
5568 status = dcerpc_samr_SetGroupInfo_r(b, tctx, &s);
5569 if (set_ok[i]) {
5570 if (!NT_STATUS_IS_OK(status)) {
5571 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5572 r.in.level, nt_errstr(status));
5573 ret = false;
5574 continue;
5576 } else {
5577 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5578 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5579 r.in.level, nt_errstr(status));
5580 ret = false;
5581 continue;
5586 return ret;
5589 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5590 struct torture_context *tctx,
5591 struct policy_handle *handle)
5593 NTSTATUS status;
5594 struct samr_QueryUserInfo r;
5595 union samr_UserInfo *info;
5596 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5597 11, 12, 13, 14, 16, 17, 20, 21};
5598 int i;
5599 bool ret = true;
5601 for (i=0;i<ARRAY_SIZE(levels);i++) {
5602 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5604 r.in.user_handle = handle;
5605 r.in.level = levels[i];
5606 r.out.info = &info;
5608 status = dcerpc_samr_QueryUserInfo_r(b, tctx, &r);
5609 if (!NT_STATUS_IS_OK(status)) {
5610 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5611 levels[i], nt_errstr(status));
5612 ret = false;
5616 return ret;
5619 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5620 struct torture_context *tctx,
5621 struct policy_handle *handle)
5623 NTSTATUS status;
5624 struct samr_QueryUserInfo2 r;
5625 union samr_UserInfo *info;
5626 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5627 11, 12, 13, 14, 16, 17, 20, 21};
5628 int i;
5629 bool ret = true;
5631 for (i=0;i<ARRAY_SIZE(levels);i++) {
5632 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5634 r.in.user_handle = handle;
5635 r.in.level = levels[i];
5636 r.out.info = &info;
5638 status = dcerpc_samr_QueryUserInfo2_r(b, tctx, &r);
5639 if (!NT_STATUS_IS_OK(status)) {
5640 torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5641 levels[i], nt_errstr(status));
5642 ret = false;
5646 return ret;
5649 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5650 struct torture_context *tctx,
5651 struct policy_handle *handle, uint32_t rid)
5653 NTSTATUS status;
5654 struct samr_OpenUser r;
5655 struct policy_handle user_handle;
5656 bool ret = true;
5658 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5660 r.in.domain_handle = handle;
5661 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5662 r.in.rid = rid;
5663 r.out.user_handle = &user_handle;
5665 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
5666 if (!NT_STATUS_IS_OK(status)) {
5667 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
5668 return false;
5671 if (!test_QuerySecurity(b, tctx, &user_handle)) {
5672 ret = false;
5675 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5676 ret = false;
5679 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5680 ret = false;
5683 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5684 ret = false;
5687 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5688 ret = false;
5691 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5692 ret = false;
5695 return ret;
5698 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5699 struct torture_context *tctx,
5700 struct policy_handle *handle, uint32_t rid)
5702 NTSTATUS status;
5703 struct samr_OpenGroup r;
5704 struct policy_handle group_handle;
5705 bool ret = true;
5707 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5709 r.in.domain_handle = handle;
5710 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5711 r.in.rid = rid;
5712 r.out.group_handle = &group_handle;
5714 status = dcerpc_samr_OpenGroup_r(b, tctx, &r);
5715 if (!NT_STATUS_IS_OK(status)) {
5716 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
5717 return false;
5720 if (!torture_setting_bool(tctx, "samba3", false)) {
5721 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5722 ret = false;
5726 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5727 ret = false;
5730 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5731 ret = false;
5734 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5735 ret = false;
5738 return ret;
5741 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5742 struct torture_context *tctx,
5743 struct policy_handle *handle, uint32_t rid)
5745 NTSTATUS status;
5746 struct samr_OpenAlias r;
5747 struct policy_handle alias_handle;
5748 bool ret = true;
5750 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5752 r.in.domain_handle = handle;
5753 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5754 r.in.rid = rid;
5755 r.out.alias_handle = &alias_handle;
5757 status = dcerpc_samr_OpenAlias_r(b, tctx, &r);
5758 if (!NT_STATUS_IS_OK(status)) {
5759 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
5760 return false;
5763 if (!torture_setting_bool(tctx, "samba3", false)) {
5764 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
5765 ret = false;
5769 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
5770 ret = false;
5773 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
5774 ret = false;
5777 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
5778 ret = false;
5781 return ret;
5784 static bool check_mask(struct dcerpc_binding_handle *b,
5785 struct torture_context *tctx,
5786 struct policy_handle *handle, uint32_t rid,
5787 uint32_t acct_flag_mask)
5789 NTSTATUS status;
5790 struct samr_OpenUser r;
5791 struct samr_QueryUserInfo q;
5792 union samr_UserInfo *info;
5793 struct policy_handle user_handle;
5794 bool ret = true;
5796 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5798 r.in.domain_handle = handle;
5799 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5800 r.in.rid = rid;
5801 r.out.user_handle = &user_handle;
5803 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
5804 if (!NT_STATUS_IS_OK(status)) {
5805 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
5806 return false;
5809 q.in.user_handle = &user_handle;
5810 q.in.level = 16;
5811 q.out.info = &info;
5813 status = dcerpc_samr_QueryUserInfo_r(b, tctx, &q);
5814 if (!NT_STATUS_IS_OK(status)) {
5815 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
5816 nt_errstr(status));
5817 ret = false;
5818 } else {
5819 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
5820 torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
5821 acct_flag_mask, info->info16.acct_flags, rid);
5822 ret = false;
5826 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5827 ret = false;
5830 return ret;
5833 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
5834 struct torture_context *tctx,
5835 struct policy_handle *handle)
5837 NTSTATUS status = STATUS_MORE_ENTRIES;
5838 struct samr_EnumDomainUsers r;
5839 uint32_t mask, resume_handle=0;
5840 int i, mask_idx;
5841 bool ret = true;
5842 struct samr_LookupNames n;
5843 struct samr_LookupRids lr ;
5844 struct lsa_Strings names;
5845 struct samr_Ids rids, types;
5846 struct samr_SamArray *sam = NULL;
5847 uint32_t num_entries = 0;
5849 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
5850 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
5851 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
5852 ACB_PWNOEXP, 0};
5854 torture_comment(tctx, "Testing EnumDomainUsers\n");
5856 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
5857 r.in.domain_handle = handle;
5858 r.in.resume_handle = &resume_handle;
5859 r.in.acct_flags = mask = masks[mask_idx];
5860 r.in.max_size = (uint32_t)-1;
5861 r.out.resume_handle = &resume_handle;
5862 r.out.num_entries = &num_entries;
5863 r.out.sam = &sam;
5865 status = dcerpc_samr_EnumDomainUsers_r(b, tctx, &r);
5866 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5867 !NT_STATUS_IS_OK(status)) {
5868 torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(status));
5869 return false;
5872 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
5874 if (sam->count == 0) {
5875 continue;
5878 for (i=0;i<sam->count;i++) {
5879 if (mask) {
5880 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
5881 ret = false;
5883 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
5884 ret = false;
5889 torture_comment(tctx, "Testing LookupNames\n");
5890 n.in.domain_handle = handle;
5891 n.in.num_names = sam->count;
5892 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
5893 n.out.rids = &rids;
5894 n.out.types = &types;
5895 for (i=0;i<sam->count;i++) {
5896 n.in.names[i].string = sam->entries[i].name.string;
5898 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
5899 if (!NT_STATUS_IS_OK(status)) {
5900 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5901 ret = false;
5905 torture_comment(tctx, "Testing LookupRids\n");
5906 lr.in.domain_handle = handle;
5907 lr.in.num_rids = sam->count;
5908 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
5909 lr.out.names = &names;
5910 lr.out.types = &types;
5911 for (i=0;i<sam->count;i++) {
5912 lr.in.rids[i] = sam->entries[i].idx;
5914 status = dcerpc_samr_LookupRids_r(b, tctx, &lr);
5915 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
5917 return ret;
5921 try blasting the server with a bunch of sync requests
5923 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
5924 struct policy_handle *handle)
5926 NTSTATUS status;
5927 struct samr_EnumDomainUsers r;
5928 uint32_t resume_handle=0;
5929 int i;
5930 #define ASYNC_COUNT 100
5931 struct tevent_req *req[ASYNC_COUNT];
5933 if (!torture_setting_bool(tctx, "dangerous", false)) {
5934 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
5937 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
5939 r.in.domain_handle = handle;
5940 r.in.resume_handle = &resume_handle;
5941 r.in.acct_flags = 0;
5942 r.in.max_size = (uint32_t)-1;
5943 r.out.resume_handle = &resume_handle;
5945 for (i=0;i<ASYNC_COUNT;i++) {
5946 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
5949 for (i=0;i<ASYNC_COUNT;i++) {
5950 tevent_req_poll(req[i], tctx->ev);
5951 status = dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx);
5952 if (!NT_STATUS_IS_OK(status)) {
5953 torture_warning(tctx, "EnumDomainUsers[%d] failed - %s\n",
5954 i, nt_errstr(status));
5955 return false;
5959 torture_comment(tctx, "%d async requests OK\n", i);
5961 return true;
5964 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
5965 struct torture_context *tctx,
5966 struct policy_handle *handle)
5968 NTSTATUS status;
5969 struct samr_EnumDomainGroups r;
5970 uint32_t resume_handle=0;
5971 struct samr_SamArray *sam = NULL;
5972 uint32_t num_entries = 0;
5973 int i;
5974 bool ret = true;
5975 bool universal_group_found = false;
5977 torture_comment(tctx, "Testing EnumDomainGroups\n");
5979 r.in.domain_handle = handle;
5980 r.in.resume_handle = &resume_handle;
5981 r.in.max_size = (uint32_t)-1;
5982 r.out.resume_handle = &resume_handle;
5983 r.out.num_entries = &num_entries;
5984 r.out.sam = &sam;
5986 status = dcerpc_samr_EnumDomainGroups_r(b, tctx, &r);
5987 if (!NT_STATUS_IS_OK(status)) {
5988 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(status));
5989 return false;
5992 if (!sam) {
5993 return false;
5996 for (i=0;i<sam->count;i++) {
5997 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
5998 ret = false;
6000 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6001 "Enterprise Admins") == 0)) {
6002 universal_group_found = true;
6006 /* when we are running this on s4 we should get back at least the
6007 * "Enterprise Admins" universal group. If we don't get a group entry
6008 * at all we probably are performing the test on the builtin domain.
6009 * So ignore this case. */
6010 if (torture_setting_bool(tctx, "samba4", false)) {
6011 if ((sam->count > 0) && (!universal_group_found)) {
6012 ret = false;
6016 return ret;
6019 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6020 struct torture_context *tctx,
6021 struct policy_handle *handle)
6023 NTSTATUS status;
6024 struct samr_EnumDomainAliases r;
6025 uint32_t resume_handle=0;
6026 struct samr_SamArray *sam = NULL;
6027 uint32_t num_entries = 0;
6028 int i;
6029 bool ret = true;
6031 torture_comment(tctx, "Testing EnumDomainAliases\n");
6033 r.in.domain_handle = handle;
6034 r.in.resume_handle = &resume_handle;
6035 r.in.max_size = (uint32_t)-1;
6036 r.out.sam = &sam;
6037 r.out.num_entries = &num_entries;
6038 r.out.resume_handle = &resume_handle;
6040 status = dcerpc_samr_EnumDomainAliases_r(b, tctx, &r);
6041 if (!NT_STATUS_IS_OK(status)) {
6042 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(status));
6043 return false;
6046 if (!sam) {
6047 return false;
6050 for (i=0;i<sam->count;i++) {
6051 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6052 ret = false;
6056 return ret;
6059 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6060 struct torture_context *tctx,
6061 struct policy_handle *handle)
6063 NTSTATUS status;
6064 struct samr_GetDisplayEnumerationIndex r;
6065 bool ret = true;
6066 uint16_t levels[] = {1, 2, 3, 4, 5};
6067 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6068 struct lsa_String name;
6069 uint32_t idx = 0;
6070 int i;
6072 for (i=0;i<ARRAY_SIZE(levels);i++) {
6073 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6075 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6077 r.in.domain_handle = handle;
6078 r.in.level = levels[i];
6079 r.in.name = &name;
6080 r.out.idx = &idx;
6082 status = dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r);
6084 if (ok_lvl[i] &&
6085 !NT_STATUS_IS_OK(status) &&
6086 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6087 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6088 levels[i], nt_errstr(status));
6089 ret = false;
6092 init_lsa_String(&name, "zzzzzzzz");
6094 status = dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r);
6096 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6097 torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6098 levels[i], nt_errstr(status));
6099 ret = false;
6103 return ret;
6106 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6107 struct torture_context *tctx,
6108 struct policy_handle *handle)
6110 NTSTATUS status;
6111 struct samr_GetDisplayEnumerationIndex2 r;
6112 bool ret = true;
6113 uint16_t levels[] = {1, 2, 3, 4, 5};
6114 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6115 struct lsa_String name;
6116 uint32_t idx = 0;
6117 int i;
6119 for (i=0;i<ARRAY_SIZE(levels);i++) {
6120 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6122 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6124 r.in.domain_handle = handle;
6125 r.in.level = levels[i];
6126 r.in.name = &name;
6127 r.out.idx = &idx;
6129 status = dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r);
6130 if (ok_lvl[i] &&
6131 !NT_STATUS_IS_OK(status) &&
6132 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6133 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6134 levels[i], nt_errstr(status));
6135 ret = false;
6138 init_lsa_String(&name, "zzzzzzzz");
6140 status = dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r);
6141 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6142 torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6143 levels[i], nt_errstr(status));
6144 ret = false;
6148 return ret;
6151 #define STRING_EQUAL_QUERY(s1, s2, user) \
6152 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6153 /* odd, but valid */ \
6154 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6155 torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6156 #s1, user.string, s1.string, s2.string, __location__); \
6157 ret = false; \
6159 #define INT_EQUAL_QUERY(s1, s2, user) \
6160 if (s1 != s2) { \
6161 torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6162 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6163 ret = false; \
6166 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6167 struct torture_context *tctx,
6168 struct samr_QueryDisplayInfo *querydisplayinfo,
6169 bool *seen_testuser)
6171 struct samr_OpenUser r;
6172 struct samr_QueryUserInfo q;
6173 union samr_UserInfo *info;
6174 struct policy_handle user_handle;
6175 int i, ret = true;
6176 NTSTATUS status;
6177 r.in.domain_handle = querydisplayinfo->in.domain_handle;
6178 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6179 for (i = 0; ; i++) {
6180 switch (querydisplayinfo->in.level) {
6181 case 1:
6182 if (i >= querydisplayinfo->out.info->info1.count) {
6183 return ret;
6185 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6186 break;
6187 case 2:
6188 if (i >= querydisplayinfo->out.info->info2.count) {
6189 return ret;
6191 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6192 break;
6193 case 3:
6194 /* Groups */
6195 case 4:
6196 case 5:
6197 /* Not interested in validating just the account name */
6198 return true;
6201 r.out.user_handle = &user_handle;
6203 switch (querydisplayinfo->in.level) {
6204 case 1:
6205 case 2:
6206 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
6207 if (!NT_STATUS_IS_OK(status)) {
6208 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
6209 return false;
6213 q.in.user_handle = &user_handle;
6214 q.in.level = 21;
6215 q.out.info = &info;
6216 status = dcerpc_samr_QueryUserInfo_r(b, tctx, &q);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
6219 return false;
6222 switch (querydisplayinfo->in.level) {
6223 case 1:
6224 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6225 *seen_testuser = true;
6227 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6228 info->info21.full_name, info->info21.account_name);
6229 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6230 info->info21.account_name, info->info21.account_name);
6231 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6232 info->info21.description, info->info21.account_name);
6233 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6234 info->info21.rid, info->info21.account_name);
6235 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6236 info->info21.acct_flags, info->info21.account_name);
6238 break;
6239 case 2:
6240 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6241 info->info21.account_name, info->info21.account_name);
6242 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6243 info->info21.description, info->info21.account_name);
6244 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6245 info->info21.rid, info->info21.account_name);
6246 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6247 info->info21.acct_flags, info->info21.account_name);
6249 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6250 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6251 info->info21.account_name.string);
6254 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6255 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6256 info->info21.account_name.string,
6257 querydisplayinfo->out.info->info2.entries[i].acct_flags,
6258 info->info21.acct_flags);
6259 return false;
6262 break;
6265 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6266 return false;
6269 return ret;
6272 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6273 struct torture_context *tctx,
6274 struct policy_handle *handle)
6276 NTSTATUS status;
6277 struct samr_QueryDisplayInfo r;
6278 struct samr_QueryDomainInfo dom_info;
6279 union samr_DomainInfo *info = NULL;
6280 bool ret = true;
6281 uint16_t levels[] = {1, 2, 3, 4, 5};
6282 int i;
6283 bool seen_testuser = false;
6284 uint32_t total_size;
6285 uint32_t returned_size;
6286 union samr_DispInfo disp_info;
6289 for (i=0;i<ARRAY_SIZE(levels);i++) {
6290 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6292 r.in.start_idx = 0;
6293 status = STATUS_MORE_ENTRIES;
6294 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6295 r.in.domain_handle = handle;
6296 r.in.level = levels[i];
6297 r.in.max_entries = 2;
6298 r.in.buf_size = (uint32_t)-1;
6299 r.out.total_size = &total_size;
6300 r.out.returned_size = &returned_size;
6301 r.out.info = &disp_info;
6303 status = dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r);
6304 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
6305 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6306 levels[i], nt_errstr(status));
6307 ret = false;
6309 switch (r.in.level) {
6310 case 1:
6311 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6312 ret = false;
6314 r.in.start_idx += r.out.info->info1.count;
6315 break;
6316 case 2:
6317 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6318 ret = false;
6320 r.in.start_idx += r.out.info->info2.count;
6321 break;
6322 case 3:
6323 r.in.start_idx += r.out.info->info3.count;
6324 break;
6325 case 4:
6326 r.in.start_idx += r.out.info->info4.count;
6327 break;
6328 case 5:
6329 r.in.start_idx += r.out.info->info5.count;
6330 break;
6333 dom_info.in.domain_handle = handle;
6334 dom_info.in.level = 2;
6335 dom_info.out.info = &info;
6337 /* Check number of users returned is correct */
6338 status = dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info);
6339 if (!NT_STATUS_IS_OK(status)) {
6340 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6341 r.in.level, nt_errstr(status));
6342 ret = false;
6343 break;
6345 switch (r.in.level) {
6346 case 1:
6347 case 4:
6348 if (info->general.num_users < r.in.start_idx) {
6349 /* On AD deployments this numbers don't match
6350 * since QueryDisplayInfo returns universal and
6351 * global groups, QueryDomainInfo only global
6352 * ones. */
6353 if (torture_setting_bool(tctx, "samba3", false)) {
6354 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6355 r.in.start_idx, info->general.num_groups,
6356 info->general.domain_name.string);
6357 ret = false;
6360 if (!seen_testuser) {
6361 struct policy_handle user_handle;
6362 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6363 torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6364 info->general.domain_name.string);
6365 ret = false;
6366 test_samr_handle_Close(b, tctx, &user_handle);
6369 break;
6370 case 3:
6371 case 5:
6372 if (info->general.num_groups != r.in.start_idx) {
6373 /* On AD deployments this numbers don't match
6374 * since QueryDisplayInfo returns universal and
6375 * global groups, QueryDomainInfo only global
6376 * ones. */
6377 if (torture_setting_bool(tctx, "samba3", false)) {
6378 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6379 r.in.start_idx, info->general.num_groups,
6380 info->general.domain_name.string);
6381 ret = false;
6385 break;
6390 return ret;
6393 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6394 struct torture_context *tctx,
6395 struct policy_handle *handle)
6397 NTSTATUS status;
6398 struct samr_QueryDisplayInfo2 r;
6399 bool ret = true;
6400 uint16_t levels[] = {1, 2, 3, 4, 5};
6401 int i;
6402 uint32_t total_size;
6403 uint32_t returned_size;
6404 union samr_DispInfo info;
6406 for (i=0;i<ARRAY_SIZE(levels);i++) {
6407 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6409 r.in.domain_handle = handle;
6410 r.in.level = levels[i];
6411 r.in.start_idx = 0;
6412 r.in.max_entries = 1000;
6413 r.in.buf_size = (uint32_t)-1;
6414 r.out.total_size = &total_size;
6415 r.out.returned_size = &returned_size;
6416 r.out.info = &info;
6418 status = dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r);
6419 if (!NT_STATUS_IS_OK(status)) {
6420 torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6421 levels[i], nt_errstr(status));
6422 ret = false;
6426 return ret;
6429 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6430 struct torture_context *tctx,
6431 struct policy_handle *handle)
6433 NTSTATUS status;
6434 struct samr_QueryDisplayInfo3 r;
6435 bool ret = true;
6436 uint16_t levels[] = {1, 2, 3, 4, 5};
6437 int i;
6438 uint32_t total_size;
6439 uint32_t returned_size;
6440 union samr_DispInfo info;
6442 for (i=0;i<ARRAY_SIZE(levels);i++) {
6443 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6445 r.in.domain_handle = handle;
6446 r.in.level = levels[i];
6447 r.in.start_idx = 0;
6448 r.in.max_entries = 1000;
6449 r.in.buf_size = (uint32_t)-1;
6450 r.out.total_size = &total_size;
6451 r.out.returned_size = &returned_size;
6452 r.out.info = &info;
6454 status = dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r);
6455 if (!NT_STATUS_IS_OK(status)) {
6456 torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6457 levels[i], nt_errstr(status));
6458 ret = false;
6462 return ret;
6466 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6467 struct torture_context *tctx,
6468 struct policy_handle *handle)
6470 NTSTATUS status;
6471 struct samr_QueryDisplayInfo r;
6472 bool ret = true;
6473 uint32_t total_size;
6474 uint32_t returned_size;
6475 union samr_DispInfo info;
6477 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6479 r.in.domain_handle = handle;
6480 r.in.level = 1;
6481 r.in.start_idx = 0;
6482 r.in.max_entries = 1;
6483 r.in.buf_size = (uint32_t)-1;
6484 r.out.total_size = &total_size;
6485 r.out.returned_size = &returned_size;
6486 r.out.info = &info;
6488 do {
6489 status = dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r);
6490 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
6491 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6492 torture_warning(tctx, "expected idx %d but got %d\n",
6493 r.in.start_idx + 1,
6494 r.out.info->info1.entries[0].idx);
6495 break;
6498 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
6499 !NT_STATUS_IS_OK(status)) {
6500 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6501 r.in.level, nt_errstr(status));
6502 ret = false;
6503 break;
6505 r.in.start_idx++;
6506 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
6507 NT_STATUS_IS_OK(status)) &&
6508 *r.out.returned_size != 0);
6510 return ret;
6513 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6514 struct torture_context *tctx,
6515 struct policy_handle *handle)
6517 NTSTATUS status;
6518 struct samr_QueryDomainInfo r;
6519 union samr_DomainInfo *info = NULL;
6520 struct samr_SetDomainInfo s;
6521 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6522 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
6523 int i;
6524 bool ret = true;
6525 struct dcerpc_binding_handle *b = p->binding_handle;
6526 const char *domain_comment = talloc_asprintf(tctx,
6527 "Tortured by Samba4 RPC-SAMR: %s",
6528 timestring(tctx, time(NULL)));
6530 s.in.domain_handle = handle;
6531 s.in.level = 4;
6532 s.in.info = talloc(tctx, union samr_DomainInfo);
6534 s.in.info->oem.oem_information.string = domain_comment;
6535 status = dcerpc_samr_SetDomainInfo_r(b, tctx, &s);
6536 if (!NT_STATUS_IS_OK(status)) {
6537 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6538 s.in.level, nt_errstr(status));
6539 return false;
6542 for (i=0;i<ARRAY_SIZE(levels);i++) {
6543 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6545 r.in.domain_handle = handle;
6546 r.in.level = levels[i];
6547 r.out.info = &info;
6549 status = dcerpc_samr_QueryDomainInfo_r(b, tctx, &r);
6550 if (!NT_STATUS_IS_OK(status)) {
6551 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6552 r.in.level, nt_errstr(status));
6553 ret = false;
6554 continue;
6557 switch (levels[i]) {
6558 case 2:
6559 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6560 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6561 levels[i], info->general.oem_information.string, domain_comment);
6562 if (!torture_setting_bool(tctx, "samba3", false)) {
6563 ret = false;
6566 if (!info->general.primary.string) {
6567 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6568 levels[i]);
6569 ret = false;
6570 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6571 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6572 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6573 levels[i], info->general.primary.string, dcerpc_server_name(p));
6576 break;
6577 case 4:
6578 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6579 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6580 levels[i], info->oem.oem_information.string, domain_comment);
6581 if (!torture_setting_bool(tctx, "samba3", false)) {
6582 ret = false;
6585 break;
6586 case 6:
6587 if (!info->info6.primary.string) {
6588 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6589 levels[i]);
6590 ret = false;
6592 break;
6593 case 11:
6594 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6595 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6596 levels[i], info->general2.general.oem_information.string, domain_comment);
6597 if (!torture_setting_bool(tctx, "samba3", false)) {
6598 ret = false;
6601 break;
6604 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6606 s.in.domain_handle = handle;
6607 s.in.level = levels[i];
6608 s.in.info = info;
6610 status = dcerpc_samr_SetDomainInfo_r(b, tctx, &s);
6611 if (set_ok[i]) {
6612 if (!NT_STATUS_IS_OK(status)) {
6613 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6614 r.in.level, nt_errstr(status));
6615 ret = false;
6616 continue;
6618 } else {
6619 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
6620 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6621 r.in.level, nt_errstr(status));
6622 ret = false;
6623 continue;
6627 status = dcerpc_samr_QueryDomainInfo_r(b, tctx, &r);
6628 if (!NT_STATUS_IS_OK(status)) {
6629 torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6630 r.in.level, nt_errstr(status));
6631 ret = false;
6632 continue;
6636 return ret;
6640 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6641 struct torture_context *tctx,
6642 struct policy_handle *handle)
6644 NTSTATUS status;
6645 struct samr_QueryDomainInfo2 r;
6646 union samr_DomainInfo *info = NULL;
6647 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6648 int i;
6649 bool ret = true;
6651 for (i=0;i<ARRAY_SIZE(levels);i++) {
6652 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6654 r.in.domain_handle = handle;
6655 r.in.level = levels[i];
6656 r.out.info = &info;
6658 status = dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r);
6659 if (!NT_STATUS_IS_OK(status)) {
6660 torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6661 r.in.level, nt_errstr(status));
6662 ret = false;
6663 continue;
6667 return true;
6670 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6671 set of group names. */
6672 static bool test_GroupList(struct dcerpc_binding_handle *b,
6673 struct torture_context *tctx,
6674 struct policy_handle *handle)
6676 struct samr_EnumDomainGroups q1;
6677 struct samr_QueryDisplayInfo q2;
6678 NTSTATUS status;
6679 uint32_t resume_handle=0;
6680 struct samr_SamArray *sam = NULL;
6681 uint32_t num_entries = 0;
6682 int i;
6683 bool ret = true;
6684 uint32_t total_size;
6685 uint32_t returned_size;
6686 union samr_DispInfo info;
6688 int num_names = 0;
6689 const char **names = NULL;
6691 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6693 q1.in.domain_handle = handle;
6694 q1.in.resume_handle = &resume_handle;
6695 q1.in.max_size = 5;
6696 q1.out.resume_handle = &resume_handle;
6697 q1.out.num_entries = &num_entries;
6698 q1.out.sam = &sam;
6700 status = STATUS_MORE_ENTRIES;
6701 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6702 status = dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1);
6704 if (!NT_STATUS_IS_OK(status) &&
6705 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6706 break;
6708 for (i=0; i<*q1.out.num_entries; i++) {
6709 add_string_to_array(tctx,
6710 sam->entries[i].name.string,
6711 &names, &num_names);
6715 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6717 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6719 q2.in.domain_handle = handle;
6720 q2.in.level = 5;
6721 q2.in.start_idx = 0;
6722 q2.in.max_entries = 5;
6723 q2.in.buf_size = (uint32_t)-1;
6724 q2.out.total_size = &total_size;
6725 q2.out.returned_size = &returned_size;
6726 q2.out.info = &info;
6728 status = STATUS_MORE_ENTRIES;
6729 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6730 status = dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2);
6732 if (!NT_STATUS_IS_OK(status) &&
6733 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6734 break;
6736 for (i=0; i<q2.out.info->info5.count; i++) {
6737 int j;
6738 const char *name = q2.out.info->info5.entries[i].account_name.string;
6739 bool found = false;
6740 for (j=0; j<num_names; j++) {
6741 if (names[j] == NULL)
6742 continue;
6743 if (strequal(names[j], name)) {
6744 names[j] = NULL;
6745 found = true;
6746 break;
6750 if (!found) {
6751 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
6752 name);
6753 ret = false;
6756 q2.in.start_idx += q2.out.info->info5.count;
6759 if (!NT_STATUS_IS_OK(status)) {
6760 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
6761 nt_errstr(status));
6762 ret = false;
6765 for (i=0; i<num_names; i++) {
6766 if (names[i] != NULL) {
6767 torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
6768 names[i]);
6769 ret = false;
6773 return ret;
6776 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
6777 struct torture_context *tctx,
6778 struct policy_handle *group_handle)
6780 struct samr_DeleteDomainGroup d;
6781 NTSTATUS status;
6783 torture_comment(tctx, "Testing DeleteDomainGroup\n");
6785 d.in.group_handle = group_handle;
6786 d.out.group_handle = group_handle;
6788 status = dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d);
6789 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
6791 return true;
6794 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
6795 struct torture_context *tctx,
6796 struct policy_handle *domain_handle)
6798 struct samr_TestPrivateFunctionsDomain r;
6799 NTSTATUS status;
6800 bool ret = true;
6802 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
6804 r.in.domain_handle = domain_handle;
6806 status = dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r);
6807 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
6809 return ret;
6812 static bool test_RidToSid(struct dcerpc_binding_handle *b,
6813 struct torture_context *tctx,
6814 struct dom_sid *domain_sid,
6815 struct policy_handle *domain_handle)
6817 struct samr_RidToSid r;
6818 NTSTATUS status;
6819 bool ret = true;
6820 struct dom_sid *calc_sid, *out_sid;
6821 int rids[] = { 0, 42, 512, 10200 };
6822 int i;
6824 for (i=0;i<ARRAY_SIZE(rids);i++) {
6825 torture_comment(tctx, "Testing RidToSid\n");
6827 calc_sid = dom_sid_dup(tctx, domain_sid);
6828 r.in.domain_handle = domain_handle;
6829 r.in.rid = rids[i];
6830 r.out.sid = &out_sid;
6832 status = dcerpc_samr_RidToSid_r(b, tctx, &r);
6833 if (!NT_STATUS_IS_OK(status)) {
6834 torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
6835 ret = false;
6836 } else {
6837 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
6839 if (!dom_sid_equal(calc_sid, out_sid)) {
6840 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
6841 dom_sid_string(tctx, out_sid),
6842 dom_sid_string(tctx, calc_sid));
6843 ret = false;
6848 return ret;
6851 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
6852 struct torture_context *tctx,
6853 struct policy_handle *domain_handle)
6855 struct samr_GetBootKeyInformation r;
6856 NTSTATUS status;
6857 bool ret = true;
6858 uint32_t unknown = 0;
6860 torture_comment(tctx, "Testing GetBootKeyInformation\n");
6862 r.in.domain_handle = domain_handle;
6863 r.out.unknown = &unknown;
6865 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
6866 if (!NT_STATUS_IS_OK(status)) {
6867 /* w2k3 seems to fail this sometimes and pass it sometimes */
6868 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
6871 return ret;
6874 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
6875 struct torture_context *tctx,
6876 struct policy_handle *domain_handle,
6877 struct policy_handle *group_handle)
6879 NTSTATUS status;
6880 struct samr_AddGroupMember r;
6881 struct samr_DeleteGroupMember d;
6882 struct samr_QueryGroupMember q;
6883 struct samr_RidTypeArray *rids = NULL;
6884 struct samr_SetMemberAttributesOfGroup s;
6885 uint32_t rid;
6886 bool found_member = false;
6887 int i;
6889 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
6890 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
6892 r.in.group_handle = group_handle;
6893 r.in.rid = rid;
6894 r.in.flags = 0; /* ??? */
6896 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
6898 d.in.group_handle = group_handle;
6899 d.in.rid = rid;
6901 status = dcerpc_samr_DeleteGroupMember_r(b, tctx, &d);
6902 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
6904 status = dcerpc_samr_AddGroupMember_r(b, tctx, &r);
6905 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6907 status = dcerpc_samr_AddGroupMember_r(b, tctx, &r);
6908 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
6910 if (torture_setting_bool(tctx, "samba4", false) ||
6911 torture_setting_bool(tctx, "samba3", false)) {
6912 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
6913 } else {
6914 /* this one is quite strange. I am using random inputs in the
6915 hope of triggering an error that might give us a clue */
6917 s.in.group_handle = group_handle;
6918 s.in.unknown1 = random();
6919 s.in.unknown2 = random();
6921 status = dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s);
6922 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
6925 q.in.group_handle = group_handle;
6926 q.out.rids = &rids;
6928 status = dcerpc_samr_QueryGroupMember_r(b, tctx, &q);
6929 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6930 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6932 for (i=0; i < rids->count; i++) {
6933 if (rids->rids[i] == rid) {
6934 found_member = true;
6938 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
6940 status = dcerpc_samr_DeleteGroupMember_r(b, tctx, &d);
6941 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
6943 rids = NULL;
6944 found_member = false;
6946 status = dcerpc_samr_QueryGroupMember_r(b, tctx, &q);
6947 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6948 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6950 for (i=0; i < rids->count; i++) {
6951 if (rids->rids[i] == rid) {
6952 found_member = true;
6956 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
6958 status = dcerpc_samr_AddGroupMember_r(b, tctx, &r);
6959 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6961 return true;
6965 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
6966 struct torture_context *tctx,
6967 struct policy_handle *domain_handle,
6968 const char *group_name,
6969 struct policy_handle *group_handle,
6970 struct dom_sid *domain_sid,
6971 bool test_group)
6973 NTSTATUS status;
6974 struct samr_CreateDomainGroup r;
6975 uint32_t rid;
6976 struct lsa_String name;
6977 bool ret = true;
6979 init_lsa_String(&name, group_name);
6981 r.in.domain_handle = domain_handle;
6982 r.in.name = &name;
6983 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6984 r.out.group_handle = group_handle;
6985 r.out.rid = &rid;
6987 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
6989 status = dcerpc_samr_CreateDomainGroup_r(b, tctx, &r);
6991 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6992 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6993 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
6994 return true;
6995 } else {
6996 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
6997 nt_errstr(status));
6998 return false;
7002 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
7003 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7004 torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7005 nt_errstr(status));
7006 return false;
7008 status = dcerpc_samr_CreateDomainGroup_r(b, tctx, &r);
7010 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
7011 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7013 torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7014 nt_errstr(status));
7015 return false;
7017 status = dcerpc_samr_CreateDomainGroup_r(b, tctx, &r);
7019 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
7021 if (!test_group) {
7022 return ret;
7025 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7026 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(status));
7027 ret = false;
7030 if (!test_SetGroupInfo(b, tctx, group_handle)) {
7031 ret = false;
7034 return ret;
7039 its not totally clear what this does. It seems to accept any sid you like.
7041 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7042 struct torture_context *tctx,
7043 struct policy_handle *domain_handle)
7045 NTSTATUS status;
7046 struct samr_RemoveMemberFromForeignDomain r;
7048 r.in.domain_handle = domain_handle;
7049 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7051 status = dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r);
7052 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
7054 return true;
7057 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7058 struct torture_context *tctx,
7059 struct policy_handle *domain_handle,
7060 uint32_t *total_num_entries_p)
7062 NTSTATUS status;
7063 struct samr_EnumDomainUsers r;
7064 uint32_t resume_handle = 0;
7065 uint32_t num_entries = 0;
7066 uint32_t total_num_entries = 0;
7067 struct samr_SamArray *sam;
7069 r.in.domain_handle = domain_handle;
7070 r.in.acct_flags = 0;
7071 r.in.max_size = (uint32_t)-1;
7072 r.in.resume_handle = &resume_handle;
7074 r.out.sam = &sam;
7075 r.out.num_entries = &num_entries;
7076 r.out.resume_handle = &resume_handle;
7078 torture_comment(tctx, "Testing EnumDomainUsers\n");
7080 do {
7081 status = dcerpc_samr_EnumDomainUsers_r(b, tctx, &r);
7082 if (NT_STATUS_IS_ERR(status)) {
7083 torture_assert_ntstatus_ok(tctx, status,
7084 "failed to enumerate users");
7087 total_num_entries += num_entries;
7088 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7090 if (total_num_entries_p) {
7091 *total_num_entries_p = total_num_entries;
7094 return true;
7097 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7098 struct torture_context *tctx,
7099 struct policy_handle *domain_handle,
7100 uint32_t *total_num_entries_p)
7102 NTSTATUS status;
7103 struct samr_EnumDomainGroups r;
7104 uint32_t resume_handle = 0;
7105 uint32_t num_entries = 0;
7106 uint32_t total_num_entries = 0;
7107 struct samr_SamArray *sam;
7109 r.in.domain_handle = domain_handle;
7110 r.in.max_size = (uint32_t)-1;
7111 r.in.resume_handle = &resume_handle;
7113 r.out.sam = &sam;
7114 r.out.num_entries = &num_entries;
7115 r.out.resume_handle = &resume_handle;
7117 torture_comment(tctx, "Testing EnumDomainGroups\n");
7119 do {
7120 status = dcerpc_samr_EnumDomainGroups_r(b, tctx, &r);
7121 if (NT_STATUS_IS_ERR(status)) {
7122 torture_assert_ntstatus_ok(tctx, status,
7123 "failed to enumerate groups");
7126 total_num_entries += num_entries;
7127 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7129 if (total_num_entries_p) {
7130 *total_num_entries_p = total_num_entries;
7133 return true;
7136 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7137 struct torture_context *tctx,
7138 struct policy_handle *domain_handle,
7139 uint32_t *total_num_entries_p)
7141 NTSTATUS status;
7142 struct samr_EnumDomainAliases r;
7143 uint32_t resume_handle = 0;
7144 uint32_t num_entries = 0;
7145 uint32_t total_num_entries = 0;
7146 struct samr_SamArray *sam;
7148 r.in.domain_handle = domain_handle;
7149 r.in.max_size = (uint32_t)-1;
7150 r.in.resume_handle = &resume_handle;
7152 r.out.sam = &sam;
7153 r.out.num_entries = &num_entries;
7154 r.out.resume_handle = &resume_handle;
7156 torture_comment(tctx, "Testing EnumDomainAliases\n");
7158 do {
7159 status = dcerpc_samr_EnumDomainAliases_r(b, tctx, &r);
7160 if (NT_STATUS_IS_ERR(status)) {
7161 torture_assert_ntstatus_ok(tctx, status,
7162 "failed to enumerate aliases");
7165 total_num_entries += num_entries;
7166 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7168 if (total_num_entries_p) {
7169 *total_num_entries_p = total_num_entries;
7172 return true;
7175 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7176 struct torture_context *tctx,
7177 struct policy_handle *handle,
7178 uint16_t level,
7179 uint32_t *total_num_entries_p)
7181 NTSTATUS status;
7182 struct samr_QueryDisplayInfo r;
7183 uint32_t total_num_entries = 0;
7185 r.in.domain_handle = handle;
7186 r.in.level = level;
7187 r.in.start_idx = 0;
7188 r.in.max_entries = (uint32_t)-1;
7189 r.in.buf_size = (uint32_t)-1;
7191 torture_comment(tctx, "Testing QueryDisplayInfo\n");
7193 do {
7194 uint32_t total_size;
7195 uint32_t returned_size;
7196 union samr_DispInfo info;
7198 r.out.total_size = &total_size;
7199 r.out.returned_size = &returned_size;
7200 r.out.info = &info;
7202 status = dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r);
7203 if (NT_STATUS_IS_ERR(status)) {
7204 torture_assert_ntstatus_ok(tctx, status,
7205 "failed to query displayinfo");
7208 if (*r.out.returned_size == 0) {
7209 break;
7212 switch (r.in.level) {
7213 case 1:
7214 total_num_entries += info.info1.count;
7215 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7216 break;
7217 case 2:
7218 total_num_entries += info.info2.count;
7219 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7220 break;
7221 case 3:
7222 total_num_entries += info.info3.count;
7223 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7224 break;
7225 case 4:
7226 total_num_entries += info.info4.count;
7227 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7228 break;
7229 case 5:
7230 total_num_entries += info.info5.count;
7231 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7232 break;
7233 default:
7234 return false;
7237 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7239 if (total_num_entries_p) {
7240 *total_num_entries_p = total_num_entries;
7243 return true;
7246 static bool test_ManyObjects(struct dcerpc_pipe *p,
7247 struct torture_context *tctx,
7248 struct policy_handle *domain_handle,
7249 struct dom_sid *domain_sid,
7250 struct torture_samr_context *ctx)
7252 uint32_t num_total = ctx->num_objects_large_dc;
7253 uint32_t num_enum = 0;
7254 uint32_t num_disp = 0;
7255 uint32_t num_created = 0;
7256 uint32_t num_anounced = 0;
7257 bool ret = true;
7258 NTSTATUS status;
7259 uint32_t i;
7260 struct dcerpc_binding_handle *b = p->binding_handle;
7262 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7264 /* query */
7267 struct samr_QueryDomainInfo2 r;
7268 union samr_DomainInfo *info;
7269 r.in.domain_handle = domain_handle;
7270 r.in.level = 2;
7271 r.out.info = &info;
7273 status = dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r);
7274 torture_assert_ntstatus_ok(tctx, status,
7275 "failed to query domain info");
7277 switch (ctx->choice) {
7278 case TORTURE_SAMR_MANY_ACCOUNTS:
7279 num_anounced = info->general.num_users;
7280 break;
7281 case TORTURE_SAMR_MANY_GROUPS:
7282 num_anounced = info->general.num_groups;
7283 break;
7284 case TORTURE_SAMR_MANY_ALIASES:
7285 num_anounced = info->general.num_aliases;
7286 break;
7287 default:
7288 return false;
7292 /* create */
7294 for (i=0; i < num_total; i++) {
7296 const char *name = NULL;
7298 switch (ctx->choice) {
7299 case TORTURE_SAMR_MANY_ACCOUNTS:
7300 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7301 ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
7302 break;
7303 case TORTURE_SAMR_MANY_GROUPS:
7304 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7305 ret &= test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false);
7306 break;
7307 case TORTURE_SAMR_MANY_ALIASES:
7308 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7309 ret &= test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false);
7310 break;
7311 default:
7312 return false;
7314 if (!policy_handle_empty(&handles[i])) {
7315 num_created++;
7319 /* enum */
7321 switch (ctx->choice) {
7322 case TORTURE_SAMR_MANY_ACCOUNTS:
7323 ret &= test_EnumDomainUsers(b, tctx, domain_handle, &num_enum);
7324 break;
7325 case TORTURE_SAMR_MANY_GROUPS:
7326 ret &= test_EnumDomainGroups(b, tctx, domain_handle, &num_enum);
7327 break;
7328 case TORTURE_SAMR_MANY_ALIASES:
7329 ret &= test_EnumDomainAliases(b, tctx, domain_handle, &num_enum);
7330 break;
7331 default:
7332 return false;
7335 /* dispinfo */
7337 switch (ctx->choice) {
7338 case TORTURE_SAMR_MANY_ACCOUNTS:
7339 ret &= test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp);
7340 break;
7341 case TORTURE_SAMR_MANY_GROUPS:
7342 ret &= test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp);
7343 break;
7344 case TORTURE_SAMR_MANY_ALIASES:
7345 /* no aliases in dispinfo */
7346 break;
7347 default:
7348 return false;
7351 /* close or delete */
7353 for (i=0; i < num_total; i++) {
7355 if (policy_handle_empty(&handles[i])) {
7356 continue;
7359 if (torture_setting_bool(tctx, "samba3", false)) {
7360 ret &= test_samr_handle_Close(b, tctx, &handles[i]);
7361 } else {
7362 switch (ctx->choice) {
7363 case TORTURE_SAMR_MANY_ACCOUNTS:
7364 ret &= test_DeleteUser(b, tctx, &handles[i]);
7365 break;
7366 case TORTURE_SAMR_MANY_GROUPS:
7367 ret &= test_DeleteDomainGroup(b, tctx, &handles[i]);
7368 break;
7369 case TORTURE_SAMR_MANY_ALIASES:
7370 ret &= test_DeleteAlias(b, tctx, &handles[i]);
7371 break;
7372 default:
7373 return false;
7378 talloc_free(handles);
7380 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7381 torture_comment(tctx,
7382 "unexpected number of results (%u) returned in enum call, expected %u\n",
7383 num_enum, num_anounced + num_created);
7385 torture_comment(tctx,
7386 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7387 num_disp, num_anounced + num_created);
7389 return ret;
7392 static bool test_Connect(struct dcerpc_binding_handle *b,
7393 struct torture_context *tctx,
7394 struct policy_handle *handle);
7396 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7397 struct torture_samr_context *ctx, struct dom_sid *sid)
7399 NTSTATUS status;
7400 struct samr_OpenDomain r;
7401 struct policy_handle domain_handle;
7402 struct policy_handle alias_handle;
7403 struct policy_handle user_handle;
7404 struct policy_handle group_handle;
7405 bool ret = true;
7406 struct dcerpc_binding_handle *b = p->binding_handle;
7408 ZERO_STRUCT(alias_handle);
7409 ZERO_STRUCT(user_handle);
7410 ZERO_STRUCT(group_handle);
7411 ZERO_STRUCT(domain_handle);
7413 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7415 r.in.connect_handle = &ctx->handle;
7416 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7417 r.in.sid = sid;
7418 r.out.domain_handle = &domain_handle;
7420 status = dcerpc_samr_OpenDomain_r(b, tctx, &r);
7421 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
7423 /* run the domain tests with the main handle closed - this tests
7424 the servers reference counting */
7425 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7427 switch (ctx->choice) {
7428 case TORTURE_SAMR_PASSWORDS:
7429 case TORTURE_SAMR_USER_PRIVILEGES:
7430 if (!torture_setting_bool(tctx, "samba3", false)) {
7431 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7433 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7434 if (!ret) {
7435 torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7437 break;
7438 case TORTURE_SAMR_USER_ATTRIBUTES:
7439 if (!torture_setting_bool(tctx, "samba3", false)) {
7440 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7442 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7443 /* This test needs 'complex' users to validate */
7444 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7445 if (!ret) {
7446 torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7448 break;
7449 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7450 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7451 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7452 if (!torture_setting_bool(tctx, "samba3", false)) {
7453 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7455 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7456 if (!ret) {
7457 torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7459 break;
7460 case TORTURE_SAMR_MANY_ACCOUNTS:
7461 case TORTURE_SAMR_MANY_GROUPS:
7462 case TORTURE_SAMR_MANY_ALIASES:
7463 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7464 if (!ret) {
7465 torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7467 break;
7468 case TORTURE_SAMR_OTHER:
7469 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7470 if (!ret) {
7471 torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7473 if (!torture_setting_bool(tctx, "samba3", false)) {
7474 ret &= test_QuerySecurity(b, tctx, &domain_handle);
7476 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7477 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7478 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7479 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7480 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7481 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7482 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7483 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7484 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7485 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7486 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7487 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7488 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7490 if (torture_setting_bool(tctx, "samba4", false)) {
7491 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7492 } else {
7493 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7494 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7496 ret &= test_GroupList(b, tctx, &domain_handle);
7497 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7498 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7499 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7500 if (!ret) {
7501 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7503 break;
7506 if (!policy_handle_empty(&user_handle) &&
7507 !test_DeleteUser(b, tctx, &user_handle)) {
7508 ret = false;
7511 if (!policy_handle_empty(&alias_handle) &&
7512 !test_DeleteAlias(b, tctx, &alias_handle)) {
7513 ret = false;
7516 if (!policy_handle_empty(&group_handle) &&
7517 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7518 ret = false;
7521 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7523 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7524 /* reconnect the main handle */
7526 if (!ret) {
7527 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7530 return ret;
7533 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7534 struct torture_samr_context *ctx, const char *domain)
7536 NTSTATUS status;
7537 struct samr_LookupDomain r;
7538 struct dom_sid2 *sid = NULL;
7539 struct lsa_String n1;
7540 struct lsa_String n2;
7541 bool ret = true;
7542 struct dcerpc_binding_handle *b = p->binding_handle;
7544 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7546 /* check for correct error codes */
7547 r.in.connect_handle = &ctx->handle;
7548 r.in.domain_name = &n2;
7549 r.out.sid = &sid;
7550 n2.string = NULL;
7552 status = dcerpc_samr_LookupDomain_r(b, tctx, &r);
7553 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7555 init_lsa_String(&n2, "xxNODOMAINxx");
7557 status = dcerpc_samr_LookupDomain_r(b, tctx, &r);
7558 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7560 r.in.connect_handle = &ctx->handle;
7562 init_lsa_String(&n1, domain);
7563 r.in.domain_name = &n1;
7565 status = dcerpc_samr_LookupDomain_r(b, tctx, &r);
7566 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
7568 if (!test_GetDomPwInfo(p, tctx, &n1)) {
7569 ret = false;
7572 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7573 ret = false;
7576 return ret;
7580 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7581 struct torture_samr_context *ctx)
7583 NTSTATUS status;
7584 struct samr_EnumDomains r;
7585 uint32_t resume_handle = 0;
7586 uint32_t num_entries = 0;
7587 struct samr_SamArray *sam = NULL;
7588 int i;
7589 bool ret = true;
7590 struct dcerpc_binding_handle *b = p->binding_handle;
7592 r.in.connect_handle = &ctx->handle;
7593 r.in.resume_handle = &resume_handle;
7594 r.in.buf_size = (uint32_t)-1;
7595 r.out.resume_handle = &resume_handle;
7596 r.out.num_entries = &num_entries;
7597 r.out.sam = &sam;
7599 status = dcerpc_samr_EnumDomains_r(b, tctx, &r);
7600 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
7602 if (!*r.out.sam) {
7603 return false;
7606 for (i=0;i<sam->count;i++) {
7607 if (!test_LookupDomain(p, tctx, ctx,
7608 sam->entries[i].name.string)) {
7609 ret = false;
7613 status = dcerpc_samr_EnumDomains_r(b, tctx, &r);
7614 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
7616 return ret;
7620 static bool test_Connect(struct dcerpc_binding_handle *b,
7621 struct torture_context *tctx,
7622 struct policy_handle *handle)
7624 NTSTATUS status;
7625 struct samr_Connect r;
7626 struct samr_Connect2 r2;
7627 struct samr_Connect3 r3;
7628 struct samr_Connect4 r4;
7629 struct samr_Connect5 r5;
7630 union samr_ConnectInfo info;
7631 struct policy_handle h;
7632 uint32_t level_out = 0;
7633 bool ret = true, got_handle = false;
7635 torture_comment(tctx, "testing samr_Connect\n");
7637 r.in.system_name = 0;
7638 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7639 r.out.connect_handle = &h;
7641 status = dcerpc_samr_Connect_r(b, tctx, &r);
7642 if (!NT_STATUS_IS_OK(status)) {
7643 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
7644 ret = false;
7645 } else {
7646 got_handle = true;
7647 *handle = h;
7650 torture_comment(tctx, "testing samr_Connect2\n");
7652 r2.in.system_name = NULL;
7653 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7654 r2.out.connect_handle = &h;
7656 status = dcerpc_samr_Connect2_r(b, tctx, &r2);
7657 if (!NT_STATUS_IS_OK(status)) {
7658 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
7659 ret = false;
7660 } else {
7661 if (got_handle) {
7662 test_samr_handle_Close(b, tctx, handle);
7664 got_handle = true;
7665 *handle = h;
7668 torture_comment(tctx, "testing samr_Connect3\n");
7670 r3.in.system_name = NULL;
7671 r3.in.unknown = 0;
7672 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7673 r3.out.connect_handle = &h;
7675 status = dcerpc_samr_Connect3_r(b, tctx, &r3);
7676 if (!NT_STATUS_IS_OK(status)) {
7677 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(status));
7678 ret = false;
7679 } else {
7680 if (got_handle) {
7681 test_samr_handle_Close(b, tctx, handle);
7683 got_handle = true;
7684 *handle = h;
7687 torture_comment(tctx, "testing samr_Connect4\n");
7689 r4.in.system_name = "";
7690 r4.in.client_version = 0;
7691 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7692 r4.out.connect_handle = &h;
7694 status = dcerpc_samr_Connect4_r(b, tctx, &r4);
7695 if (!NT_STATUS_IS_OK(status)) {
7696 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(status));
7697 ret = false;
7698 } else {
7699 if (got_handle) {
7700 test_samr_handle_Close(b, tctx, handle);
7702 got_handle = true;
7703 *handle = h;
7706 torture_comment(tctx, "testing samr_Connect5\n");
7708 info.info1.client_version = 0;
7709 info.info1.unknown2 = 0;
7711 r5.in.system_name = "";
7712 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7713 r5.in.level_in = 1;
7714 r5.out.level_out = &level_out;
7715 r5.in.info_in = &info;
7716 r5.out.info_out = &info;
7717 r5.out.connect_handle = &h;
7719 status = dcerpc_samr_Connect5_r(b, tctx, &r5);
7720 if (!NT_STATUS_IS_OK(status)) {
7721 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(status));
7722 ret = false;
7723 } else {
7724 if (got_handle) {
7725 test_samr_handle_Close(b, tctx, handle);
7727 got_handle = true;
7728 *handle = h;
7731 return ret;
7735 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
7736 struct torture_context *tctx)
7738 struct samr_ValidatePassword r;
7739 union samr_ValidatePasswordReq req;
7740 union samr_ValidatePasswordRep *repp = NULL;
7741 NTSTATUS status;
7742 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
7743 int i;
7744 struct dcerpc_binding_handle *b = p->binding_handle;
7746 torture_comment(tctx, "testing samr_ValidatePassword\n");
7748 ZERO_STRUCT(r);
7749 r.in.level = NetValidatePasswordReset;
7750 r.in.req = &req;
7751 r.out.rep = &repp;
7753 ZERO_STRUCT(req);
7754 req.req3.account.string = "non-existant-account-aklsdji";
7756 for (i=0; passwords[i]; i++) {
7757 req.req3.password.string = passwords[i];
7758 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
7759 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT) &&
7760 p->last_fault_code == DCERPC_FAULT_OP_RNG_ERROR) {
7761 torture_skip(tctx, "ValidatePassword not supported by server\n");
7763 torture_assert_ntstatus_ok(tctx, status, "samr_ValidatePassword");
7764 torture_comment(tctx, "Server %s password '%s' with code %i\n",
7765 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
7766 req.req3.password.string, repp->ctr3.status);
7769 return true;
7772 bool torture_rpc_samr(struct torture_context *torture)
7774 NTSTATUS status;
7775 struct dcerpc_pipe *p;
7776 bool ret = true;
7777 struct torture_samr_context *ctx;
7778 struct dcerpc_binding_handle *b;
7780 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7781 if (!NT_STATUS_IS_OK(status)) {
7782 return false;
7784 b = p->binding_handle;
7786 ctx = talloc_zero(torture, struct torture_samr_context);
7788 ctx->choice = TORTURE_SAMR_OTHER;
7790 ret &= test_Connect(b, torture, &ctx->handle);
7792 if (!torture_setting_bool(torture, "samba3", false)) {
7793 ret &= test_QuerySecurity(b, torture, &ctx->handle);
7796 ret &= test_EnumDomains(p, torture, ctx);
7798 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
7800 ret &= test_Shutdown(b, torture, &ctx->handle);
7802 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7804 return ret;
7808 bool torture_rpc_samr_users(struct torture_context *torture)
7810 NTSTATUS status;
7811 struct dcerpc_pipe *p;
7812 bool ret = true;
7813 struct torture_samr_context *ctx;
7814 struct dcerpc_binding_handle *b;
7816 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7817 if (!NT_STATUS_IS_OK(status)) {
7818 return false;
7820 b = p->binding_handle;
7822 ctx = talloc_zero(torture, struct torture_samr_context);
7824 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
7826 ret &= test_Connect(b, torture, &ctx->handle);
7828 if (!torture_setting_bool(torture, "samba3", false)) {
7829 ret &= test_QuerySecurity(b, torture, &ctx->handle);
7832 ret &= test_EnumDomains(p, torture, ctx);
7834 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
7836 ret &= test_Shutdown(b, torture, &ctx->handle);
7838 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7840 return ret;
7844 bool torture_rpc_samr_passwords(struct torture_context *torture)
7846 NTSTATUS status;
7847 struct dcerpc_pipe *p;
7848 bool ret = true;
7849 struct torture_samr_context *ctx;
7850 struct dcerpc_binding_handle *b;
7852 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7853 if (!NT_STATUS_IS_OK(status)) {
7854 return false;
7856 b = p->binding_handle;
7858 ctx = talloc_zero(torture, struct torture_samr_context);
7860 ctx->choice = TORTURE_SAMR_PASSWORDS;
7862 ret &= test_Connect(b, torture, &ctx->handle);
7864 ret &= test_EnumDomains(p, torture, ctx);
7866 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7868 ret &= test_samr_ValidatePassword(p, torture);
7870 return ret;
7873 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
7874 struct dcerpc_pipe *p2,
7875 struct cli_credentials *machine_credentials)
7877 NTSTATUS status;
7878 struct dcerpc_pipe *p;
7879 bool ret = true;
7880 struct torture_samr_context *ctx;
7881 struct dcerpc_binding_handle *b;
7883 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7884 if (!NT_STATUS_IS_OK(status)) {
7885 return false;
7887 b = p->binding_handle;
7889 ctx = talloc_zero(torture, struct torture_samr_context);
7891 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
7892 ctx->machine_credentials = machine_credentials;
7894 ret &= test_Connect(b, torture, &ctx->handle);
7896 ret &= test_EnumDomains(p, torture, ctx);
7898 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7900 return ret;
7903 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
7905 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
7906 struct torture_rpc_tcase *tcase;
7908 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7909 &ndr_table_samr,
7910 TEST_ACCOUNT_NAME_PWD);
7912 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
7913 torture_rpc_samr_pwdlastset);
7915 return suite;
7918 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
7919 struct dcerpc_pipe *p2,
7920 struct cli_credentials *machine_credentials)
7922 NTSTATUS status;
7923 struct dcerpc_pipe *p;
7924 bool ret = true;
7925 struct torture_samr_context *ctx;
7926 struct dcerpc_binding_handle *b;
7928 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7929 if (!NT_STATUS_IS_OK(status)) {
7930 return false;
7932 b = p->binding_handle;
7934 ctx = talloc_zero(torture, struct torture_samr_context);
7936 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
7937 ctx->machine_credentials = machine_credentials;
7939 ret &= test_Connect(b, torture, &ctx->handle);
7941 ret &= test_EnumDomains(p, torture, ctx);
7943 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7945 return ret;
7948 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
7950 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
7951 struct torture_rpc_tcase *tcase;
7953 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7954 &ndr_table_samr,
7955 TEST_ACCOUNT_NAME_PWD);
7957 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
7958 torture_rpc_samr_users_privileges_delete_user);
7960 return suite;
7963 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
7964 struct dcerpc_pipe *p2,
7965 void *data)
7967 NTSTATUS status;
7968 struct dcerpc_pipe *p;
7969 bool ret = true;
7970 struct torture_samr_context *ctx =
7971 talloc_get_type_abort(data, struct torture_samr_context);
7972 struct dcerpc_binding_handle *b;
7974 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7975 if (!NT_STATUS_IS_OK(status)) {
7976 return false;
7978 b = p->binding_handle;
7980 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
7981 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7982 ctx->num_objects_large_dc);
7984 ret &= test_Connect(b, torture, &ctx->handle);
7986 ret &= test_EnumDomains(p, torture, ctx);
7988 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7990 return ret;
7993 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
7994 struct dcerpc_pipe *p2,
7995 void *data)
7997 NTSTATUS status;
7998 struct dcerpc_pipe *p;
7999 bool ret = true;
8000 struct torture_samr_context *ctx =
8001 talloc_get_type_abort(data, struct torture_samr_context);
8002 struct dcerpc_binding_handle *b;
8004 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8005 if (!NT_STATUS_IS_OK(status)) {
8006 return false;
8008 b = p->binding_handle;
8010 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8011 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8012 ctx->num_objects_large_dc);
8014 ret &= test_Connect(b, torture, &ctx->handle);
8016 ret &= test_EnumDomains(p, torture, ctx);
8018 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8020 return ret;
8023 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8024 struct dcerpc_pipe *p2,
8025 void *data)
8027 NTSTATUS status;
8028 struct dcerpc_pipe *p;
8029 bool ret = true;
8030 struct torture_samr_context *ctx =
8031 talloc_get_type_abort(data, struct torture_samr_context);
8032 struct dcerpc_binding_handle *b;
8034 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8035 if (!NT_STATUS_IS_OK(status)) {
8036 return false;
8038 b = p->binding_handle;
8040 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8041 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8042 ctx->num_objects_large_dc);
8044 ret &= test_Connect(b, torture, &ctx->handle);
8046 ret &= test_EnumDomains(p, torture, ctx);
8048 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8050 return ret;
8053 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8055 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
8056 struct torture_rpc_tcase *tcase;
8057 struct torture_samr_context *ctx;
8059 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8061 ctx = talloc_zero(suite, struct torture_samr_context);
8062 ctx->num_objects_large_dc = 150;
8064 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8065 torture_rpc_samr_many_aliases, ctx);
8066 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8067 torture_rpc_samr_many_groups, ctx);
8068 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8069 torture_rpc_samr_many_accounts, ctx);
8071 return suite;
8074 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8075 struct dcerpc_pipe *p2,
8076 struct cli_credentials *machine_credentials)
8078 NTSTATUS status;
8079 struct dcerpc_pipe *p;
8080 bool ret = true;
8081 struct torture_samr_context *ctx;
8082 struct dcerpc_binding_handle *b;
8084 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8085 if (!NT_STATUS_IS_OK(status)) {
8086 return false;
8088 b = p->binding_handle;
8090 ctx = talloc_zero(torture, struct torture_samr_context);
8092 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8093 ctx->machine_credentials = machine_credentials;
8095 ret &= test_Connect(b, torture, &ctx->handle);
8097 ret &= test_EnumDomains(p, torture, ctx);
8099 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8101 return ret;
8104 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8106 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-BADPWDCOUNT");
8107 struct torture_rpc_tcase *tcase;
8109 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8110 &ndr_table_samr,
8111 TEST_ACCOUNT_NAME_PWD);
8113 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8114 torture_rpc_samr_badpwdcount);
8116 return suite;
8119 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8120 struct dcerpc_pipe *p2,
8121 struct cli_credentials *machine_credentials)
8123 NTSTATUS status;
8124 struct dcerpc_pipe *p;
8125 bool ret = true;
8126 struct torture_samr_context *ctx;
8127 struct dcerpc_binding_handle *b;
8129 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8130 if (!NT_STATUS_IS_OK(status)) {
8131 return false;
8133 b = p->binding_handle;
8135 ctx = talloc_zero(torture, struct torture_samr_context);
8137 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8138 ctx->machine_credentials = machine_credentials;
8140 ret &= test_Connect(b, torture, &ctx->handle);
8142 ret &= test_EnumDomains(p, torture, ctx);
8144 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8146 return ret;
8149 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8151 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-LOCKOUT");
8152 struct torture_rpc_tcase *tcase;
8154 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8155 &ndr_table_samr,
8156 TEST_ACCOUNT_NAME_PWD);
8158 torture_rpc_tcase_add_test_creds(tcase, "lockout",
8159 torture_rpc_samr_lockout);
8161 return suite;