ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / rpc / samr.c
blob981196a81239752c60086352b5d022a53992635a
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for samr rpc operations
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7 Copyright (C) Jelmer Vernooij 2005-2007
8 Copyright (C) Guenther Deschner 2008-2010
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include <tevent.h>
27 #include "system/time.h"
28 #include "system/network.h"
29 #include "librpc/gen_ndr/lsa.h"
30 #include "librpc/gen_ndr/ndr_netlogon.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
33 #include "librpc/gen_ndr/ndr_lsa_c.h"
34 #include "lib/crypto/crypto.h"
35 #include "libcli/auth/libcli_auth.h"
36 #include "libcli/security/security.h"
37 #include "torture/rpc/torture_rpc.h"
38 #include "param/param.h"
39 #include "auth/gensec/gensec.h"
40 #include "auth/gensec/gensec_proto.h"
41 #include "../libcli/auth/schannel.h"
42 #include "torture/util.h"
43 #include "source4/librpc/rpc/dcerpc.h"
44 #include "librpc/rpc/dcerpc_samr.h"
45 #include "source3/rpc_client/init_samr.h"
46 #include "lib/crypto/gnutls_helpers.h"
48 #undef strcasecmp
50 #define TEST_ACCOUNT_NAME "samrtorturetest"
51 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
52 #define TEST_ALIASNAME "samrtorturetestalias"
53 #define TEST_GROUPNAME "samrtorturetestgroup"
54 #define TEST_MACHINENAME "samrtestmach$"
55 #define TEST_DOMAINNAME "samrtestdom$"
57 #include <gnutls/gnutls.h>
58 #include <gnutls/crypto.h>
60 enum torture_samr_choice {
61 TORTURE_SAMR_PASSWORDS,
62 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
63 TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
64 TORTURE_SAMR_PASSWORDS_LOCKOUT,
65 TORTURE_SAMR_USER_ATTRIBUTES,
66 TORTURE_SAMR_USER_PRIVILEGES,
67 TORTURE_SAMR_OTHER,
68 TORTURE_SAMR_MANY_ACCOUNTS,
69 TORTURE_SAMR_MANY_GROUPS,
70 TORTURE_SAMR_MANY_ALIASES
73 struct torture_samr_context {
74 struct policy_handle handle;
75 struct cli_credentials *machine_credentials;
76 enum torture_samr_choice choice;
77 uint32_t num_objects_large_dc;
80 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
81 struct torture_context *tctx,
82 struct policy_handle *handle);
84 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
85 struct torture_context *tctx,
86 struct policy_handle *handle);
88 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
89 struct torture_context *tctx,
90 struct policy_handle *handle);
92 static bool test_ChangePassword(struct dcerpc_pipe *p,
93 struct torture_context *tctx,
94 const char *acct_name,
95 struct policy_handle *domain_handle, char **password);
97 static void init_lsa_String(struct lsa_String *string, const char *s)
99 string->string = s;
102 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
104 string->string = s;
107 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
109 string->length = length;
110 string->size = length;
111 string->array = (uint16_t *)discard_const(s);
114 bool test_samr_handle_Close(struct dcerpc_binding_handle *b,
115 struct torture_context *tctx,
116 struct policy_handle *handle)
118 struct samr_Close r;
120 r.in.handle = handle;
121 r.out.handle = handle;
123 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Close_r(b, tctx, &r),
124 "Close failed");
125 torture_assert_ntstatus_ok(tctx, r.out.result, "Close failed");
127 return true;
130 static bool test_Shutdown(struct dcerpc_binding_handle *b,
131 struct torture_context *tctx,
132 struct policy_handle *handle)
134 struct samr_Shutdown r;
136 if (!torture_setting_bool(tctx, "dangerous", false)) {
137 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
138 return true;
141 r.in.connect_handle = handle;
143 torture_comment(tctx, "Testing samr_Shutdown\n");
145 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Shutdown_r(b, tctx, &r),
146 "Shutdown failed");
147 torture_assert_ntstatus_ok(tctx, r.out.result, "Shutdown failed");
149 return true;
152 static bool test_SetDsrmPassword(struct dcerpc_binding_handle *b,
153 struct torture_context *tctx,
154 struct policy_handle *handle)
156 struct samr_SetDsrmPassword r;
157 struct lsa_String string;
158 struct samr_Password hash;
160 if (!torture_setting_bool(tctx, "dangerous", false)) {
161 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
164 E_md4hash("TeSTDSRM123", hash.hash);
166 init_lsa_String(&string, "Administrator");
168 r.in.name = &string;
169 r.in.unknown = 0;
170 r.in.hash = &hash;
172 torture_comment(tctx, "Testing samr_SetDsrmPassword\n");
174 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDsrmPassword_r(b, tctx, &r),
175 "SetDsrmPassword failed");
176 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_SUPPORTED, "SetDsrmPassword failed");
178 return true;
182 static bool test_QuerySecurity(struct dcerpc_binding_handle *b,
183 struct torture_context *tctx,
184 struct policy_handle *handle)
186 struct samr_QuerySecurity r;
187 struct samr_SetSecurity s;
188 struct sec_desc_buf *sdbuf = NULL;
190 r.in.handle = handle;
191 r.in.sec_info = 7;
192 r.out.sdbuf = &sdbuf;
194 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
195 "QuerySecurity failed");
196 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
198 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
200 s.in.handle = handle;
201 s.in.sec_info = 7;
202 s.in.sdbuf = sdbuf;
204 if (torture_setting_bool(tctx, "samba4", false)) {
205 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
208 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetSecurity_r(b, tctx, &s),
209 "SetSecurity failed");
210 torture_assert_ntstatus_ok(tctx, r.out.result, "SetSecurity failed");
212 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
213 "QuerySecurity failed");
214 torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
216 return true;
220 static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_context *tctx,
221 struct policy_handle *handle, uint32_t base_acct_flags,
222 const char *base_account_name)
224 struct samr_SetUserInfo s;
225 struct samr_SetUserInfo2 s2;
226 struct samr_QueryUserInfo q;
227 struct samr_QueryUserInfo q0;
228 union samr_UserInfo u;
229 union samr_UserInfo *info;
230 bool ret = true;
231 const char *test_account_name;
233 uint32_t user_extra_flags = 0;
235 if (!torture_setting_bool(tctx, "samba3", false)) {
236 if (base_acct_flags == ACB_NORMAL) {
237 /* When created, accounts are expired by default */
238 user_extra_flags = ACB_PW_EXPIRED;
242 s.in.user_handle = handle;
243 s.in.info = &u;
245 s2.in.user_handle = handle;
246 s2.in.info = &u;
248 q.in.user_handle = handle;
249 q.out.info = &info;
250 q0 = q;
252 #define TESTCALL(call, r) \
253 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ ##call## _r(b, tctx, &r),\
254 #call " failed"); \
255 if (!NT_STATUS_IS_OK(r.out.result)) { \
256 torture_result(tctx, TORTURE_FAIL, #call " level %u failed - %s (%s)\n", \
257 r.in.level, nt_errstr(r.out.result), __location__); \
258 ret = false; \
259 break; \
262 #define STRING_EQUAL(s1, s2, field) \
263 torture_assert_str_equal(tctx, s1, s2, "Failed to set " #field)
265 #define MEM_EQUAL(s1, s2, length, field) \
266 torture_assert_mem_equal(tctx, s1, s2, length, "Failed to set " #field)
268 #define INT_EQUAL(i1, i2, field) \
269 torture_assert_int_equal(tctx, i1, i2, "Failed to set " #field)
271 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
272 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
273 q.in.level = lvl1; \
274 TESTCALL(QueryUserInfo, q) \
275 s.in.level = lvl1; \
276 s2.in.level = lvl1; \
277 u = *info; \
278 if (lvl1 == 21) { \
279 ZERO_STRUCT(u.info21); \
280 u.info21.fields_present = fpval; \
282 init_lsa_String(&u.info ## lvl1.field1, value); \
283 TESTCALL(SetUserInfo, s) \
284 TESTCALL(SetUserInfo2, s2) \
285 init_lsa_String(&u.info ## lvl1.field1, ""); \
286 TESTCALL(QueryUserInfo, q); \
287 u = *info; \
288 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
289 q.in.level = lvl2; \
290 TESTCALL(QueryUserInfo, q) \
291 u = *info; \
292 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
293 } while (0)
295 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
296 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
297 q.in.level = lvl1; \
298 TESTCALL(QueryUserInfo, q) \
299 s.in.level = lvl1; \
300 s2.in.level = lvl1; \
301 u = *info; \
302 if (lvl1 == 21) { \
303 ZERO_STRUCT(u.info21); \
304 u.info21.fields_present = fpval; \
306 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
307 TESTCALL(SetUserInfo, s) \
308 TESTCALL(SetUserInfo2, s2) \
309 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
310 TESTCALL(QueryUserInfo, q); \
311 u = *info; \
312 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
313 q.in.level = lvl2; \
314 TESTCALL(QueryUserInfo, q) \
315 u = *info; \
316 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
317 } while (0)
319 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
320 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
321 q.in.level = lvl1; \
322 TESTCALL(QueryUserInfo, q) \
323 s.in.level = lvl1; \
324 s2.in.level = lvl1; \
325 u = *info; \
326 if (lvl1 == 21) { \
327 uint8_t *bits = u.info21.logon_hours.bits; \
328 ZERO_STRUCT(u.info21); \
329 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
330 u.info21.logon_hours.units_per_week = 168; \
331 u.info21.logon_hours.bits = bits; \
333 u.info21.fields_present = fpval; \
335 u.info ## lvl1.field1 = value; \
336 TESTCALL(SetUserInfo, s) \
337 TESTCALL(SetUserInfo2, s2) \
338 u.info ## lvl1.field1 = 0; \
339 TESTCALL(QueryUserInfo, q); \
340 u = *info; \
341 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
342 q.in.level = lvl2; \
343 TESTCALL(QueryUserInfo, q) \
344 u = *info; \
345 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
346 } while (0)
348 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
349 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
350 } while (0)
352 q0.in.level = 12;
353 do { TESTCALL(QueryUserInfo, q0) } while (0);
355 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
356 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
357 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
358 SAMR_FIELD_COMMENT);
360 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
361 TEST_USERINFO_STRING(7, account_name, 1, account_name, test_account_name, 0);
362 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
363 TEST_USERINFO_STRING(7, account_name, 3, account_name, test_account_name, 0);
364 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
365 TEST_USERINFO_STRING(7, account_name, 5, account_name, test_account_name, 0);
366 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
367 TEST_USERINFO_STRING(7, account_name, 6, account_name, test_account_name, 0);
368 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
369 TEST_USERINFO_STRING(7, account_name, 7, account_name, test_account_name, 0);
370 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
371 TEST_USERINFO_STRING(7, account_name, 21, account_name, test_account_name, 0);
372 test_account_name = base_account_name;
373 TEST_USERINFO_STRING(21, account_name, 21, account_name, test_account_name,
374 SAMR_FIELD_ACCOUNT_NAME);
376 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
377 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
378 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
379 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
380 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
381 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
382 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
383 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
384 SAMR_FIELD_FULL_NAME);
386 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
387 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
388 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
389 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
390 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
391 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
392 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
393 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
394 SAMR_FIELD_FULL_NAME);
396 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
397 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
398 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
399 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
400 SAMR_FIELD_LOGON_SCRIPT);
402 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
403 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
404 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
405 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
406 SAMR_FIELD_PROFILE_PATH);
408 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
409 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
410 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
411 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
412 SAMR_FIELD_HOME_DIRECTORY);
413 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
414 SAMR_FIELD_HOME_DIRECTORY);
416 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
417 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
418 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
419 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
420 SAMR_FIELD_HOME_DRIVE);
421 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
422 SAMR_FIELD_HOME_DRIVE);
424 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
425 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
426 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
427 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
428 SAMR_FIELD_DESCRIPTION);
430 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
431 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
432 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
433 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
434 SAMR_FIELD_WORKSTATIONS);
435 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
436 SAMR_FIELD_WORKSTATIONS);
437 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
438 SAMR_FIELD_WORKSTATIONS);
439 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
440 SAMR_FIELD_WORKSTATIONS);
442 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
443 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
444 SAMR_FIELD_PARAMETERS);
445 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
446 SAMR_FIELD_PARAMETERS);
447 /* also empty user parameters are allowed */
448 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
449 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
450 SAMR_FIELD_PARAMETERS);
451 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
452 SAMR_FIELD_PARAMETERS);
454 /* Samba 3 cannot store country_code and code_page atm. - gd */
455 if (!torture_setting_bool(tctx, "samba3", false)) {
456 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
457 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
458 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
459 SAMR_FIELD_COUNTRY_CODE);
460 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
461 SAMR_FIELD_COUNTRY_CODE);
463 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
464 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
465 SAMR_FIELD_CODE_PAGE);
466 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
467 SAMR_FIELD_CODE_PAGE);
470 if (!torture_setting_bool(tctx, "samba3", false)) {
471 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
472 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
473 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
474 SAMR_FIELD_ACCT_EXPIRY);
475 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
476 SAMR_FIELD_ACCT_EXPIRY);
477 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
478 SAMR_FIELD_ACCT_EXPIRY);
479 } else {
480 /* Samba 3 can only store seconds / time_t in passdb - gd */
481 NTTIME nt;
482 unix_to_nt_time(&nt, time(NULL) + __LINE__);
483 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
484 unix_to_nt_time(&nt, time(NULL) + __LINE__);
485 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
486 unix_to_nt_time(&nt, time(NULL) + __LINE__);
487 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
488 unix_to_nt_time(&nt, time(NULL) + __LINE__);
489 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
490 unix_to_nt_time(&nt, time(NULL) + __LINE__);
491 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
494 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
495 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
496 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
497 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
498 SAMR_FIELD_LOGON_HOURS);
500 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
501 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
502 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
504 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
505 (base_acct_flags | ACB_DISABLED),
506 (base_acct_flags | ACB_DISABLED | user_extra_flags),
509 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
510 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
511 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
512 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
514 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
515 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
516 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
520 /* The 'autolock' flag doesn't stick - check this */
521 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
522 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
523 (base_acct_flags | ACB_DISABLED | user_extra_flags),
525 #if 0
526 /* Removing the 'disabled' flag doesn't stick - check this */
527 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
528 (base_acct_flags),
529 (base_acct_flags | ACB_DISABLED | user_extra_flags),
531 #endif
533 /* Samba3 cannot store these atm */
534 if (!torture_setting_bool(tctx, "samba3", false)) {
535 /* The 'store plaintext' flag does stick */
536 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
537 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
538 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
540 /* The 'use DES' flag does stick */
541 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
542 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
543 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
545 /* The 'don't require kerberos pre-authentication flag does stick */
546 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
547 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
548 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
550 /* The 'no kerberos PAC required' flag sticks */
551 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
552 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
553 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
556 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
557 (base_acct_flags | ACB_DISABLED),
558 (base_acct_flags | ACB_DISABLED | user_extra_flags),
559 SAMR_FIELD_ACCT_FLAGS);
561 #if 0
562 /* these fail with win2003 - it appears you can't set the primary gid?
563 the set succeeds, but the gid isn't changed. Very weird! */
564 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
565 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
566 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
567 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
568 #endif
570 return ret;
574 generate a random password for password change tests
576 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
578 size_t len = MAX(8, min_len);
579 char *s = generate_random_password(mem_ctx, len, len+6);
580 return s;
583 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
585 char *s = samr_rand_pass_silent(mem_ctx, min_len);
586 printf("Generated password '%s'\n", s);
587 return s;
592 generate a random password for password change tests
594 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
596 int i;
597 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
598 generate_random_buffer(password.data, password.length);
600 for (i=0; i < len; i++) {
601 if (((uint16_t *)password.data)[i] == 0) {
602 ((uint16_t *)password.data)[i] = 1;
606 return password;
610 generate a random password for password change tests (fixed length)
612 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
614 char *s = generate_random_password(mem_ctx, len, len);
615 printf("Generated password '%s'\n", s);
616 return s;
619 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
620 struct policy_handle *handle, char **password)
622 NTSTATUS status;
623 struct samr_SetUserInfo s;
624 union samr_UserInfo u;
625 bool ret = true;
626 DATA_BLOB session_key;
627 char *newpass;
628 struct dcerpc_binding_handle *b = p->binding_handle;
629 struct samr_GetUserPwInfo pwp;
630 struct samr_PwInfo info;
631 int policy_min_pw_len = 0;
632 pwp.in.user_handle = handle;
633 pwp.out.info = &info;
635 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
636 "GetUserPwInfo failed");
637 if (NT_STATUS_IS_OK(pwp.out.result)) {
638 policy_min_pw_len = pwp.out.info->min_password_length;
640 newpass = samr_rand_pass(tctx, policy_min_pw_len);
642 s.in.user_handle = handle;
643 s.in.info = &u;
644 s.in.level = 24;
646 u.info24.password_expired = 0;
648 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
649 if (!NT_STATUS_IS_OK(status)) {
650 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
651 s.in.level, nt_errstr(status));
652 return false;
655 status = init_samr_CryptPassword(newpass,
656 &session_key,
657 &u.info24.password);
658 torture_assert_ntstatus_ok(tctx,
659 status,
660 "init_samr_CryptPassword failed");
662 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
664 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
665 "SetUserInfo failed");
666 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
667 __location__, __FUNCTION__,
668 newpass, nt_errstr(s.out.result));
669 if (!NT_STATUS_IS_OK(s.out.result)) {
670 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
671 s.in.level, nt_errstr(s.out.result));
672 ret = false;
673 } else {
674 *password = newpass;
677 return ret;
681 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
682 struct policy_handle *handle, uint32_t fields_present,
683 char **password)
685 NTSTATUS status;
686 struct samr_SetUserInfo s;
687 union samr_UserInfo u;
688 bool ret = true;
689 DATA_BLOB session_key;
690 struct dcerpc_binding_handle *b = p->binding_handle;
691 char *newpass;
692 struct samr_GetUserPwInfo pwp;
693 struct samr_PwInfo info;
694 int policy_min_pw_len = 0;
695 pwp.in.user_handle = handle;
696 pwp.out.info = &info;
698 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
699 "GetUserPwInfo failed");
700 if (NT_STATUS_IS_OK(pwp.out.result)) {
701 policy_min_pw_len = pwp.out.info->min_password_length;
703 newpass = samr_rand_pass(tctx, policy_min_pw_len);
705 s.in.user_handle = handle;
706 s.in.info = &u;
707 s.in.level = 23;
709 ZERO_STRUCT(u);
711 u.info23.info.fields_present = fields_present;
713 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
714 if (!NT_STATUS_IS_OK(status)) {
715 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
716 s.in.level, nt_errstr(status));
717 return false;
720 status = init_samr_CryptPassword(newpass,
721 &session_key,
722 &u.info23.password);
723 torture_assert_ntstatus_ok(tctx,
724 status,
725 "init_samr_CryptPassword failed");
727 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
729 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
730 "SetUserInfo failed");
731 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
732 __location__, __FUNCTION__,
733 newpass, nt_errstr(s.out.result));
734 if (!NT_STATUS_IS_OK(s.out.result)) {
735 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
736 s.in.level, nt_errstr(s.out.result));
737 ret = false;
738 } else {
739 *password = newpass;
742 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
743 if (!NT_STATUS_IS_OK(status)) {
744 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
745 s.in.level, nt_errstr(status));
746 return false;
749 /* This should break the key nicely */
750 session_key.data[0]++;
752 status = init_samr_CryptPassword(newpass,
753 &session_key,
754 &u.info23.password);
755 torture_assert_ntstatus_ok(tctx,
756 status,
757 "init_samr_CryptPassword failed");
759 /* Reset the session key */
760 session_key.data[0]--;
762 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
764 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
765 "SetUserInfo failed");
766 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
767 __location__, __FUNCTION__,
768 newpass, nt_errstr(s.out.result));
769 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
770 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
771 s.in.level, nt_errstr(s.out.result));
772 ret = false;
775 return ret;
778 static bool test_SetUserPass_32(struct dcerpc_pipe *p, struct torture_context *tctx,
779 struct policy_handle *handle, uint32_t fields_present,
780 char **password)
782 NTSTATUS status;
783 struct samr_SetUserInfo s;
784 union samr_UserInfo u;
785 DATA_BLOB session_key;
786 uint8_t salt_data[16];
787 DATA_BLOB salt = {
788 .data = salt_data,
789 .length = sizeof(salt_data),
791 char *newpass = NULL;
792 struct dcerpc_binding_handle *b = p->binding_handle;
793 struct samr_GetUserPwInfo pwp;
794 struct samr_PwInfo info;
795 int policy_min_pw_len = 0;
796 bool ret = true;
798 pwp.in.user_handle = handle;
799 pwp.out.info = &info;
801 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
802 "GetUserPwInfo failed");
803 if (NT_STATUS_IS_OK(pwp.out.result)) {
804 policy_min_pw_len = pwp.out.info->min_password_length;
806 newpass = samr_rand_pass(tctx, policy_min_pw_len);
808 s.in.user_handle = handle;
809 s.in.info = &u;
810 s.in.level = 32;
812 ZERO_STRUCT(u);
814 u.info32.info.fields_present = fields_present;
816 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
817 if (!NT_STATUS_IS_OK(status)) {
818 torture_result(tctx,
819 TORTURE_FAIL,
820 "SetUserInfo level %u - no session key - %s\n",
821 s.in.level,
822 nt_errstr(status));
823 return false;
826 generate_nonce_buffer(salt.data, salt.length);
828 status = init_samr_CryptPasswordAES(tctx,
829 newpass,
830 &salt,
831 &session_key,
832 &u.info32.password);
833 torture_assert_ntstatus_ok(tctx,
834 status,
835 "init_samr_CryptPasswordAES failed");
837 torture_comment(tctx,
838 "Testing SetUserInfo level 32 (set password aes)\n");
840 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
841 torture_assert_ntstatus_ok(tctx, status, "SetUserInfo failed");
842 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
843 __location__,
844 __FUNCTION__,
845 newpass,
846 nt_errstr(s.out.result));
847 if (!NT_STATUS_IS_OK(s.out.result)) {
848 torture_result(tctx,
849 TORTURE_FAIL,
850 "SetUserInfo level %u failed - %s\n",
851 s.in.level,
852 nt_errstr(s.out.result));
853 ret = false;
854 } else {
855 *password = newpass;
858 /* This should break the key nicely */
859 session_key.data[0]++;
861 status = init_samr_CryptPasswordAES(tctx,
862 newpass,
863 &salt,
864 &session_key,
865 &u.info32.password);
866 torture_assert_ntstatus_ok(tctx,
867 status,
868 "init_samr_CryptPasswordEx failed");
870 /* Reset the key */
871 session_key.data[0]--;
873 torture_comment(tctx,
874 "Testing SetUserInfo level 32 (set password aes) with "
875 "wrong session key\n");
877 status = dcerpc_samr_SetUserInfo_r(b, tctx, &s);
878 torture_assert_ntstatus_ok(tctx, status, "SetUserInfo failed");
879 torture_comment(tctx,
880 "(%s:%s) new_password[%s] status[%s]\n",
881 __location__,
882 __FUNCTION__,
883 newpass,
884 nt_errstr(s.out.result));
885 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
886 torture_result(tctx,
887 TORTURE_FAIL,
888 "SetUserInfo level %u should have failed with "
889 "WRONG_PASSWORD- %s\n",
890 s.in.level,
891 nt_errstr(s.out.result));
892 ret = false;
895 return ret;
899 static bool test_SetUserPass_31(struct dcerpc_pipe *p, struct torture_context *tctx,
900 struct policy_handle *handle, bool makeshort,
901 char **password)
903 NTSTATUS status;
904 struct samr_SetUserInfo s;
905 union samr_UserInfo u;
906 bool ret = true;
907 DATA_BLOB session_key;
908 uint8_t salt_data[16];
909 DATA_BLOB salt = {
910 .data = salt_data,
911 .length = sizeof(salt_data),
913 char *newpass;
914 struct dcerpc_binding_handle *b = p->binding_handle;
915 struct samr_GetUserPwInfo pwp;
916 struct samr_PwInfo info;
917 int policy_min_pw_len = 0;
919 pwp.in.user_handle = handle;
920 pwp.out.info = &info;
922 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
923 "GetUserPwInfo failed");
924 if (NT_STATUS_IS_OK(pwp.out.result)) {
925 policy_min_pw_len = pwp.out.info->min_password_length;
927 if (makeshort && policy_min_pw_len) {
928 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
929 } else {
930 newpass = samr_rand_pass(tctx, policy_min_pw_len);
933 s.in.user_handle = handle;
934 s.in.info = &u;
935 s.in.level = 31;
937 ZERO_STRUCT(u);
939 u.info31.password_expired = 0;
941 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
942 if (!NT_STATUS_IS_OK(status)) {
943 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
944 s.in.level, nt_errstr(status));
945 return false;
948 generate_nonce_buffer(salt.data, salt.length);
950 status = init_samr_CryptPasswordAES(tctx,
951 newpass,
952 &salt,
953 &session_key,
954 &u.info31.password);
955 torture_assert_ntstatus_ok(tctx,
956 status,
957 "init_samr_CryptPasswordEx failed");
959 torture_comment(tctx, "Testing SetUserInfo level 31 (set password aes)\n");
961 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
962 "SetUserInfo failed");
963 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
964 __location__, __FUNCTION__,
965 newpass, nt_errstr(s.out.result));
966 if (!NT_STATUS_IS_OK(s.out.result)) {
967 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
968 s.in.level, nt_errstr(s.out.result));
969 ret = false;
970 } else {
971 *password = newpass;
974 /* This should break the key nicely */
975 session_key.data[0]++;
977 status = init_samr_CryptPasswordAES(tctx,
978 newpass,
979 &salt,
980 &session_key,
981 &u.info31.password);
982 torture_assert_ntstatus_ok(tctx,
983 status,
984 "init_samr_CryptPasswordEx failed");
986 /* Reset the key */
987 session_key.data[0]--;
989 torture_comment(tctx, "Testing SetUserInfo level 31 (set password aes) with wrong session key\n");
991 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
992 "SetUserInfo failed");
993 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
994 __location__, __FUNCTION__,
995 newpass, nt_errstr(s.out.result));
996 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
997 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
998 s.in.level, nt_errstr(s.out.result));
999 ret = false;
1000 } else {
1001 *password = newpass;
1004 return ret;
1008 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
1009 struct policy_handle *handle, bool makeshort,
1010 char **password)
1012 NTSTATUS status;
1013 struct samr_SetUserInfo s;
1014 union samr_UserInfo u;
1015 bool ret = true;
1016 DATA_BLOB session_key;
1017 char *newpass;
1018 struct dcerpc_binding_handle *b = p->binding_handle;
1019 struct samr_GetUserPwInfo pwp;
1020 struct samr_PwInfo info;
1021 int policy_min_pw_len = 0;
1023 pwp.in.user_handle = handle;
1024 pwp.out.info = &info;
1026 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1027 "GetUserPwInfo failed");
1028 if (NT_STATUS_IS_OK(pwp.out.result)) {
1029 policy_min_pw_len = pwp.out.info->min_password_length;
1031 if (makeshort && policy_min_pw_len) {
1032 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
1033 } else {
1034 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1037 s.in.user_handle = handle;
1038 s.in.info = &u;
1039 s.in.level = 26;
1041 u.info26.password_expired = 0;
1043 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
1044 if (!NT_STATUS_IS_OK(status)) {
1045 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1046 s.in.level, nt_errstr(status));
1047 return false;
1050 status = init_samr_CryptPasswordEx(newpass,
1051 &session_key,
1052 &u.info26.password);
1053 torture_assert_ntstatus_ok(tctx,
1054 status,
1055 "init_samr_CryptPasswordEx failed");
1057 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
1059 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1060 "SetUserInfo failed");
1061 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1062 __location__, __FUNCTION__,
1063 newpass, nt_errstr(s.out.result));
1064 if (!NT_STATUS_IS_OK(s.out.result)) {
1065 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1066 s.in.level, nt_errstr(s.out.result));
1067 ret = false;
1068 } else {
1069 *password = newpass;
1072 /* This should break the key nicely */
1073 session_key.data[0]++;
1075 status = init_samr_CryptPasswordEx(newpass,
1076 &session_key,
1077 &u.info26.password);
1078 torture_assert_ntstatus_ok(tctx,
1079 status,
1080 "init_samr_CryptPasswordEx failed");
1082 /* Reset the key */
1083 session_key.data[0]--;
1085 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
1087 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1088 "SetUserInfo failed");
1089 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1090 __location__, __FUNCTION__,
1091 newpass, nt_errstr(s.out.result));
1092 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
1093 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
1094 s.in.level, nt_errstr(s.out.result));
1095 ret = false;
1096 } else {
1097 *password = newpass;
1100 return ret;
1103 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
1104 struct policy_handle *handle, uint32_t fields_present,
1105 char **password)
1107 NTSTATUS status;
1108 struct samr_SetUserInfo s;
1109 union samr_UserInfo u;
1110 bool ret = true;
1111 DATA_BLOB session_key;
1112 char *newpass;
1113 struct dcerpc_binding_handle *b = p->binding_handle;
1114 struct samr_GetUserPwInfo pwp;
1115 struct samr_PwInfo info;
1116 int policy_min_pw_len = 0;
1118 pwp.in.user_handle = handle;
1119 pwp.out.info = &info;
1121 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1122 "GetUserPwInfo failed");
1123 if (NT_STATUS_IS_OK(pwp.out.result)) {
1124 policy_min_pw_len = pwp.out.info->min_password_length;
1126 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1128 s.in.user_handle = handle;
1129 s.in.info = &u;
1130 s.in.level = 25;
1132 ZERO_STRUCT(u);
1134 u.info25.info.fields_present = fields_present;
1136 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
1137 if (!NT_STATUS_IS_OK(status)) {
1138 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1139 s.in.level, nt_errstr(status));
1140 return false;
1143 status = init_samr_CryptPasswordEx(newpass,
1144 &session_key,
1145 &u.info25.password);
1146 torture_assert_ntstatus_ok(tctx,
1147 status,
1148 "init_samr_CryptPasswordEx failed");
1150 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
1152 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1153 "SetUserInfo failed");
1154 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1155 __location__, __FUNCTION__,
1156 newpass, nt_errstr(s.out.result));
1157 if (!NT_STATUS_IS_OK(s.out.result)) {
1158 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1159 s.in.level, nt_errstr(s.out.result));
1160 ret = false;
1161 } else {
1162 *password = newpass;
1165 /* This should break the key nicely */
1166 session_key.data[0]++;
1168 status = init_samr_CryptPasswordEx(newpass,
1169 &session_key,
1170 &u.info25.password);
1171 torture_assert_ntstatus_ok(tctx,
1172 status,
1173 "init_samr_CryptPasswordEx failed");
1175 /* Reset the key */
1176 session_key.data[0]--;
1178 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
1180 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1181 "SetUserInfo failed");
1182 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1183 __location__, __FUNCTION__,
1184 newpass, nt_errstr(s.out.result));
1185 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
1186 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
1187 s.in.level, nt_errstr(s.out.result));
1188 ret = false;
1191 return ret;
1194 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
1195 struct policy_handle *handle, char **password)
1197 NTSTATUS status;
1198 struct samr_SetUserInfo s;
1199 union samr_UserInfo u;
1200 bool ret = true;
1201 DATA_BLOB session_key;
1202 char *newpass;
1203 struct dcerpc_binding_handle *b = p->binding_handle;
1204 struct samr_GetUserPwInfo pwp;
1205 struct samr_PwInfo info;
1206 int policy_min_pw_len = 0;
1207 uint8_t lm_hash[16], nt_hash[16];
1209 pwp.in.user_handle = handle;
1210 pwp.out.info = &info;
1212 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1213 "GetUserPwInfo failed");
1214 if (NT_STATUS_IS_OK(pwp.out.result)) {
1215 policy_min_pw_len = pwp.out.info->min_password_length;
1217 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1219 s.in.user_handle = handle;
1220 s.in.info = &u;
1221 s.in.level = 18;
1223 ZERO_STRUCT(u);
1225 u.info18.nt_pwd_active = true;
1226 u.info18.lm_pwd_active = true;
1228 E_md4hash(newpass, nt_hash);
1229 E_deshash(newpass, lm_hash);
1231 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
1232 if (!NT_STATUS_IS_OK(status)) {
1233 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1234 s.in.level, nt_errstr(status));
1235 return false;
1239 DATA_BLOB in,out;
1240 in = data_blob_const(nt_hash, 16);
1241 out = data_blob_talloc_zero(tctx, 16);
1242 sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
1243 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1246 DATA_BLOB in,out;
1247 in = data_blob_const(lm_hash, 16);
1248 out = data_blob_talloc_zero(tctx, 16);
1249 sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
1250 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1253 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
1255 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1256 "SetUserInfo failed");
1257 if (!NT_STATUS_IS_OK(s.out.result)) {
1258 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1259 s.in.level, nt_errstr(s.out.result));
1260 ret = false;
1261 } else {
1262 *password = newpass;
1265 return ret;
1268 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1269 struct policy_handle *handle, uint32_t fields_present,
1270 char **password)
1272 NTSTATUS status;
1273 struct samr_SetUserInfo s;
1274 union samr_UserInfo u;
1275 bool ret = true;
1276 DATA_BLOB session_key;
1277 char *newpass;
1278 struct dcerpc_binding_handle *b = p->binding_handle;
1279 struct samr_GetUserPwInfo pwp;
1280 struct samr_PwInfo info;
1281 int policy_min_pw_len = 0;
1282 uint8_t lm_hash[16], nt_hash[16];
1284 pwp.in.user_handle = handle;
1285 pwp.out.info = &info;
1287 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1288 "GetUserPwInfo failed");
1289 if (NT_STATUS_IS_OK(pwp.out.result)) {
1290 policy_min_pw_len = pwp.out.info->min_password_length;
1292 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1294 s.in.user_handle = handle;
1295 s.in.info = &u;
1296 s.in.level = 21;
1298 E_md4hash(newpass, nt_hash);
1299 E_deshash(newpass, lm_hash);
1301 ZERO_STRUCT(u);
1303 u.info21.fields_present = fields_present;
1305 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1306 u.info21.lm_owf_password.length = 16;
1307 u.info21.lm_owf_password.size = 16;
1308 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1309 u.info21.lm_password_set = true;
1312 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1313 u.info21.nt_owf_password.length = 16;
1314 u.info21.nt_owf_password.size = 16;
1315 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1316 u.info21.nt_password_set = true;
1319 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
1320 if (!NT_STATUS_IS_OK(status)) {
1321 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1322 s.in.level, nt_errstr(status));
1323 return false;
1326 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1327 DATA_BLOB in,out;
1328 in = data_blob_const(u.info21.lm_owf_password.array,
1329 u.info21.lm_owf_password.length);
1330 out = data_blob_talloc_zero(tctx, 16);
1331 sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
1332 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1335 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1336 DATA_BLOB in,out;
1337 in = data_blob_const(u.info21.nt_owf_password.array,
1338 u.info21.nt_owf_password.length);
1339 out = data_blob_talloc_zero(tctx, 16);
1340 sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
1341 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1344 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1346 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1347 "SetUserInfo failed");
1348 if (!NT_STATUS_IS_OK(s.out.result)) {
1349 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
1350 s.in.level, nt_errstr(s.out.result));
1351 ret = false;
1352 } else {
1353 *password = newpass;
1356 /* try invalid length */
1357 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1359 u.info21.nt_owf_password.length++;
1361 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1362 "SetUserInfo failed");
1363 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1364 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1365 s.in.level, nt_errstr(s.out.result));
1366 ret = false;
1370 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1372 u.info21.lm_owf_password.length++;
1374 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1375 "SetUserInfo failed");
1376 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1377 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1378 s.in.level, nt_errstr(s.out.result));
1379 ret = false;
1383 return ret;
1386 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1387 struct torture_context *tctx,
1388 struct policy_handle *handle,
1389 uint16_t level,
1390 uint32_t fields_present,
1391 char **password, uint8_t password_expired,
1392 bool use_setinfo2,
1393 bool *matched_expected_error)
1395 NTSTATUS status;
1396 NTSTATUS expected_error = NT_STATUS_OK;
1397 struct samr_SetUserInfo s;
1398 struct samr_SetUserInfo2 s2;
1399 union samr_UserInfo u;
1400 bool ret = true;
1401 DATA_BLOB session_key;
1402 uint8_t salt_data[16];
1403 DATA_BLOB salt = {
1404 .data = salt_data,
1405 .length = sizeof(salt_data),
1407 char *newpass;
1408 struct dcerpc_binding_handle *b = p->binding_handle;
1409 struct samr_GetUserPwInfo pwp;
1410 struct samr_PwInfo info;
1411 int policy_min_pw_len = 0;
1412 const char *comment = NULL;
1413 uint8_t lm_hash[16], nt_hash[16];
1415 pwp.in.user_handle = handle;
1416 pwp.out.info = &info;
1418 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1419 "GetUserPwInfo failed");
1420 if (NT_STATUS_IS_OK(pwp.out.result)) {
1421 policy_min_pw_len = pwp.out.info->min_password_length;
1423 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1425 if (use_setinfo2) {
1426 s2.in.user_handle = handle;
1427 s2.in.info = &u;
1428 s2.in.level = level;
1429 } else {
1430 s.in.user_handle = handle;
1431 s.in.info = &u;
1432 s.in.level = level;
1435 if (fields_present & SAMR_FIELD_COMMENT) {
1436 comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
1439 ZERO_STRUCT(u);
1441 switch (level) {
1442 case 18:
1443 E_md4hash(newpass, nt_hash);
1444 E_deshash(newpass, lm_hash);
1446 u.info18.nt_pwd_active = true;
1447 u.info18.lm_pwd_active = true;
1448 u.info18.password_expired = password_expired;
1450 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1451 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1453 break;
1454 case 21:
1455 E_md4hash(newpass, nt_hash);
1456 E_deshash(newpass, lm_hash);
1458 u.info21.fields_present = fields_present;
1459 u.info21.password_expired = password_expired;
1460 u.info21.comment.string = comment;
1462 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1463 u.info21.lm_owf_password.length = 16;
1464 u.info21.lm_owf_password.size = 16;
1465 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1466 u.info21.lm_password_set = true;
1469 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1470 u.info21.nt_owf_password.length = 16;
1471 u.info21.nt_owf_password.size = 16;
1472 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1473 u.info21.nt_password_set = true;
1476 break;
1477 case 23:
1478 u.info23.info.fields_present = fields_present;
1479 u.info23.info.password_expired = password_expired;
1480 u.info23.info.comment.string = comment;
1482 break;
1483 case 24:
1484 u.info24.password_expired = password_expired;
1486 break;
1487 case 25:
1488 u.info25.info.fields_present = fields_present;
1489 u.info25.info.password_expired = password_expired;
1490 u.info25.info.comment.string = comment;
1492 break;
1493 case 26:
1494 u.info26.password_expired = password_expired;
1496 break;
1497 case 31:
1498 u.info31.password_expired = password_expired;
1500 break;
1501 case 28:
1502 u.info25.info.fields_present = fields_present;
1503 u.info25.info.password_expired = password_expired;
1504 u.info25.info.comment.string = comment;
1506 break;
1509 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
1510 if (!NT_STATUS_IS_OK(status)) {
1511 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
1512 s.in.level, nt_errstr(status));
1513 return false;
1516 generate_nonce_buffer(salt.data, salt.length);
1518 switch (level) {
1519 case 18:
1521 DATA_BLOB in,out;
1522 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1523 out = data_blob_talloc_zero(tctx, 16);
1524 sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
1525 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1528 DATA_BLOB in,out;
1529 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1530 out = data_blob_talloc_zero(tctx, 16);
1531 sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
1532 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1535 break;
1536 case 21:
1537 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1538 DATA_BLOB in,out;
1539 in = data_blob_const(u.info21.lm_owf_password.array,
1540 u.info21.lm_owf_password.length);
1541 out = data_blob_talloc_zero(tctx, 16);
1542 sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
1543 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1545 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1546 DATA_BLOB in,out;
1547 in = data_blob_const(u.info21.nt_owf_password.array,
1548 u.info21.nt_owf_password.length);
1549 out = data_blob_talloc_zero(tctx, 16);
1550 sess_crypt_blob(&out, &in, &session_key, SAMBA_GNUTLS_ENCRYPT);
1551 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1553 break;
1554 case 23:
1555 status = init_samr_CryptPassword(newpass,
1556 &session_key,
1557 &u.info23.password);
1558 torture_assert_ntstatus_ok(tctx,
1559 status,
1560 "init_samr_CryptPassword failed");
1561 break;
1562 case 24:
1563 status = init_samr_CryptPassword(newpass,
1564 &session_key,
1565 &u.info24.password);
1566 torture_assert_ntstatus_ok(tctx,
1567 status,
1568 "init_samr_CryptPassword failed");
1569 break;
1570 case 25:
1571 status = init_samr_CryptPasswordEx(newpass,
1572 &session_key,
1573 &u.info25.password);
1574 torture_assert_ntstatus_ok(tctx,
1575 status,
1576 "init_samr_CryptPasswordEx failed");
1577 break;
1578 case 26:
1579 status = init_samr_CryptPasswordEx(newpass,
1580 &session_key,
1581 &u.info26.password);
1582 torture_assert_ntstatus_ok(tctx,
1583 status,
1584 "init_samr_CryptPasswordEx failed");
1585 break;
1586 case 31:
1587 status = init_samr_CryptPasswordAES(tctx,
1588 newpass,
1589 &salt,
1590 &session_key,
1591 &u.info31.password);
1593 break;
1594 case 32:
1595 status = init_samr_CryptPasswordAES(tctx,
1596 newpass,
1597 &salt,
1598 &session_key,
1599 &u.info32.password);
1601 break;
1604 if (use_setinfo2) {
1605 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1606 "SetUserInfo2 failed");
1607 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1608 __location__, __FUNCTION__,
1609 newpass, nt_errstr(s2.out.result));
1610 status = s2.out.result;
1611 } else {
1612 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1613 "SetUserInfo failed");
1614 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1615 __location__, __FUNCTION__,
1616 newpass, nt_errstr(s.out.result));
1617 status = s.out.result;
1620 if (!NT_STATUS_IS_OK(status)) {
1621 if (fields_present == 0) {
1622 expected_error = NT_STATUS_INVALID_PARAMETER;
1624 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1625 expected_error = NT_STATUS_ACCESS_DENIED;
1629 if (!NT_STATUS_IS_OK(expected_error)) {
1630 if (use_setinfo2) {
1631 torture_assert_ntstatus_equal(tctx,
1632 s2.out.result,
1633 expected_error, "SetUserInfo2 failed");
1634 } else {
1635 torture_assert_ntstatus_equal(tctx,
1636 s.out.result,
1637 expected_error, "SetUserInfo failed");
1639 *matched_expected_error = true;
1640 return true;
1643 if (!NT_STATUS_IS_OK(status)) {
1644 torture_result(tctx, TORTURE_FAIL, "SetUserInfo%s level %u failed - %s\n",
1645 use_setinfo2 ? "2":"", level, nt_errstr(status));
1646 ret = false;
1647 } else {
1648 *password = newpass;
1651 return ret;
1654 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1655 struct torture_context *tctx,
1656 struct policy_handle *handle)
1658 struct samr_SetAliasInfo r;
1659 struct samr_QueryAliasInfo q;
1660 union samr_AliasInfo *info;
1661 uint16_t levels[] = {2, 3};
1662 int i;
1663 bool ret = true;
1665 /* Ignoring switch level 1, as that includes the number of members for the alias
1666 * and setting this to a wrong value might have negative consequences
1669 for (i=0;i<ARRAY_SIZE(levels);i++) {
1670 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1672 r.in.alias_handle = handle;
1673 r.in.level = levels[i];
1674 r.in.info = talloc(tctx, union samr_AliasInfo);
1675 switch (r.in.level) {
1676 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1677 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1678 "Test Description, should test I18N as well"); break;
1679 case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1682 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1683 "SetAliasInfo failed");
1684 if (!NT_STATUS_IS_OK(r.out.result)) {
1685 torture_result(tctx, TORTURE_FAIL, "SetAliasInfo level %u failed - %s\n",
1686 levels[i], nt_errstr(r.out.result));
1687 ret = false;
1690 q.in.alias_handle = handle;
1691 q.in.level = levels[i];
1692 q.out.info = &info;
1694 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1695 "QueryAliasInfo failed");
1696 if (!NT_STATUS_IS_OK(q.out.result)) {
1697 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
1698 levels[i], nt_errstr(q.out.result));
1699 ret = false;
1703 return ret;
1706 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1707 struct torture_context *tctx,
1708 struct policy_handle *user_handle)
1710 struct samr_GetGroupsForUser r;
1711 struct samr_RidWithAttributeArray *rids = NULL;
1713 torture_comment(tctx, "Testing GetGroupsForUser\n");
1715 r.in.user_handle = user_handle;
1716 r.out.rids = &rids;
1718 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1719 "GetGroupsForUser failed");
1720 torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1722 return true;
1726 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1727 struct lsa_String *domain_name)
1729 struct samr_GetDomPwInfo r;
1730 struct samr_PwInfo info;
1731 struct dcerpc_binding_handle *b = p->binding_handle;
1733 r.in.domain_name = domain_name;
1734 r.out.info = &info;
1736 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1738 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1739 "GetDomPwInfo failed");
1740 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1742 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1743 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1745 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1746 "GetDomPwInfo failed");
1747 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1749 r.in.domain_name->string = "\\\\__NONAME__";
1750 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1752 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1753 "GetDomPwInfo failed");
1754 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1756 r.in.domain_name->string = "\\\\Builtin";
1757 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1759 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1760 "GetDomPwInfo failed");
1761 torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1763 return true;
1766 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1767 struct torture_context *tctx,
1768 struct policy_handle *handle)
1770 struct samr_GetUserPwInfo r;
1771 struct samr_PwInfo info;
1773 torture_comment(tctx, "Testing GetUserPwInfo\n");
1775 r.in.user_handle = handle;
1776 r.out.info = &info;
1778 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1779 "GetUserPwInfo failed");
1780 torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1782 return true;
1785 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1786 struct torture_context *tctx,
1787 struct policy_handle *domain_handle, const char *name,
1788 uint32_t *rid)
1790 NTSTATUS status;
1791 struct samr_LookupNames n;
1792 struct lsa_String sname[2];
1793 struct samr_Ids rids, types;
1795 init_lsa_String(&sname[0], name);
1797 n.in.domain_handle = domain_handle;
1798 n.in.num_names = 1;
1799 n.in.names = sname;
1800 n.out.rids = &rids;
1801 n.out.types = &types;
1802 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1803 if (!NT_STATUS_IS_OK(status)) {
1804 return status;
1806 if (NT_STATUS_IS_OK(n.out.result)) {
1807 *rid = n.out.rids->ids[0];
1808 } else {
1809 return n.out.result;
1812 init_lsa_String(&sname[1], "xxNONAMExx");
1813 n.in.num_names = 2;
1814 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1815 if (!NT_STATUS_IS_OK(status)) {
1816 return status;
1818 if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1819 torture_result(tctx, TORTURE_FAIL, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1820 if (NT_STATUS_IS_OK(n.out.result)) {
1821 return NT_STATUS_UNSUCCESSFUL;
1823 return n.out.result;
1826 n.in.num_names = 0;
1827 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1828 if (!NT_STATUS_IS_OK(status)) {
1829 return status;
1831 if (!NT_STATUS_IS_OK(n.out.result)) {
1832 torture_result(tctx, TORTURE_FAIL, "LookupNames[0] failed - %s\n", nt_errstr(status));
1833 return n.out.result;
1836 init_lsa_String(&sname[0], "xxNONAMExx");
1837 n.in.num_names = 1;
1838 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1839 if (!NT_STATUS_IS_OK(status)) {
1840 return status;
1842 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1843 torture_result(tctx, TORTURE_FAIL, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1844 if (NT_STATUS_IS_OK(n.out.result)) {
1845 return NT_STATUS_UNSUCCESSFUL;
1847 return n.out.result;
1850 init_lsa_String(&sname[0], "xxNONAMExx");
1851 init_lsa_String(&sname[1], "xxNONAME2xx");
1852 n.in.num_names = 2;
1853 status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1854 if (!NT_STATUS_IS_OK(status)) {
1855 return status;
1857 if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1858 torture_result(tctx, TORTURE_FAIL, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1859 if (NT_STATUS_IS_OK(n.out.result)) {
1860 return NT_STATUS_UNSUCCESSFUL;
1862 return n.out.result;
1865 return NT_STATUS_OK;
1868 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1869 struct torture_context *tctx,
1870 struct policy_handle *domain_handle,
1871 const char *name, struct policy_handle *user_handle)
1873 NTSTATUS status;
1874 struct samr_OpenUser r;
1875 uint32_t rid;
1877 status = test_LookupName(b, tctx, domain_handle, name, &rid);
1878 if (!NT_STATUS_IS_OK(status)) {
1879 return status;
1882 r.in.domain_handle = domain_handle;
1883 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1884 r.in.rid = rid;
1885 r.out.user_handle = user_handle;
1886 status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1887 if (!NT_STATUS_IS_OK(status)) {
1888 return status;
1890 if (!NT_STATUS_IS_OK(r.out.result)) {
1891 torture_result(tctx, TORTURE_FAIL, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1894 return r.out.result;
1897 #if 0
1898 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1899 struct torture_context *tctx,
1900 struct policy_handle *handle)
1902 NTSTATUS status;
1903 struct samr_ChangePasswordUser r;
1904 bool ret = true;
1905 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1906 struct policy_handle user_handle;
1907 char *oldpass = "test";
1908 char *newpass = "test2";
1909 uint8_t old_nt_hash[16], new_nt_hash[16];
1910 uint8_t old_lm_hash[16], new_lm_hash[16];
1912 status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 return false;
1917 torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1919 torture_comment(tctx, "old password: %s\n", oldpass);
1920 torture_comment(tctx, "new password: %s\n", newpass);
1922 E_md4hash(oldpass, old_nt_hash);
1923 E_md4hash(newpass, new_nt_hash);
1924 E_deshash(oldpass, old_lm_hash);
1925 E_deshash(newpass, new_lm_hash);
1927 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1928 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1929 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1930 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1931 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1932 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1934 r.in.handle = &user_handle;
1935 r.in.lm_present = 1;
1936 r.in.old_lm_crypted = &hash1;
1937 r.in.new_lm_crypted = &hash2;
1938 r.in.nt_present = 1;
1939 r.in.old_nt_crypted = &hash3;
1940 r.in.new_nt_crypted = &hash4;
1941 r.in.cross1_present = 1;
1942 r.in.nt_cross = &hash5;
1943 r.in.cross2_present = 1;
1944 r.in.lm_cross = &hash6;
1946 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1947 "ChangePasswordUser failed");
1948 if (!NT_STATUS_IS_OK(r.out.result)) {
1949 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1950 ret = false;
1953 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1954 ret = false;
1957 return ret;
1959 #endif
1961 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1962 struct torture_context *tctx,
1963 const char *acct_name,
1964 struct policy_handle *handle, char **password)
1966 NTSTATUS status;
1967 struct samr_ChangePasswordUser r;
1968 bool ret = true;
1969 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1970 struct policy_handle user_handle;
1971 char *oldpass;
1972 uint8_t old_nt_hash[16], new_nt_hash[16];
1973 uint8_t old_lm_hash[16], new_lm_hash[16];
1974 bool changed = true;
1976 char *newpass;
1977 struct samr_GetUserPwInfo pwp;
1978 struct samr_PwInfo info;
1979 int policy_min_pw_len = 0;
1981 status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1982 if (!NT_STATUS_IS_OK(status)) {
1983 return false;
1985 pwp.in.user_handle = &user_handle;
1986 pwp.out.info = &info;
1988 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1989 "GetUserPwInfo failed");
1990 if (NT_STATUS_IS_OK(pwp.out.result)) {
1991 policy_min_pw_len = pwp.out.info->min_password_length;
1993 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1995 torture_comment(tctx, "Testing ChangePasswordUser\n");
1997 torture_assert(tctx, *password != NULL,
1998 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
2000 oldpass = *password;
2002 E_md4hash(oldpass, old_nt_hash);
2003 E_md4hash(newpass, new_nt_hash);
2004 E_deshash(oldpass, old_lm_hash);
2005 E_deshash(newpass, new_lm_hash);
2007 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
2008 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
2009 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
2010 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
2011 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
2012 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
2014 r.in.user_handle = &user_handle;
2015 r.in.lm_present = 1;
2016 /* Break the NT hash */
2017 hash3.hash[0]++;
2018 r.in.old_lm_crypted = &hash1;
2019 r.in.new_lm_crypted = &hash2;
2020 r.in.nt_present = 1;
2021 r.in.old_nt_crypted = &hash3;
2022 r.in.new_nt_crypted = &hash4;
2023 r.in.cross1_present = 1;
2024 r.in.nt_cross = &hash5;
2025 r.in.cross2_present = 1;
2026 r.in.lm_cross = &hash6;
2028 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
2029 "ChangePasswordUser failed");
2030 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2031 __location__, __FUNCTION__,
2032 oldpass, newpass, nt_errstr(r.out.result));
2034 /* Do not proceed if this call has been removed */
2035 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
2036 torture_skip(tctx, "ValidatePassword not supported by server\n");
2039 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2040 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
2041 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
2044 /* Unbreak the NT hash */
2045 hash3.hash[0]--;
2047 r.in.user_handle = &user_handle;
2048 r.in.lm_present = 1;
2049 r.in.old_lm_crypted = &hash1;
2050 r.in.new_lm_crypted = &hash2;
2051 /* Break the LM hash */
2052 hash1.hash[0]--;
2053 r.in.nt_present = 1;
2054 r.in.old_nt_crypted = &hash3;
2055 r.in.new_nt_crypted = &hash4;
2056 r.in.cross1_present = 1;
2057 r.in.nt_cross = &hash5;
2058 r.in.cross2_present = 1;
2059 r.in.lm_cross = &hash6;
2061 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
2062 "ChangePasswordUser failed");
2063 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2064 __location__, __FUNCTION__,
2065 oldpass, newpass, nt_errstr(r.out.result));
2066 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2067 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
2068 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
2071 /* Unbreak the NT hash */
2072 hash3.hash[0]--;
2074 r.in.user_handle = &user_handle;
2075 r.in.lm_present = 1;
2076 r.in.old_lm_crypted = &hash1;
2077 r.in.new_lm_crypted = &hash2;
2078 r.in.nt_present = 1;
2079 r.in.old_nt_crypted = &hash3;
2080 r.in.new_nt_crypted = &hash4;
2081 r.in.cross1_present = 1;
2082 r.in.nt_cross = &hash5;
2083 r.in.cross2_present = 1;
2084 /* Break the LM cross */
2085 hash6.hash[0]++;
2086 r.in.lm_cross = &hash6;
2088 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
2089 "ChangePasswordUser failed");
2090 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2091 __location__, __FUNCTION__,
2092 oldpass, newpass, nt_errstr(r.out.result));
2093 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
2094 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
2096 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
2097 ret = false;
2100 /* Unbreak the LM cross */
2101 hash6.hash[0]--;
2103 r.in.user_handle = &user_handle;
2104 r.in.lm_present = 1;
2105 r.in.old_lm_crypted = &hash1;
2106 r.in.new_lm_crypted = &hash2;
2107 r.in.nt_present = 1;
2108 r.in.old_nt_crypted = &hash3;
2109 r.in.new_nt_crypted = &hash4;
2110 r.in.cross1_present = 1;
2111 /* Break the NT cross */
2112 hash5.hash[0]++;
2113 r.in.nt_cross = &hash5;
2114 r.in.cross2_present = 1;
2115 r.in.lm_cross = &hash6;
2117 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
2118 "ChangePasswordUser failed");
2119 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2120 __location__, __FUNCTION__,
2121 oldpass, newpass, nt_errstr(r.out.result));
2122 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
2123 !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
2125 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
2126 ret = false;
2129 /* Unbreak the NT cross */
2130 hash5.hash[0]--;
2133 /* Reset the hashes to not broken values */
2134 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
2135 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
2136 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
2137 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
2138 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
2139 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
2141 r.in.user_handle = &user_handle;
2142 r.in.lm_present = 1;
2143 r.in.old_lm_crypted = &hash1;
2144 r.in.new_lm_crypted = &hash2;
2145 r.in.nt_present = 1;
2146 r.in.old_nt_crypted = &hash3;
2147 r.in.new_nt_crypted = &hash4;
2148 r.in.cross1_present = 1;
2149 r.in.nt_cross = &hash5;
2150 r.in.cross2_present = 0;
2151 r.in.lm_cross = NULL;
2153 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
2154 "ChangePasswordUser failed");
2155 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2156 __location__, __FUNCTION__,
2157 oldpass, newpass, nt_errstr(r.out.result));
2158 if (NT_STATUS_IS_OK(r.out.result)) {
2159 changed = true;
2160 *password = newpass;
2161 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
2162 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
2163 ret = false;
2166 oldpass = newpass;
2167 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2169 E_md4hash(oldpass, old_nt_hash);
2170 E_md4hash(newpass, new_nt_hash);
2171 E_deshash(oldpass, old_lm_hash);
2172 E_deshash(newpass, new_lm_hash);
2175 /* Reset the hashes to not broken values */
2176 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
2177 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
2178 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
2179 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
2180 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
2181 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
2183 r.in.user_handle = &user_handle;
2184 r.in.lm_present = 1;
2185 r.in.old_lm_crypted = &hash1;
2186 r.in.new_lm_crypted = &hash2;
2187 r.in.nt_present = 1;
2188 r.in.old_nt_crypted = &hash3;
2189 r.in.new_nt_crypted = &hash4;
2190 r.in.cross1_present = 0;
2191 r.in.nt_cross = NULL;
2192 r.in.cross2_present = 1;
2193 r.in.lm_cross = &hash6;
2195 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
2196 "ChangePasswordUser failed");
2197 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2198 __location__, __FUNCTION__,
2199 oldpass, newpass, nt_errstr(r.out.result));
2200 if (NT_STATUS_IS_OK(r.out.result)) {
2201 changed = true;
2202 *password = newpass;
2203 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
2204 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
2205 ret = false;
2208 oldpass = newpass;
2209 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2211 E_md4hash(oldpass, old_nt_hash);
2212 E_md4hash(newpass, new_nt_hash);
2213 E_deshash(oldpass, old_lm_hash);
2214 E_deshash(newpass, new_lm_hash);
2217 /* Reset the hashes to not broken values */
2218 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
2219 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
2220 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
2221 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
2222 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
2223 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
2225 r.in.user_handle = &user_handle;
2226 r.in.lm_present = 1;
2227 r.in.old_lm_crypted = &hash1;
2228 r.in.new_lm_crypted = &hash2;
2229 r.in.nt_present = 1;
2230 r.in.old_nt_crypted = &hash3;
2231 r.in.new_nt_crypted = &hash4;
2232 r.in.cross1_present = 1;
2233 r.in.nt_cross = &hash5;
2234 r.in.cross2_present = 1;
2235 r.in.lm_cross = &hash6;
2237 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
2238 "ChangePasswordUser failed");
2239 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2240 __location__, __FUNCTION__,
2241 oldpass, newpass, nt_errstr(r.out.result));
2242 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2243 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2244 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2245 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
2246 ret = false;
2247 } else {
2248 changed = true;
2249 *password = newpass;
2252 r.in.user_handle = &user_handle;
2253 r.in.lm_present = 1;
2254 r.in.old_lm_crypted = &hash1;
2255 r.in.new_lm_crypted = &hash2;
2256 r.in.nt_present = 1;
2257 r.in.old_nt_crypted = &hash3;
2258 r.in.new_nt_crypted = &hash4;
2259 r.in.cross1_present = 1;
2260 r.in.nt_cross = &hash5;
2261 r.in.cross2_present = 1;
2262 r.in.lm_cross = &hash6;
2264 if (changed) {
2265 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
2266 "ChangePasswordUser failed");
2267 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2268 __location__, __FUNCTION__,
2269 oldpass, newpass, nt_errstr(r.out.result));
2270 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2271 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2272 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2273 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
2274 ret = false;
2279 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
2280 ret = false;
2283 return ret;
2287 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
2288 struct torture_context *tctx,
2289 const char *acct_name,
2290 struct policy_handle *handle, char **password)
2292 struct samr_OemChangePasswordUser2 r;
2293 bool ret = true;
2294 struct samr_Password lm_verifier;
2295 struct samr_CryptPassword lm_pass;
2296 struct lsa_AsciiString server, account, account_bad;
2297 char *oldpass;
2298 char *newpass;
2299 struct dcerpc_binding_handle *b = p->binding_handle;
2300 uint8_t old_lm_hash[16], new_lm_hash[16];
2301 gnutls_cipher_hd_t cipher_hnd = NULL;
2302 gnutls_datum_t session_key = {
2303 .data = old_lm_hash,
2304 .size = 16
2307 struct samr_GetDomPwInfo dom_pw_info;
2308 struct samr_PwInfo info;
2309 int policy_min_pw_len = 0;
2311 struct lsa_String domain_name;
2313 domain_name.string = "";
2314 dom_pw_info.in.domain_name = &domain_name;
2315 dom_pw_info.out.info = &info;
2317 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
2319 torture_assert(tctx, *password != NULL,
2320 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
2322 oldpass = *password;
2324 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2325 "GetDomPwInfo failed");
2326 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2327 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2330 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2332 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2333 account.string = acct_name;
2335 E_deshash(oldpass, old_lm_hash);
2336 E_deshash(newpass, new_lm_hash);
2338 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2340 gnutls_cipher_init(&cipher_hnd,
2341 GNUTLS_CIPHER_ARCFOUR_128,
2342 &session_key,
2343 NULL);
2344 gnutls_cipher_encrypt(cipher_hnd, lm_pass.data, 516);
2345 gnutls_cipher_deinit(cipher_hnd);
2346 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2348 r.in.server = &server;
2349 r.in.account = &account;
2350 r.in.password = &lm_pass;
2351 r.in.hash = &lm_verifier;
2353 /* Break the verification */
2354 lm_verifier.hash[0]++;
2356 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2357 "OemChangePasswordUser2 failed");
2358 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2359 __location__, __FUNCTION__,
2360 oldpass, newpass, nt_errstr(r.out.result));
2362 if (torture_setting_bool(tctx, "samba4", false)) {
2363 torture_assert_ntstatus_equal(tctx,
2364 r.out.result,
2365 NT_STATUS_NOT_IMPLEMENTED,
2366 "Samba4 should refuse LM password change");
2368 * No point continuing, once we have checked this is not
2369 * implemented
2371 return true;
2374 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2375 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2376 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2377 nt_errstr(r.out.result));
2378 ret = false;
2381 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2382 /* Break the old password */
2383 old_lm_hash[0]++;
2384 gnutls_cipher_init(&cipher_hnd,
2385 GNUTLS_CIPHER_ARCFOUR_128,
2386 &session_key,
2387 NULL);
2388 gnutls_cipher_encrypt(cipher_hnd, lm_pass.data, 516);
2389 gnutls_cipher_deinit(cipher_hnd);
2390 /* unbreak it for the next operation */
2391 old_lm_hash[0]--;
2392 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2394 r.in.server = &server;
2395 r.in.account = &account;
2396 r.in.password = &lm_pass;
2397 r.in.hash = &lm_verifier;
2399 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2400 "OemChangePasswordUser2 failed");
2401 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2402 __location__, __FUNCTION__,
2403 oldpass, newpass, nt_errstr(r.out.result));
2405 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2406 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2407 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrypted password - %s\n",
2408 nt_errstr(r.out.result));
2409 ret = false;
2412 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2413 gnutls_cipher_init(&cipher_hnd,
2414 GNUTLS_CIPHER_ARCFOUR_128,
2415 &session_key,
2416 NULL);
2417 gnutls_cipher_encrypt(cipher_hnd, lm_pass.data, 516);
2418 gnutls_cipher_deinit(cipher_hnd);
2420 r.in.server = &server;
2421 r.in.account = &account;
2422 r.in.password = &lm_pass;
2423 r.in.hash = NULL;
2425 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2426 "OemChangePasswordUser2 failed");
2427 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2428 __location__, __FUNCTION__,
2429 oldpass, newpass, nt_errstr(r.out.result));
2431 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2432 && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2433 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2434 nt_errstr(r.out.result));
2435 ret = false;
2438 /* This shouldn't be a valid name */
2439 account_bad.string = TEST_ACCOUNT_NAME "XX";
2440 r.in.account = &account_bad;
2442 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2443 "OemChangePasswordUser2 failed");
2444 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2445 __location__, __FUNCTION__,
2446 oldpass, newpass, nt_errstr(r.out.result));
2448 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2449 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2450 nt_errstr(r.out.result));
2451 ret = false;
2454 /* This shouldn't be a valid name */
2455 account_bad.string = TEST_ACCOUNT_NAME "XX";
2456 r.in.account = &account_bad;
2457 r.in.password = &lm_pass;
2458 r.in.hash = &lm_verifier;
2460 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2461 "OemChangePasswordUser2 failed");
2462 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2463 __location__, __FUNCTION__,
2464 oldpass, newpass, nt_errstr(r.out.result));
2466 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2467 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2468 nt_errstr(r.out.result));
2469 ret = false;
2472 /* This shouldn't be a valid name */
2473 account_bad.string = TEST_ACCOUNT_NAME "XX";
2474 r.in.account = &account_bad;
2475 r.in.password = NULL;
2476 r.in.hash = &lm_verifier;
2478 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2479 "OemChangePasswordUser2 failed");
2480 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2481 __location__, __FUNCTION__,
2482 oldpass, newpass, nt_errstr(r.out.result));
2484 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2485 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2486 nt_errstr(r.out.result));
2487 ret = false;
2490 E_deshash(oldpass, old_lm_hash);
2491 E_deshash(newpass, new_lm_hash);
2493 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2494 gnutls_cipher_init(&cipher_hnd,
2495 GNUTLS_CIPHER_ARCFOUR_128,
2496 &session_key,
2497 NULL);
2498 gnutls_cipher_encrypt(cipher_hnd, lm_pass.data, 516);
2499 gnutls_cipher_deinit(cipher_hnd);
2500 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2502 r.in.server = &server;
2503 r.in.account = &account;
2504 r.in.password = &lm_pass;
2505 r.in.hash = &lm_verifier;
2507 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2508 "OemChangePasswordUser2 failed");
2509 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2510 __location__, __FUNCTION__,
2511 oldpass, newpass, nt_errstr(r.out.result));
2513 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2514 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2515 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2516 torture_result(tctx, TORTURE_FAIL, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2517 ret = false;
2518 } else {
2519 *password = newpass;
2522 return ret;
2526 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2527 const char *acct_name,
2528 char **password,
2529 char *newpass, bool allow_password_restriction)
2531 struct samr_ChangePasswordUser2 r;
2532 bool ret = true;
2533 struct lsa_String server, account;
2534 struct samr_CryptPassword nt_pass, lm_pass;
2535 struct samr_Password nt_verifier, lm_verifier;
2536 char *oldpass;
2537 struct dcerpc_binding_handle *b = p->binding_handle;
2538 uint8_t old_nt_hash[16] = { 0 }, new_nt_hash[16];
2539 uint8_t old_lm_hash[16], new_lm_hash[16];
2540 DATA_BLOB old_nt_hash_blob
2541 = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
2542 struct samr_GetDomPwInfo dom_pw_info;
2543 struct samr_PwInfo info;
2545 struct lsa_String domain_name;
2546 NTSTATUS status;
2548 gnutls_cipher_hd_t cipher_hnd = NULL;
2549 gnutls_datum_t old_lm_key = {
2550 .data = old_lm_hash,
2551 .size = sizeof(old_lm_hash),
2554 domain_name.string = "";
2555 dom_pw_info.in.domain_name = &domain_name;
2556 dom_pw_info.out.info = &info;
2558 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2560 torture_assert(tctx, *password != NULL,
2561 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2562 oldpass = *password;
2564 if (!newpass) {
2565 int policy_min_pw_len = 0;
2566 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2567 "GetDomPwInfo failed");
2568 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2569 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2572 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2575 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2576 init_lsa_String(&account, acct_name);
2578 E_md4hash(oldpass, old_nt_hash);
2579 E_md4hash(newpass, new_nt_hash);
2581 E_deshash(oldpass, old_lm_hash);
2582 E_deshash(newpass, new_lm_hash);
2584 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2586 gnutls_cipher_init(&cipher_hnd,
2587 GNUTLS_CIPHER_ARCFOUR_128,
2588 &old_lm_key,
2589 NULL);
2590 gnutls_cipher_encrypt(cipher_hnd,
2591 lm_pass.data,
2592 516);
2593 gnutls_cipher_deinit(cipher_hnd);
2595 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2597 status = init_samr_CryptPassword(newpass,
2598 &old_nt_hash_blob,
2599 &nt_pass);
2600 torture_assert_ntstatus_ok(tctx,
2601 status,
2602 "init_samr_CryptPassword failed");
2604 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2606 r.in.server = &server;
2607 r.in.account = &account;
2608 r.in.nt_password = &nt_pass;
2609 r.in.nt_verifier = &nt_verifier;
2610 r.in.lm_change = 1;
2611 r.in.lm_password = &lm_pass;
2612 r.in.lm_verifier = &lm_verifier;
2614 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2615 "ChangePasswordUser2 failed");
2616 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2617 __location__, __FUNCTION__,
2618 oldpass, newpass, nt_errstr(r.out.result));
2620 if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2621 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2622 } else if (!NT_STATUS_IS_OK(r.out.result)) {
2623 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2624 ret = false;
2625 } else {
2626 *password = newpass;
2629 return ret;
2633 static bool test_ChangePasswordUser2_ntstatus(struct dcerpc_pipe *p, struct torture_context *tctx,
2634 const char *acct_name,
2635 const char *password, NTSTATUS status)
2637 struct samr_ChangePasswordUser2 r;
2638 struct lsa_String server, account;
2639 struct samr_CryptPassword nt_pass, lm_pass;
2640 struct samr_Password nt_verifier, lm_verifier;
2641 const char *oldpass;
2642 struct dcerpc_binding_handle *b = p->binding_handle;
2643 uint8_t old_nt_hash[16] = { 0 }, new_nt_hash[16];
2644 uint8_t old_lm_hash[16], new_lm_hash[16];
2645 DATA_BLOB old_nt_hash_blob
2646 = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
2647 gnutls_cipher_hd_t cipher_hnd = NULL;
2648 gnutls_datum_t old_lm_key = {
2649 .data = old_lm_hash,
2650 .size = sizeof(old_lm_hash),
2653 struct samr_GetDomPwInfo dom_pw_info;
2654 struct samr_PwInfo info;
2656 struct lsa_String domain_name;
2657 NTSTATUS crypt_status;
2659 char *newpass;
2660 int policy_min_pw_len = 0;
2662 domain_name.string = "";
2663 dom_pw_info.in.domain_name = &domain_name;
2664 dom_pw_info.out.info = &info;
2666 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2668 oldpass = password;
2670 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2671 "GetDomPwInfo failed");
2672 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2673 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2676 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2678 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2679 init_lsa_String(&account, acct_name);
2681 E_md4hash(oldpass, old_nt_hash);
2682 E_md4hash(newpass, new_nt_hash);
2684 E_deshash(oldpass, old_lm_hash);
2685 E_deshash(newpass, new_lm_hash);
2687 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2689 gnutls_cipher_init(&cipher_hnd,
2690 GNUTLS_CIPHER_ARCFOUR_128,
2691 &old_lm_key,
2692 NULL);
2693 gnutls_cipher_encrypt(cipher_hnd,
2694 lm_pass.data,
2695 516);
2696 gnutls_cipher_deinit(cipher_hnd);
2698 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2700 crypt_status = init_samr_CryptPassword(newpass,
2701 &old_nt_hash_blob,
2702 &nt_pass);
2703 torture_assert_ntstatus_ok(tctx,
2704 crypt_status,
2705 "init_samr_CryptPassword failed");
2707 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2709 r.in.server = &server;
2710 r.in.account = &account;
2711 r.in.nt_password = &nt_pass;
2712 r.in.nt_verifier = &nt_verifier;
2713 r.in.lm_change = 1;
2714 r.in.lm_password = &lm_pass;
2715 r.in.lm_verifier = &lm_verifier;
2717 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2718 "ChangePasswordUser2 failed");
2719 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2720 __location__, __FUNCTION__,
2721 oldpass, newpass, nt_errstr(r.out.result));
2723 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2724 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2725 } else {
2726 torture_assert_ntstatus_equal(tctx, r.out.result, status, "ChangePasswordUser2 returned unexpected value");
2729 return true;
2733 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2734 const char *account_string,
2735 int policy_min_pw_len,
2736 char **password,
2737 const char *newpass,
2738 NTTIME last_password_change,
2739 bool handle_reject_reason)
2741 struct samr_ChangePasswordUser3 r;
2742 bool ret = true;
2743 struct lsa_String server, account, account_bad;
2744 struct samr_CryptPassword nt_pass, lm_pass;
2745 struct samr_Password nt_verifier, lm_verifier;
2746 char *oldpass;
2747 struct dcerpc_binding_handle *b = p->binding_handle;
2748 uint8_t old_nt_hash[16] = { 0 }, new_nt_hash[16];
2749 uint8_t old_lm_hash[16], new_lm_hash[16];
2750 NTTIME t;
2751 struct samr_DomInfo1 *dominfo = NULL;
2752 struct userPwdChangeFailureInformation *reject = NULL;
2753 DATA_BLOB old_nt_hash_blob = data_blob_const(old_nt_hash, 16);
2754 NTSTATUS status;
2756 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2758 if (newpass == NULL) {
2759 do {
2760 if (policy_min_pw_len == 0) {
2761 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2762 } else {
2763 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2765 } while (check_password_quality(newpass) == false);
2766 } else {
2767 torture_comment(tctx, "Using password '%s'\n", newpass);
2770 torture_assert(tctx, *password != NULL,
2771 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2773 oldpass = *password;
2774 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2775 init_lsa_String(&account, account_string);
2777 E_md4hash(oldpass, old_nt_hash);
2778 E_md4hash(newpass, new_nt_hash);
2780 E_deshash(oldpass, old_lm_hash);
2781 E_deshash(newpass, new_lm_hash);
2784 * The new plaintext password is encrypted using RC4 with the
2785 * old NT password hash (directly, with no confounder). The
2786 * password is at the end of the random padded buffer,
2787 * offering a little protection.
2789 * This is almost certainly wrong, it should be the old LM
2790 * hash, it was switched in an unrelated commit
2791 * 579c13da43d5b40ac6d6c1436399fbc1d8dfd054 in 2004.
2793 status = init_samr_CryptPassword(newpass,
2794 &old_nt_hash_blob,
2795 &lm_pass);
2796 torture_assert_ntstatus_ok(tctx,
2797 status,
2798 "init_samr_CryptPassword");
2801 * Now we prepare a DES cross-hash of the old LM and new NT
2802 * passwords to link the two buffers
2804 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2807 * The new plaintext password is also encrypted using RC4 with
2808 * the old NT password hash (directly, with no confounder).
2809 * The password is at the end of the random padded buffer,
2810 * offering a little protection.
2812 status = init_samr_CryptPassword(newpass,
2813 &old_nt_hash_blob,
2814 &nt_pass);
2815 torture_assert_ntstatus_ok(tctx,
2816 status,
2817 "init_samr_CryptPassword");
2820 * Another DES based cross-hash
2822 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2824 /* Break the verification */
2825 nt_verifier.hash[0]++;
2827 r.in.server = &server;
2828 r.in.account = &account;
2829 r.in.nt_password = &nt_pass;
2830 r.in.nt_verifier = &nt_verifier;
2831 r.in.lm_change = 1;
2832 r.in.lm_password = &lm_pass;
2833 r.in.lm_verifier = &lm_verifier;
2834 r.in.password3 = NULL;
2835 r.out.dominfo = &dominfo;
2836 r.out.reject = &reject;
2838 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2839 "ChangePasswordUser3 failed");
2840 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2841 __location__, __FUNCTION__,
2842 oldpass, newpass, nt_errstr(r.out.result));
2843 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2844 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2845 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2846 nt_errstr(r.out.result));
2847 ret = false;
2850 status = init_samr_CryptPassword(newpass,
2851 &old_nt_hash_blob,
2852 &lm_pass);
2853 torture_assert_ntstatus_ok(tctx,
2854 status,
2855 "init_samr_CryptPassword");
2857 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2859 /* Break the NT Hash */
2860 old_nt_hash[0]++;
2862 status = init_samr_CryptPassword(newpass,
2863 &old_nt_hash_blob,
2864 &nt_pass);
2865 torture_assert_ntstatus_ok(tctx,
2866 status,
2867 "init_samr_CryptPassword");
2869 /* Unbreak it again */
2870 old_nt_hash[0]--;
2872 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2874 r.in.server = &server;
2875 r.in.account = &account;
2876 r.in.nt_password = &nt_pass;
2877 r.in.nt_verifier = &nt_verifier;
2878 r.in.lm_change = 1;
2879 r.in.lm_password = &lm_pass;
2880 r.in.lm_verifier = &lm_verifier;
2881 r.in.password3 = NULL;
2882 r.out.dominfo = &dominfo;
2883 r.out.reject = &reject;
2885 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2886 "ChangePasswordUser3 failed");
2887 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2888 __location__, __FUNCTION__,
2889 oldpass, newpass, nt_errstr(r.out.result));
2890 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2891 (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2892 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrypted password - %s\n",
2893 nt_errstr(r.out.result));
2894 ret = false;
2897 /* This shouldn't be a valid name */
2898 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2900 r.in.account = &account_bad;
2901 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2902 "ChangePasswordUser3 failed");
2903 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2904 __location__, __FUNCTION__,
2905 oldpass, newpass, nt_errstr(r.out.result));
2906 if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2907 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2908 nt_errstr(r.out.result));
2909 ret = false;
2912 E_md4hash(oldpass, old_nt_hash);
2913 E_md4hash(newpass, new_nt_hash);
2915 E_deshash(oldpass, old_lm_hash);
2916 E_deshash(newpass, new_lm_hash);
2918 status = init_samr_CryptPassword(newpass,
2919 &old_nt_hash_blob,
2920 &lm_pass);
2921 torture_assert_ntstatus_ok(tctx,
2922 status,
2923 "init_samr_CryptPassword");
2925 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2927 status = init_samr_CryptPassword(newpass,
2928 &old_nt_hash_blob,
2929 &nt_pass);
2930 torture_assert_ntstatus_ok(tctx,
2931 status,
2932 "init_samr_CryptPassword");
2934 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2936 r.in.server = &server;
2937 r.in.account = &account;
2938 r.in.nt_password = &nt_pass;
2939 r.in.nt_verifier = &nt_verifier;
2940 r.in.lm_change = 1;
2941 r.in.lm_password = &lm_pass;
2942 r.in.lm_verifier = &lm_verifier;
2943 r.in.password3 = NULL;
2944 r.out.dominfo = &dominfo;
2945 r.out.reject = &reject;
2947 unix_to_nt_time(&t, time(NULL));
2949 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2950 "ChangePasswordUser3 failed");
2951 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2952 __location__, __FUNCTION__,
2953 oldpass, newpass, nt_errstr(r.out.result));
2955 torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2956 "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2957 __location__,
2958 (dominfo == NULL)? "NULL" : "present",
2959 reject ? "true" : "false",
2960 handle_reject_reason ? "true" : "false",
2961 null_nttime(last_password_change) ? "null" : "not null",
2962 dominfo ? (long long)dominfo->min_password_age : (long long)0);
2964 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2965 && dominfo
2966 && reject
2967 && handle_reject_reason
2968 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2969 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2971 if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2972 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2973 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2974 return false;
2978 /* We tested the order of precedence which is as follows:
2980 * pwd min_age
2981 * pwd length
2982 * pwd complexity
2983 * pwd history
2985 Guenther */
2987 if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
2988 (last_password_change - dominfo->min_password_age > t)) {
2990 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2991 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2992 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2993 return false;
2996 } else if ((dominfo->min_password_length > 0) &&
2997 (strlen(newpass) < dominfo->min_password_length)) {
2999 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
3000 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
3001 SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
3002 return false;
3005 } else if ((dominfo->password_history_length > 0) &&
3006 strequal(oldpass, newpass)) {
3008 if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
3009 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
3010 SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
3011 return false;
3013 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
3015 if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
3016 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
3017 SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
3018 return false;
3023 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
3024 /* retry with adjusted size */
3025 return test_ChangePasswordUser3(p, tctx, account_string,
3026 dominfo->min_password_length,
3027 password, NULL, 0, false);
3031 } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
3032 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
3033 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
3034 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
3035 return false;
3037 /* Perhaps the server has a 'min password age' set? */
3039 } else {
3040 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
3042 *password = talloc_strdup(tctx, newpass);
3045 return ret;
3048 bool test_ChangePasswordUser4(struct dcerpc_pipe *p,
3049 struct torture_context *tctx,
3050 const char *account_string,
3051 int policy_min_pw_len,
3052 char **password,
3053 const char *newpassword)
3055 struct dcerpc_binding_handle *b = p->binding_handle;
3056 struct samr_ChangePasswordUser4 r;
3057 const char *oldpassword = *password;
3058 char *srv_str = NULL;
3059 struct lsa_String server;
3060 struct lsa_String account;
3061 uint8_t old_nt_key_data[16] = {0};
3062 gnutls_datum_t old_nt_key = {
3063 .data = old_nt_key_data,
3064 .size = sizeof(old_nt_key),
3066 uint8_t cek_data[16] = {0};
3067 DATA_BLOB cek = {
3068 .data = cek_data,
3069 .length = sizeof(cek_data),
3071 uint8_t pw_data[514] = {0};
3072 DATA_BLOB plaintext = {
3073 .data = pw_data,
3074 .length = sizeof(pw_data),
3076 DATA_BLOB ciphertext = data_blob_null;
3077 struct samr_EncryptedPasswordAES pwd_buf = {.cipher_len = 0};
3078 DATA_BLOB iv = {
3079 .data = pwd_buf.salt,
3080 .length = sizeof(pwd_buf.salt),
3082 gnutls_datum_t iv_datum = {
3083 .data = iv.data,
3084 .size = iv.length,
3086 uint64_t pbkdf2_iterations = generate_random_u64_range(5000, 1000000);
3087 NTSTATUS status;
3088 bool ok;
3089 int rc;
3091 torture_comment(tctx, "Testing ChangePasswordUser4\n");
3093 if (newpassword == NULL) {
3094 do {
3095 if (policy_min_pw_len == 0) {
3096 newpassword =
3097 samr_rand_pass(tctx, policy_min_pw_len);
3098 } else {
3099 newpassword = samr_rand_pass_fixed_len(
3100 tctx,
3101 policy_min_pw_len);
3103 } while (check_password_quality(newpassword) == false);
3104 } else {
3105 torture_comment(tctx, "Using password '%s'\n", newpassword);
3108 torture_assert_not_null(tctx,
3109 *password,
3110 "Failing ChangePasswordUser4 as old password "
3111 "was NULL. Previous test failed?");
3113 srv_str = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3114 torture_assert_not_null(tctx, srv_str, "srvstr is NULL");
3115 init_lsa_String(&server, srv_str);
3117 init_lsa_String(&account, account_string);
3119 E_md4hash(oldpassword, old_nt_key_data);
3121 generate_nonce_buffer(iv.data, iv.length);
3123 rc = gnutls_pbkdf2(GNUTLS_MAC_SHA512,
3124 &old_nt_key,
3125 &iv_datum,
3126 pbkdf2_iterations,
3127 cek.data,
3128 cek.length);
3129 torture_assert_int_equal(tctx, rc, 0, "gnutls_pbkdf2 failed");
3131 ok = encode_pwd_buffer514_from_str(pw_data, newpassword, STR_UNICODE);
3132 torture_assert(tctx, ok, "encode_aes_pw_buffer failed");
3134 status = samba_gnutls_aead_aes_256_cbc_hmac_sha512_encrypt(
3135 tctx,
3136 &plaintext,
3137 &cek,
3138 &samr_aes256_enc_key_salt,
3139 &samr_aes256_mac_key_salt,
3140 &iv,
3141 &ciphertext,
3142 pwd_buf.auth_data);
3143 torture_assert_ntstatus_ok(
3144 tctx,
3145 status,
3146 "samba_gnutls_aead_aes_256_cbc_hmac_sha512_encrypt failed");
3148 pwd_buf.cipher_len = ciphertext.length;
3149 pwd_buf.cipher = ciphertext.data;
3150 pwd_buf.PBKDF2Iterations = pbkdf2_iterations;
3152 r.in.server = &server;
3153 r.in.account = &account;
3154 r.in.password = &pwd_buf;
3156 status = dcerpc_samr_ChangePasswordUser4_r(b, tctx, &r);
3157 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser4 failed");
3159 *password = talloc_strdup(tctx, newpassword);
3160 return true;
3163 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
3164 const char *account_string,
3165 struct policy_handle *handle,
3166 char **password)
3168 NTSTATUS status;
3169 struct samr_ChangePasswordUser3 r;
3170 struct samr_SetUserInfo s;
3171 union samr_UserInfo u;
3172 DATA_BLOB session_key;
3174 bool ret = true;
3175 struct lsa_String server, account;
3176 struct samr_CryptPassword nt_pass;
3177 struct samr_Password nt_verifier;
3178 DATA_BLOB new_random_pass;
3179 char *newpass;
3180 char *oldpass;
3181 struct dcerpc_binding_handle *b = p->binding_handle;
3182 uint8_t old_nt_hash[16] = { 0 }, new_nt_hash[16];
3183 DATA_BLOB old_nt_hash_blob
3184 = data_blob_const(old_nt_hash,
3185 sizeof(old_nt_hash));
3186 NTTIME t;
3187 struct samr_DomInfo1 *dominfo = NULL;
3188 struct userPwdChangeFailureInformation *reject = NULL;
3189 gnutls_cipher_hd_t cipher_hnd = NULL;
3190 uint8_t _confounder[16] = {0};
3191 DATA_BLOB confounder
3192 = data_blob_const(_confounder,
3193 sizeof(_confounder));
3194 DATA_BLOB pw_data;
3195 gnutls_datum_t old_nt_key = {
3196 .data = old_nt_hash,
3197 .size = sizeof(old_nt_hash),
3200 new_random_pass = samr_very_rand_pass(tctx, 128);
3202 torture_assert(tctx, *password != NULL,
3203 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
3205 oldpass = *password;
3206 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3207 init_lsa_String(&account, account_string);
3209 s.in.user_handle = handle;
3210 s.in.info = &u;
3211 s.in.level = 25;
3213 ZERO_STRUCT(u);
3215 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
3217 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
3219 pw_data = data_blob_const(u.info25.password.data, 516);
3221 status = dcerpc_binding_handle_transport_session_key(b, tctx, &session_key);
3222 if (!NT_STATUS_IS_OK(status)) {
3223 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u - no session key - %s\n",
3224 s.in.level, nt_errstr(status));
3225 return false;
3228 generate_random_buffer(_confounder,
3229 sizeof(_confounder));
3231 samba_gnutls_arcfour_confounded_md5(&confounder,
3232 &session_key,
3233 &pw_data,
3234 SAMBA_GNUTLS_ENCRYPT);
3236 memcpy(&u.info25.password.data[516], _confounder, sizeof(_confounder));
3238 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
3240 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
3241 "SetUserInfo failed");
3242 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
3243 __location__, __FUNCTION__,
3244 oldpass, "RANDOM", nt_errstr(s.out.result));
3245 if (!NT_STATUS_IS_OK(s.out.result)) {
3246 torture_result(tctx, TORTURE_FAIL, "SetUserInfo level %u failed - %s\n",
3247 s.in.level, nt_errstr(s.out.result));
3248 ret = false;
3251 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
3253 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
3255 new_random_pass = samr_very_rand_pass(tctx, 128);
3257 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
3259 set_pw_in_buffer(nt_pass.data, &new_random_pass);
3261 gnutls_cipher_init(&cipher_hnd,
3262 GNUTLS_CIPHER_ARCFOUR_128,
3263 &old_nt_key,
3264 NULL);
3265 gnutls_cipher_encrypt(cipher_hnd,
3266 nt_pass.data,
3267 516);
3268 gnutls_cipher_deinit(cipher_hnd);
3270 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
3272 r.in.server = &server;
3273 r.in.account = &account;
3274 r.in.nt_password = &nt_pass;
3275 r.in.nt_verifier = &nt_verifier;
3276 r.in.lm_change = 0;
3277 r.in.lm_password = NULL;
3278 r.in.lm_verifier = NULL;
3279 r.in.password3 = NULL;
3280 r.out.dominfo = &dominfo;
3281 r.out.reject = &reject;
3283 unix_to_nt_time(&t, time(NULL));
3285 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
3286 "ChangePasswordUser3 failed");
3287 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
3288 __location__, __FUNCTION__,
3289 oldpass, "RANDOM", nt_errstr(r.out.result));
3291 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
3292 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
3293 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
3294 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
3295 return false;
3297 /* Perhaps the server has a 'min password age' set? */
3299 } else if (!NT_STATUS_IS_OK(r.out.result)) {
3300 torture_result(tctx, TORTURE_FAIL, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
3301 ret = false;
3304 newpass = samr_rand_pass(tctx, 128);
3306 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
3308 E_md4hash(newpass, new_nt_hash);
3310 status = init_samr_CryptPassword(newpass,
3311 &old_nt_hash_blob,
3312 &nt_pass);
3313 torture_assert_ntstatus_ok(tctx,
3314 status,
3315 "init_samr_CryptPassword failed");
3317 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
3319 r.in.server = &server;
3320 r.in.account = &account;
3321 r.in.nt_password = &nt_pass;
3322 r.in.nt_verifier = &nt_verifier;
3323 r.in.lm_change = 0;
3324 r.in.lm_password = NULL;
3325 r.in.lm_verifier = NULL;
3326 r.in.password3 = NULL;
3327 r.out.dominfo = &dominfo;
3328 r.out.reject = &reject;
3330 unix_to_nt_time(&t, time(NULL));
3332 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
3333 "ChangePasswordUser3 failed");
3334 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
3335 __location__, __FUNCTION__,
3336 oldpass, newpass, nt_errstr(r.out.result));
3338 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
3339 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
3340 torture_result(tctx, TORTURE_FAIL, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
3341 SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
3342 return false;
3344 /* Perhaps the server has a 'min password age' set? */
3346 } else {
3347 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
3348 *password = talloc_strdup(tctx, newpass);
3351 return ret;
3355 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
3356 struct torture_context *tctx,
3357 struct policy_handle *alias_handle)
3359 struct samr_GetMembersInAlias r;
3360 struct lsa_SidArray sids;
3362 torture_comment(tctx, "Testing GetMembersInAlias\n");
3364 r.in.alias_handle = alias_handle;
3365 r.out.sids = &sids;
3367 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
3368 "GetMembersInAlias failed");
3369 torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
3371 return true;
3374 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
3375 struct torture_context *tctx,
3376 struct policy_handle *alias_handle,
3377 const struct dom_sid *domain_sid)
3379 struct samr_AddAliasMember r;
3380 struct samr_DeleteAliasMember d;
3381 struct dom_sid *sid;
3383 sid = dom_sid_add_rid(tctx, domain_sid, 512);
3385 torture_comment(tctx, "Testing AddAliasMember\n");
3386 r.in.alias_handle = alias_handle;
3387 r.in.sid = sid;
3389 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
3390 "AddAliasMember failed");
3391 torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
3393 d.in.alias_handle = alias_handle;
3394 d.in.sid = sid;
3396 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
3397 "DeleteAliasMember failed");
3398 torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
3400 return true;
3403 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
3404 struct torture_context *tctx,
3405 struct policy_handle *alias_handle)
3407 struct samr_AddMultipleMembersToAlias a;
3408 struct samr_RemoveMultipleMembersFromAlias r;
3409 struct lsa_SidArray sids;
3411 torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
3412 a.in.alias_handle = alias_handle;
3413 a.in.sids = &sids;
3415 sids.num_sids = 3;
3416 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
3418 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
3419 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
3420 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
3422 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
3423 "AddMultipleMembersToAlias failed");
3424 torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
3427 torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
3428 r.in.alias_handle = alias_handle;
3429 r.in.sids = &sids;
3431 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
3432 "RemoveMultipleMembersFromAlias failed");
3433 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
3435 /* strange! removing twice doesn't give any error */
3436 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
3437 "RemoveMultipleMembersFromAlias failed");
3438 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
3440 /* but removing an alias that isn't there does */
3441 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
3443 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
3444 "RemoveMultipleMembersFromAlias failed");
3445 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
3447 return true;
3450 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
3451 struct torture_context *tctx,
3452 struct policy_handle *domain_handle)
3454 struct samr_GetAliasMembership r;
3455 struct lsa_SidArray sids;
3456 struct samr_Ids rids;
3458 torture_comment(tctx, "Testing GetAliasMembership\n");
3460 r.in.domain_handle = domain_handle;
3461 r.in.sids = &sids;
3462 r.out.rids = &rids;
3464 sids.num_sids = 0;
3465 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
3467 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
3468 "GetAliasMembership failed");
3469 torture_assert_ntstatus_ok(tctx, r.out.result,
3470 "samr_GetAliasMembership failed");
3472 torture_assert_int_equal(tctx, sids.num_sids, rids.count,
3473 "protocol misbehaviour");
3475 sids.num_sids = 1;
3476 sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
3477 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
3479 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
3480 "samr_GetAliasMembership failed");
3481 torture_assert_ntstatus_ok(tctx, r.out.result,
3482 "samr_GetAliasMembership failed");
3484 #if 0
3485 /* only true for w2k8 it seems
3486 * win7, xp, w2k3 will return a 0 length array pointer */
3488 if (rids.ids && (rids.count == 0)) {
3489 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
3491 #endif
3492 if (!rids.ids && rids.count) {
3493 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
3496 return true;
3499 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
3500 struct torture_context *tctx,
3501 struct policy_handle *user_handle)
3503 struct samr_TestPrivateFunctionsUser r;
3505 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
3507 r.in.user_handle = user_handle;
3509 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
3510 "TestPrivateFunctionsUser failed");
3511 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
3513 return true;
3516 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
3517 struct torture_context *tctx,
3518 struct policy_handle *handle,
3519 bool use_info2,
3520 NTTIME *pwdlastset)
3522 NTSTATUS status;
3523 uint16_t levels[] = { /* 3, */ 5, 21 };
3524 int i;
3525 /* NTTIME pwdlastset3 = 0; */
3526 NTTIME pwdlastset5 = 0;
3527 NTTIME pwdlastset21 = 0;
3529 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
3530 use_info2 ? "2":"");
3532 for (i=0; i<ARRAY_SIZE(levels); i++) {
3534 struct samr_QueryUserInfo r;
3535 struct samr_QueryUserInfo2 r2;
3536 union samr_UserInfo *info;
3538 if (use_info2) {
3539 r2.in.user_handle = handle;
3540 r2.in.level = levels[i];
3541 r2.out.info = &info;
3542 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
3543 "QueryUserInfo2 failed");
3544 status = r2.out.result;
3546 } else {
3547 r.in.user_handle = handle;
3548 r.in.level = levels[i];
3549 r.out.info = &info;
3550 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3551 "QueryUserInfo failed");
3552 status = r.out.result;
3555 if (!NT_STATUS_IS_OK(status) &&
3556 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
3557 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo%s level %u failed - %s\n",
3558 use_info2 ? "2":"", levels[i], nt_errstr(status));
3559 return false;
3562 switch (levels[i]) {
3563 case 3:
3564 /* pwdlastset3 = info->info3.last_password_change; */
3565 break;
3566 case 5:
3567 pwdlastset5 = info->info5.last_password_change;
3568 break;
3569 case 21:
3570 pwdlastset21 = info->info21.last_password_change;
3571 break;
3572 default:
3573 return false;
3576 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
3577 "pwdlastset mixup"); */
3578 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
3579 "pwdlastset mixup");
3581 *pwdlastset = pwdlastset21;
3583 torture_comment(tctx, "(pwdlastset: %llu)\n",
3584 (unsigned long long) *pwdlastset);
3586 return true;
3589 static bool test_SamLogon(struct torture_context *tctx,
3590 struct dcerpc_pipe *p,
3591 struct cli_credentials *machine_credentials,
3592 struct cli_credentials *test_credentials,
3593 NTSTATUS expected_result,
3594 bool interactive)
3596 NTSTATUS status;
3597 struct netr_LogonSamLogonEx r;
3598 union netr_LogonLevel logon;
3599 union netr_Validation validation;
3600 uint8_t authoritative;
3601 struct netr_IdentityInfo identity = {};
3602 struct netr_NetworkInfo ninfo;
3603 struct netr_PasswordInfo pinfo;
3604 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
3605 int flags = CLI_CRED_NTLM_AUTH;
3606 uint32_t samlogon_flags = 0;
3607 struct netlogon_creds_CredentialState *creds;
3608 struct netr_Authenticator a;
3609 struct dcerpc_binding_handle *b = p->binding_handle;
3610 enum dcerpc_AuthType auth_type = DCERPC_AUTH_TYPE_NONE;
3611 enum dcerpc_AuthLevel auth_level = DCERPC_AUTH_LEVEL_NONE;
3613 torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), "");
3615 if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
3616 flags |= CLI_CRED_LANMAN_AUTH;
3619 if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
3620 flags |= CLI_CRED_NTLMv2_AUTH;
3623 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
3624 &identity.account_name.string,
3625 &identity.domain_name.string);
3627 identity.parameter_control =
3628 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
3629 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
3630 identity.logon_id = 0;
3631 identity.workstation.string = cli_credentials_get_workstation(test_credentials);
3633 if (interactive) {
3634 netlogon_creds_client_authenticator(creds, &a);
3636 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
3637 ZERO_STRUCT(pinfo.lmpassword.hash);
3639 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
3641 pinfo.identity_info = identity;
3642 logon.password = &pinfo;
3644 r.in.logon_level = NetlogonInteractiveInformation;
3645 } else {
3646 generate_random_buffer(ninfo.challenge,
3647 sizeof(ninfo.challenge));
3648 chal = data_blob_const(ninfo.challenge,
3649 sizeof(ninfo.challenge));
3651 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3652 cli_credentials_get_domain(test_credentials));
3654 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3655 &flags,
3656 chal,
3657 NULL, /* server_timestamp */
3658 names_blob,
3659 &lm_resp, &nt_resp,
3660 NULL, NULL);
3661 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3663 ninfo.lm.data = lm_resp.data;
3664 ninfo.lm.length = lm_resp.length;
3666 ninfo.nt.data = nt_resp.data;
3667 ninfo.nt.length = nt_resp.length;
3669 ninfo.identity_info = identity;
3670 logon.network = &ninfo;
3672 r.in.logon_level = NetlogonNetworkInformation;
3675 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3676 r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3677 r.in.logon = &logon;
3678 r.in.flags = &samlogon_flags;
3679 r.out.flags = &samlogon_flags;
3680 r.out.validation = &validation;
3681 r.out.authoritative = &authoritative;
3683 torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3685 r.in.validation_level = 6;
3687 dcerpc_binding_handle_auth_info(b, &auth_type, &auth_level);
3688 status = netlogon_creds_encrypt_samlogon_logon(creds,
3689 r.in.logon_level,
3690 r.in.logon,
3691 auth_type,
3692 auth_level);
3693 torture_assert_ntstatus_ok(tctx, status, "encrypt_samlogon_logon");
3695 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3696 "netr_LogonSamLogonEx failed");
3697 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3698 r.in.validation_level = 3;
3699 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3700 "netr_LogonSamLogonEx failed");
3702 if (!NT_STATUS_IS_OK(r.out.result)) {
3703 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3704 return true;
3705 } else {
3706 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3709 return true;
3712 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3713 struct dcerpc_pipe *p,
3714 struct cli_credentials *machine_creds,
3715 const char *acct_name,
3716 const char *password,
3717 NTSTATUS expected_samlogon_result,
3718 bool interactive)
3720 bool ret = true;
3721 struct cli_credentials *test_credentials;
3723 test_credentials = cli_credentials_init(tctx);
3725 cli_credentials_set_workstation(test_credentials,
3726 cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3727 cli_credentials_set_domain(test_credentials,
3728 cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3729 cli_credentials_set_username(test_credentials,
3730 acct_name, CRED_SPECIFIED);
3731 cli_credentials_set_password(test_credentials,
3732 password, CRED_SPECIFIED);
3734 torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3735 interactive ? "interactive" : "network", acct_name, password);
3737 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
3738 expected_samlogon_result, interactive)) {
3739 torture_result(tctx, TORTURE_FAIL, "new password did not work\n");
3740 ret = false;
3743 return ret;
3746 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3747 struct dcerpc_pipe *np,
3748 struct torture_context *tctx,
3749 struct policy_handle *handle,
3750 uint16_t level,
3751 uint32_t fields_present,
3752 uint8_t password_expired,
3753 bool *matched_expected_error,
3754 bool use_setinfo2,
3755 const char *acct_name,
3756 char **password,
3757 struct cli_credentials *machine_creds,
3758 bool use_queryinfo2,
3759 NTTIME *pwdlastset,
3760 NTSTATUS expected_samlogon_result)
3762 const char *fields = NULL;
3763 bool ret = true;
3764 struct dcerpc_binding_handle *b = p->binding_handle;
3766 switch (level) {
3767 case 21:
3768 case 23:
3769 case 25:
3770 case 32:
3771 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3772 fields_present);
3773 break;
3774 default:
3775 break;
3778 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3779 "(password_expired: %d) %s\n",
3780 use_setinfo2 ? "2":"", level, password_expired,
3781 fields ? fields : "");
3783 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3784 fields_present,
3785 password,
3786 password_expired,
3787 use_setinfo2,
3788 matched_expected_error)) {
3789 ret = false;
3792 if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3793 use_queryinfo2,
3794 pwdlastset)) {
3795 ret = false;
3798 if (*matched_expected_error == true) {
3799 return ret;
3802 if (!test_SamLogon_with_creds(tctx, np,
3803 machine_creds,
3804 acct_name,
3805 *password,
3806 expected_samlogon_result,
3807 false)) {
3808 ret = false;
3811 return ret;
3814 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3815 struct cli_credentials *credentials,
3816 struct dcerpc_pipe **p)
3818 struct dcerpc_binding *b;
3819 NTSTATUS status;
3821 torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3822 "failed to get rpc binding");
3824 /* We have to use schannel, otherwise the SamLogonEx fails
3825 * with INTERNAL_ERROR */
3827 status = dcerpc_binding_set_flags(b,
3828 DCERPC_SCHANNEL |
3829 DCERPC_SIGN | DCERPC_SEAL |
3830 DCERPC_SCHANNEL_AUTO,
3831 DCERPC_AUTH_OPTIONS);
3832 torture_assert_ntstatus_ok(tctx, status, "set flags");
3834 torture_assert_ntstatus_ok(tctx,
3835 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3836 credentials, tctx->ev, tctx->lp_ctx),
3837 "failed to bind to netlogon");
3839 return true;
3842 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3843 struct torture_context *tctx,
3844 uint32_t acct_flags,
3845 const char *acct_name,
3846 struct policy_handle *handle,
3847 char **password,
3848 struct cli_credentials *machine_credentials)
3850 int s = 0, q = 0, f = 0, l = 0, z = 0;
3851 bool ret = true;
3852 int delay = 50000;
3853 bool set_levels[] = { false, true };
3854 bool query_levels[] = { false, true };
3855 uint32_t levels[] = { 18, 21, 26, 23, 24, 25, 31 }; /* Second half only used when TEST_ALL_LEVELS defined */
3856 uint32_t nonzeros[] = { 1, 24 };
3857 uint32_t fields_present[] = {
3859 SAMR_FIELD_EXPIRED_FLAG,
3860 SAMR_FIELD_LAST_PWD_CHANGE,
3861 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3862 SAMR_FIELD_COMMENT,
3863 SAMR_FIELD_NT_PASSWORD_PRESENT,
3864 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3865 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3866 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3867 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3868 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3869 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3871 struct dcerpc_pipe *np = NULL;
3873 if (torture_setting_bool(tctx, "samba3", false) ||
3874 torture_setting_bool(tctx, "samba4", false)) {
3875 delay = 999999;
3876 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3877 delay);
3880 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3882 /* set to 1 to enable testing for all possible opcode
3883 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3884 combinations */
3885 #if 0
3886 #define TEST_ALL_LEVELS 1
3887 #define TEST_SET_LEVELS 1
3888 #define TEST_QUERY_LEVELS 1
3889 #endif
3890 #ifdef TEST_ALL_LEVELS
3891 for (l=0; l<ARRAY_SIZE(levels); l++) {
3892 #else
3893 for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3894 #endif
3895 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3896 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3897 #ifdef TEST_SET_LEVELS
3898 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3899 #endif
3900 #ifdef TEST_QUERY_LEVELS
3901 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3902 #endif
3903 NTTIME pwdlastset_old = 0;
3904 NTTIME pwdlastset_new = 0;
3905 bool matched_expected_error = false;
3906 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3908 torture_comment(tctx, "------------------------------\n"
3909 "Testing pwdLastSet attribute for flags: 0x%08x "
3910 "(s: %d (l: %d), q: %d)\n",
3911 acct_flags, s, levels[l], q);
3913 switch (levels[l]) {
3914 case 21:
3915 case 23:
3916 case 25:
3917 case 32:
3918 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3919 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3920 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3922 break;
3926 /* set #1 */
3928 /* set a password and force password change (pwdlastset 0) by
3929 * setting the password expired flag to a non-0 value */
3931 if (!test_SetPassword_level(p, np, tctx, handle,
3932 levels[l],
3933 fields_present[f],
3934 nonzeros[z],
3935 &matched_expected_error,
3936 set_levels[s],
3937 acct_name,
3938 password,
3939 machine_credentials,
3940 query_levels[q],
3941 &pwdlastset_new,
3942 expected_samlogon_result)) {
3943 ret = false;
3946 if (matched_expected_error == true) {
3947 /* skipping on expected failure */
3948 continue;
3951 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3952 * set without the SAMR_FIELD_EXPIRED_FLAG */
3954 switch (levels[l]) {
3955 case 21:
3956 case 23:
3957 case 25:
3958 case 32:
3959 if ((pwdlastset_new != 0) &&
3960 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3961 torture_comment(tctx, "not considering a non-0 "
3962 "pwdLastSet as a an error as the "
3963 "SAMR_FIELD_EXPIRED_FLAG has not "
3964 "been set\n");
3965 break;
3967 break;
3968 default:
3969 if (pwdlastset_new != 0) {
3970 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
3971 "expected pwdLastSet 0 but got %llu\n",
3972 (unsigned long long) pwdlastset_old);
3973 ret = false;
3975 break;
3978 switch (levels[l]) {
3979 case 21:
3980 case 23:
3981 case 25:
3982 case 32:
3983 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3984 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3985 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3986 (pwdlastset_old >= pwdlastset_new)) {
3987 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
3988 ret = false;
3990 break;
3993 pwdlastset_old = pwdlastset_new;
3995 usleep(delay);
3997 /* set #2 */
3999 /* set a password, pwdlastset needs to get updated (increased
4000 * value), password_expired value used here is 0 */
4002 if (!test_SetPassword_level(p, np, tctx, handle,
4003 levels[l],
4004 fields_present[f],
4006 &matched_expected_error,
4007 set_levels[s],
4008 acct_name,
4009 password,
4010 machine_credentials,
4011 query_levels[q],
4012 &pwdlastset_new,
4013 expected_samlogon_result)) {
4014 ret = false;
4017 /* when a password has been changed, pwdlastset must not be 0 afterwards
4018 * and must be larger then the old value */
4020 switch (levels[l]) {
4021 case 21:
4022 case 23:
4023 case 25:
4024 case 32:
4025 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
4026 * password has been changed, old and new pwdlastset
4027 * need to be the same value */
4029 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
4030 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
4031 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
4033 torture_assert_int_equal(tctx, pwdlastset_old,
4034 pwdlastset_new, "pwdlastset must be equal");
4035 break;
4037 break;
4038 default:
4039 if (pwdlastset_old >= pwdlastset_new) {
4040 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
4041 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
4042 (unsigned long long) pwdlastset_old,
4043 (unsigned long long) pwdlastset_new);
4044 ret = false;
4046 if (pwdlastset_new == 0) {
4047 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
4048 "expected non-0 pwdlastset, got: %llu\n",
4049 (unsigned long long) pwdlastset_new);
4050 ret = false;
4052 break;
4055 switch (levels[l]) {
4056 case 21:
4057 case 23:
4058 case 25:
4059 case 32:
4060 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
4061 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
4062 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
4063 (pwdlastset_old >= pwdlastset_new)) {
4064 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
4065 ret = false;
4067 break;
4070 pwdlastset_old = pwdlastset_new;
4072 usleep(delay);
4074 /* set #2b */
4076 /* set a password, pwdlastset needs to get updated (increased
4077 * value), password_expired value used here is 0 */
4079 if (!test_SetPassword_level(p, np, tctx, handle,
4080 levels[l],
4081 fields_present[f],
4083 &matched_expected_error,
4084 set_levels[s],
4085 acct_name,
4086 password,
4087 machine_credentials,
4088 query_levels[q],
4089 &pwdlastset_new,
4090 expected_samlogon_result)) {
4091 ret = false;
4094 /* when a password has been changed, pwdlastset must not be 0 afterwards
4095 * and must be larger then the old value */
4097 switch (levels[l]) {
4098 case 21:
4099 case 23:
4100 case 25:
4101 case 32:
4102 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
4103 * password has been changed, old and new pwdlastset
4104 * need to be the same value */
4106 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
4107 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
4108 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
4110 torture_assert_int_equal(tctx, pwdlastset_old,
4111 pwdlastset_new, "pwdlastset must be equal");
4112 break;
4114 break;
4115 default:
4116 if (pwdlastset_old >= pwdlastset_new) {
4117 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
4118 "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
4119 (unsigned long long) pwdlastset_old,
4120 (unsigned long long) pwdlastset_new);
4121 ret = false;
4123 if (pwdlastset_new == 0) {
4124 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
4125 "expected non-0 pwdlastset, got: %llu\n",
4126 (unsigned long long) pwdlastset_new);
4127 ret = false;
4129 break;
4132 switch (levels[l]) {
4133 case 21:
4134 case 23:
4135 case 25:
4136 case 32:
4137 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
4138 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
4139 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
4140 (pwdlastset_old >= pwdlastset_new)) {
4141 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
4142 ret = false;
4144 break;
4147 pwdlastset_old = pwdlastset_new;
4149 usleep(delay);
4151 /* set #3 */
4153 /* set a password and force password change (pwdlastset 0) by
4154 * setting the password expired flag to a non-0 value */
4156 if (!test_SetPassword_level(p, np, tctx, handle,
4157 levels[l],
4158 fields_present[f],
4159 nonzeros[z],
4160 &matched_expected_error,
4161 set_levels[s],
4162 acct_name,
4163 password,
4164 machine_credentials,
4165 query_levels[q],
4166 &pwdlastset_new,
4167 expected_samlogon_result)) {
4168 ret = false;
4171 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
4172 * set without the SAMR_FIELD_EXPIRED_FLAG */
4174 switch (levels[l]) {
4175 case 21:
4176 case 23:
4177 case 25:
4178 case 32:
4179 if ((pwdlastset_new != 0) &&
4180 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
4181 torture_comment(tctx, "not considering a non-0 "
4182 "pwdLastSet as a an error as the "
4183 "SAMR_FIELD_EXPIRED_FLAG has not "
4184 "been set\n");
4185 break;
4188 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
4189 * password has been changed, old and new pwdlastset
4190 * need to be the same value */
4192 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
4193 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
4194 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
4196 torture_assert_int_equal(tctx, pwdlastset_old,
4197 pwdlastset_new, "pwdlastset must be equal");
4198 break;
4200 break;
4201 default:
4202 if (pwdlastset_new != 0) {
4203 torture_result(tctx, TORTURE_FAIL, "pwdLastSet test failed: "
4204 "expected pwdLastSet 0, got %llu\n",
4205 (unsigned long long) pwdlastset_old);
4206 ret = false;
4208 break;
4211 switch (levels[l]) {
4212 case 21:
4213 case 23:
4214 case 25:
4215 case 32:
4216 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
4217 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
4218 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
4219 (pwdlastset_old >= pwdlastset_new)) {
4220 torture_result(tctx, TORTURE_FAIL, "pwdlastset not increasing\n");
4221 ret = false;
4223 break;
4226 /* if the level we are testing does not have a fields_present
4227 * field, skip all fields present tests by setting f to to
4228 * arraysize */
4229 switch (levels[l]) {
4230 case 18:
4231 case 24:
4232 case 26:
4233 case 31:
4234 f = ARRAY_SIZE(fields_present);
4235 break;
4238 #ifdef TEST_QUERY_LEVELS
4240 #endif
4241 #ifdef TEST_SET_LEVELS
4243 #endif
4244 } /* fields present */
4245 } /* nonzeros */
4246 } /* levels */
4248 #undef TEST_SET_LEVELS
4249 #undef TEST_QUERY_LEVELS
4251 talloc_free(np);
4253 return ret;
4256 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
4257 struct torture_context *tctx,
4258 struct policy_handle *handle,
4259 uint32_t *badpwdcount)
4261 union samr_UserInfo *info;
4262 struct samr_QueryUserInfo r;
4264 r.in.user_handle = handle;
4265 r.in.level = 3;
4266 r.out.info = &info;
4268 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4270 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4271 "failed to query userinfo");
4272 torture_assert_ntstatus_ok(tctx, r.out.result,
4273 "failed to query userinfo");
4275 *badpwdcount = info->info3.bad_password_count;
4277 torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
4279 return true;
4282 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
4283 struct torture_context *tctx,
4284 struct policy_handle *user_handle,
4285 uint32_t acct_flags)
4287 struct samr_SetUserInfo r;
4288 union samr_UserInfo user_info;
4290 torture_comment(tctx, "Testing SetUserInfo level 16\n");
4292 user_info.info16.acct_flags = acct_flags;
4294 r.in.user_handle = user_handle;
4295 r.in.level = 16;
4296 r.in.info = &user_info;
4298 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
4299 "failed to set account flags");
4300 torture_assert_ntstatus_ok(tctx, r.out.result,
4301 "failed to set account flags");
4303 return true;
4306 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
4307 struct torture_context *tctx,
4308 struct policy_handle *user_handle,
4309 uint32_t acct_flags,
4310 char **password)
4312 struct dcerpc_binding_handle *b = p->binding_handle;
4314 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
4315 "failed to set password");
4317 torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
4319 torture_assert(tctx,
4320 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4321 acct_flags & ~ACB_DISABLED),
4322 "failed to enable user");
4324 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
4325 "failed to set password");
4327 return true;
4330 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
4331 struct torture_context *tctx,
4332 struct policy_handle *domain_handle,
4333 enum samr_DomainInfoClass level,
4334 union samr_DomainInfo *info)
4336 struct samr_SetDomainInfo r;
4338 r.in.domain_handle = domain_handle;
4339 r.in.level = level;
4340 r.in.info = info;
4342 torture_assert_ntstatus_ok(tctx,
4343 dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
4344 "failed to set domain info");
4345 torture_assert_ntstatus_ok(tctx, r.out.result,
4346 "failed to set domain info");
4348 return true;
4351 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
4352 struct torture_context *tctx,
4353 struct policy_handle *domain_handle,
4354 enum samr_DomainInfoClass level,
4355 union samr_DomainInfo *info,
4356 NTSTATUS expected)
4358 struct samr_SetDomainInfo r;
4360 r.in.domain_handle = domain_handle;
4361 r.in.level = level;
4362 r.in.info = info;
4364 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
4365 "SetDomainInfo failed");
4366 torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
4368 return true;
4371 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
4372 struct torture_context *tctx,
4373 struct policy_handle *domain_handle,
4374 enum samr_DomainInfoClass level,
4375 union samr_DomainInfo **q_info)
4377 struct samr_QueryDomainInfo2 r;
4379 r.in.domain_handle = domain_handle;
4380 r.in.level = level;
4381 r.out.info = q_info;
4383 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
4384 "failed to query domain info");
4385 torture_assert_ntstatus_ok(tctx, r.out.result,
4386 "failed to query domain info");
4388 return true;
4391 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
4392 struct dcerpc_pipe *np,
4393 struct torture_context *tctx,
4394 uint32_t acct_flags,
4395 const char *acct_name,
4396 struct policy_handle *domain_handle,
4397 struct policy_handle *user_handle,
4398 char **password,
4399 struct cli_credentials *machine_credentials,
4400 const char *comment,
4401 bool disable,
4402 bool interactive,
4403 NTSTATUS expected_success_status,
4404 struct samr_DomInfo1 *info1,
4405 struct samr_DomInfo12 *info12)
4407 union samr_DomainInfo info;
4408 char **passwords;
4409 int i;
4410 uint32_t badpwdcount, tmp;
4411 uint32_t password_history_length = 12;
4412 uint32_t lockout_threshold = 15;
4413 uint32_t lockout_seconds = 5;
4414 uint64_t delta_time_factor = 10 * 1000 * 1000;
4415 struct dcerpc_binding_handle *b = p->binding_handle;
4417 if (torture_setting_bool(tctx, "samba3", false)) {
4418 lockout_seconds = 60;
4421 torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
4423 torture_assert(tctx, password_history_length < lockout_threshold,
4424 "password history length needs to be smaller than account lockout threshold for this test");
4427 /* set policies */
4429 info.info1 = *info1;
4430 info.info1.password_history_length = password_history_length;
4431 info.info1.min_password_age = 0;
4433 torture_assert(tctx,
4434 test_SetDomainInfo(b, tctx, domain_handle,
4435 DomainPasswordInformation, &info),
4436 "failed to set password history length and min passwd age");
4438 info.info12 = *info12;
4439 info.info12.lockout_threshold = lockout_threshold;
4441 /* set lockout duration of 5 seconds */
4442 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4443 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4445 torture_assert(tctx,
4446 test_SetDomainInfo(b, tctx, domain_handle,
4447 DomainLockoutInformation, &info),
4448 "failed to set lockout threshold");
4450 /* reset bad pwd count */
4452 torture_assert(tctx,
4453 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4456 /* enable or disable account */
4457 if (disable) {
4458 torture_assert(tctx,
4459 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4460 acct_flags | ACB_DISABLED),
4461 "failed to disable user");
4462 } else {
4463 torture_assert(tctx,
4464 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4465 acct_flags & ~ACB_DISABLED),
4466 "failed to enable user");
4470 /* setup password history */
4472 passwords = talloc_array(tctx, char *, password_history_length);
4474 for (i=0; i < password_history_length; i++) {
4476 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
4477 "failed to set password");
4478 passwords[i] = talloc_strdup(tctx, *password);
4480 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4481 acct_name, passwords[i],
4482 expected_success_status, interactive)) {
4483 torture_fail(tctx, "failed to auth with latest password");
4486 torture_assert(tctx,
4487 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4489 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4493 /* test with wrong password */
4495 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4496 acct_name, "random_crap",
4497 NT_STATUS_WRONG_PASSWORD, interactive)) {
4498 torture_fail(tctx, "succeeded to authenticate with wrong password");
4501 torture_assert(tctx,
4502 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4504 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4507 /* test with latest good password */
4509 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4510 passwords[password_history_length-1],
4511 expected_success_status, interactive)) {
4512 torture_fail(tctx, "succeeded to authenticate with wrong password");
4515 torture_assert(tctx,
4516 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4518 if (disable) {
4519 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4520 } else {
4521 /* only enabled accounts get the bad pwd count reset upon
4522 * successful logon */
4523 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4526 tmp = badpwdcount;
4529 /* test password history */
4531 for (i=0; i < password_history_length; i++) {
4533 torture_comment(tctx, "Testing bad password count behavior with "
4534 "password #%d of #%d\n", i, password_history_length);
4536 /* - network samlogon will succeed auth and not
4537 * increase badpwdcount for 2 last entries
4538 * - interactive samlogon only for the last one */
4540 if (i == password_history_length - 1 ||
4541 (i == password_history_length - 2 && !interactive)) {
4543 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4544 acct_name, passwords[i],
4545 expected_success_status, interactive)) {
4546 torture_fail(tctx, talloc_asprintf(tctx, "did not successfully to obtain %s for %s login with old password (#%d of #%d in history)",
4547 nt_errstr(expected_success_status),
4548 interactive ? "interactive" : "network", i, password_history_length));
4551 torture_assert(tctx,
4552 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4554 if (disable) {
4555 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
4556 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
4557 } else {
4558 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
4559 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4562 tmp = badpwdcount;
4564 continue;
4567 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4568 acct_name, passwords[i],
4569 NT_STATUS_WRONG_PASSWORD, interactive)) {
4570 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
4573 torture_assert(tctx,
4574 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4576 /* - network samlogon will fail auth but not increase
4577 * badpwdcount for 3rd last entry
4578 * - interactive samlogon for 3rd and 2nd last entry */
4580 if (i == password_history_length - 3 ||
4581 (i == password_history_length - 2 && interactive)) {
4582 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
4583 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
4584 } else {
4585 /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
4586 torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
4589 tmp = badpwdcount;
4592 return true;
4595 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
4596 struct torture_context *tctx,
4597 uint32_t acct_flags,
4598 const char *acct_name,
4599 struct policy_handle *domain_handle,
4600 struct policy_handle *user_handle,
4601 char **password,
4602 struct cli_credentials *machine_credentials)
4604 union samr_DomainInfo *q_info, s_info;
4605 struct samr_DomInfo1 info1, _info1;
4606 struct samr_DomInfo12 info12, _info12;
4607 bool ret = true;
4608 struct dcerpc_binding_handle *b = p->binding_handle;
4609 struct dcerpc_pipe *np;
4610 int i;
4612 struct {
4613 const char *comment;
4614 bool disabled;
4615 bool interactive;
4616 NTSTATUS expected_success_status;
4617 } creds[] = {
4619 .comment = "network logon (disabled account)",
4620 .disabled = true,
4621 .interactive = false,
4622 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4625 .comment = "network logon (enabled account)",
4626 .disabled = false,
4627 .interactive = false,
4628 .expected_success_status= NT_STATUS_OK
4631 .comment = "interactive logon (disabled account)",
4632 .disabled = true,
4633 .interactive = true,
4634 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4637 .comment = "interactive logon (enabled account)",
4638 .disabled = false,
4639 .interactive = true,
4640 .expected_success_status= NT_STATUS_OK
4644 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4646 /* backup old policies */
4648 torture_assert(tctx,
4649 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4650 DomainPasswordInformation, &q_info),
4651 "failed to query domain info level 1");
4653 info1 = q_info->info1;
4654 _info1 = info1;
4656 torture_assert(tctx,
4657 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4658 DomainLockoutInformation, &q_info),
4659 "failed to query domain info level 12");
4661 info12 = q_info->info12;
4662 _info12 = info12;
4664 /* run tests */
4666 for (i=0; i < ARRAY_SIZE(creds); i++) {
4668 /* skip trust tests for now */
4669 if (acct_flags & ACB_WSTRUST ||
4670 acct_flags & ACB_SVRTRUST ||
4671 acct_flags & ACB_DOMTRUST) {
4672 continue;
4675 if (!test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
4676 domain_handle, user_handle, password,
4677 machine_credentials,
4678 creds[i].comment,
4679 creds[i].disabled,
4680 creds[i].interactive,
4681 creds[i].expected_success_status,
4682 &_info1, &_info12)) {
4683 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
4684 ret = false;
4685 } else {
4686 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4690 /* restore policies */
4692 s_info.info1 = info1;
4694 torture_assert(tctx,
4695 test_SetDomainInfo(b, tctx, domain_handle,
4696 DomainPasswordInformation, &s_info),
4697 "failed to set password information");
4699 s_info.info12 = info12;
4701 torture_assert(tctx,
4702 test_SetDomainInfo(b, tctx, domain_handle,
4703 DomainLockoutInformation, &s_info),
4704 "failed to set lockout information");
4706 return ret;
4709 static bool test_QueryUserInfo_lockout(struct dcerpc_binding_handle *b,
4710 struct torture_context *tctx,
4711 struct policy_handle *domain_handle,
4712 const char *acct_name,
4713 uint16_t raw_bad_password_count,
4714 uint16_t effective_bad_password_count,
4715 uint32_t effective_acb_lockout)
4717 struct policy_handle user_handle;
4718 union samr_UserInfo *i;
4719 struct samr_QueryUserInfo r;
4721 NTSTATUS status = test_OpenUser_byname(b, tctx, domain_handle, acct_name, &user_handle);
4722 if (!NT_STATUS_IS_OK(status)) {
4723 return false;
4726 r.in.user_handle = &user_handle;
4727 r.in.level = 3;
4728 r.out.info = &i;
4729 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4730 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4731 "failed to query userinfo");
4732 torture_assert_ntstatus_ok(tctx, r.out.result,
4733 "failed to query userinfo");
4734 torture_comment(tctx, " (acct_flags: 0x%08x) (raw_bad_pwd_count: %u)\n",
4735 i->info3.acct_flags, i->info3.bad_password_count);
4736 torture_assert_int_equal(tctx, i->info3.bad_password_count,
4737 raw_bad_password_count,
4738 "raw badpwdcount");
4739 torture_assert_int_equal(tctx, i->info3.acct_flags & ACB_AUTOLOCK,
4740 effective_acb_lockout,
4741 "effective acb_lockout");
4742 TALLOC_FREE(i);
4744 r.in.user_handle = &user_handle;
4745 r.in.level = 5;
4746 r.out.info = &i;
4747 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4748 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4749 "failed to query userinfo");
4750 torture_assert_ntstatus_ok(tctx, r.out.result,
4751 "failed to query userinfo");
4752 torture_comment(tctx, " (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
4753 i->info5.acct_flags, i->info5.bad_password_count);
4754 torture_assert_int_equal(tctx, i->info5.bad_password_count,
4755 effective_bad_password_count,
4756 "effective badpwdcount");
4757 torture_assert_int_equal(tctx, i->info5.acct_flags & ACB_AUTOLOCK,
4758 effective_acb_lockout,
4759 "effective acb_lockout");
4760 TALLOC_FREE(i);
4762 r.in.user_handle = &user_handle;
4763 r.in.level = 16;
4764 r.out.info = &i;
4765 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4766 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4767 "failed to query userinfo");
4768 torture_assert_ntstatus_ok(tctx, r.out.result,
4769 "failed to query userinfo");
4770 torture_comment(tctx, " (acct_flags: 0x%08x)\n",
4771 i->info16.acct_flags);
4772 torture_assert_int_equal(tctx, i->info16.acct_flags & ACB_AUTOLOCK,
4773 effective_acb_lockout,
4774 "effective acb_lockout");
4775 TALLOC_FREE(i);
4777 r.in.user_handle = &user_handle;
4778 r.in.level = 21;
4779 r.out.info = &i;
4780 torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
4781 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
4782 "failed to query userinfo");
4783 torture_assert_ntstatus_ok(tctx, r.out.result,
4784 "failed to query userinfo");
4785 torture_comment(tctx, " (acct_flags: 0x%08x) (effective_bad_pwd_count: %u)\n",
4786 i->info21.acct_flags, i->info21.bad_password_count);
4787 torture_assert_int_equal(tctx, i->info21.bad_password_count,
4788 effective_bad_password_count,
4789 "effective badpwdcount");
4790 torture_assert_int_equal(tctx, i->info21.acct_flags & ACB_AUTOLOCK,
4791 effective_acb_lockout,
4792 "effective acb_lockout");
4793 TALLOC_FREE(i);
4795 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
4796 return false;
4799 return true;
4802 static bool test_Password_lockout(struct dcerpc_pipe *p,
4803 struct dcerpc_pipe *np,
4804 struct torture_context *tctx,
4805 uint32_t acct_flags,
4806 const char *acct_name,
4807 struct policy_handle *domain_handle,
4808 struct policy_handle *user_handle,
4809 char **password,
4810 struct cli_credentials *machine_credentials,
4811 const char *comment,
4812 bool disable,
4813 bool interactive,
4814 uint32_t password_history_length,
4815 NTSTATUS expected_success_status,
4816 struct samr_DomInfo1 *info1,
4817 struct samr_DomInfo12 *info12)
4819 union samr_DomainInfo info;
4820 uint64_t lockout_threshold = 1;
4821 uint32_t lockout_seconds = 5;
4822 uint64_t delta_time_factor = 10 * 1000 * 1000;
4823 struct dcerpc_binding_handle *b = p->binding_handle;
4825 if (torture_setting_bool(tctx, "samba3", false)) {
4826 lockout_seconds = 60;
4829 torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
4831 /* set policies */
4833 info.info1 = *info1;
4835 torture_comment(tctx, "setting password history length to %d.\n", password_history_length);
4836 info.info1.password_history_length = password_history_length;
4838 torture_comment(tctx, "setting min password again.\n");
4839 info.info1.min_password_age = 0;
4841 torture_assert(tctx,
4842 test_SetDomainInfo(b, tctx, domain_handle,
4843 DomainPasswordInformation, &info),
4844 "failed to set password history length");
4846 info.info12 = *info12;
4847 info.info12.lockout_threshold = lockout_threshold;
4849 /* set lockout duration < lockout window: should fail */
4850 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4851 info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
4853 torture_assert(tctx,
4854 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4855 DomainLockoutInformation, &info,
4856 NT_STATUS_INVALID_PARAMETER),
4857 "setting lockout duration < lockout window gave unexpected result");
4859 info.info12.lockout_duration = 0;
4860 info.info12.lockout_window = 0;
4862 torture_assert(tctx,
4863 test_SetDomainInfo(b, tctx, domain_handle,
4864 DomainLockoutInformation, &info),
4865 "failed to set lockout window and duration to 0");
4868 /* set lockout duration of 5 seconds */
4869 info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4870 info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4872 torture_assert(tctx,
4873 test_SetDomainInfo(b, tctx, domain_handle,
4874 DomainLockoutInformation, &info),
4875 "failed to set lockout window and duration to 5 seconds");
4877 /* reset bad pwd count */
4879 torture_assert(tctx,
4880 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4883 /* enable or disable account */
4885 if (disable) {
4886 torture_assert(tctx,
4887 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4888 acct_flags | ACB_DISABLED),
4889 "failed to disable user");
4890 } else {
4891 torture_assert(tctx,
4892 test_SetUserInfo_acct_flags(b, tctx, user_handle,
4893 acct_flags & ~ACB_DISABLED),
4894 "failed to enable user");
4898 /* test logon with right password */
4900 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4901 acct_name, *password,
4902 expected_success_status, interactive)) {
4903 torture_fail(tctx, "failed to auth with latest password");
4906 torture_assert(tctx,
4907 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4908 0, 0, 0),
4909 "expected account to not be locked");
4911 /* test with wrong password ==> lockout */
4913 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4914 acct_name, "random_crap",
4915 NT_STATUS_WRONG_PASSWORD, interactive)) {
4916 torture_fail(tctx, "succeeded to authenticate with wrong password");
4920 * curiously, windows does _not_ return fresh values of
4921 * effective bad_password_count and ACB_AUTOLOCK.
4923 torture_assert(tctx,
4924 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4925 1, 1, ACB_AUTOLOCK),
4926 "expected account to not be locked");
4928 /* test with good password */
4930 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4931 *password,
4932 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4934 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4937 /* bad pwd count should not get updated */
4938 torture_assert(tctx,
4939 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4940 1, 1, ACB_AUTOLOCK),
4941 "expected account to be locked");
4943 torture_assert(tctx,
4944 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password,
4945 NT_STATUS_ACCOUNT_LOCKED_OUT),
4946 "got wrong status from ChangePasswordUser2");
4948 /* bad pwd count should not get updated */
4949 torture_assert(tctx,
4950 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4951 1, 1, ACB_AUTOLOCK),
4952 "expected account to be locked");
4954 torture_assert(tctx,
4955 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
4956 "got wrong status from ChangePasswordUser2");
4958 /* bad pwd count should not get updated */
4959 torture_assert(tctx,
4960 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4961 1, 1, ACB_AUTOLOCK),
4962 "expected account to be locked");
4964 /* with bad password */
4966 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4967 acct_name, "random_crap2",
4968 NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4970 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4973 /* bad pwd count should not get updated */
4974 torture_assert(tctx,
4975 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4976 1, 1, ACB_AUTOLOCK),
4977 "expected account to be locked");
4979 /* let lockout duration expire ==> unlock */
4981 torture_comment(tctx, "let lockout duration expire...\n");
4982 sleep(lockout_seconds + 1);
4984 torture_assert(tctx,
4985 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4986 1, 0, 0),
4987 "expected account to not be locked");
4989 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4990 *password,
4991 expected_success_status, interactive))
4993 torture_fail(tctx, "failed to authenticate after lockout expired");
4996 if (NT_STATUS_IS_OK(expected_success_status)) {
4997 torture_assert(tctx,
4998 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
4999 0, 0, 0),
5000 "expected account to not be locked");
5001 } else {
5002 torture_assert(tctx,
5003 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5004 1, 0, 0),
5005 "expected account to not be locked");
5008 torture_assert(tctx,
5009 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
5010 "got wrong status from ChangePasswordUser2");
5012 torture_assert(tctx,
5013 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5014 1, 1, ACB_AUTOLOCK),
5015 "expected account to be locked");
5017 torture_assert(tctx,
5018 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
5019 "got wrong status from ChangePasswordUser2");
5021 torture_assert(tctx,
5022 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5023 1, 1, ACB_AUTOLOCK),
5024 "expected account to be locked");
5026 torture_assert(tctx,
5027 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_ACCOUNT_LOCKED_OUT),
5028 "got wrong status from ChangePasswordUser2");
5030 torture_assert(tctx,
5031 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5032 1, 1, ACB_AUTOLOCK),
5033 "expected account to be locked");
5035 /* let lockout duration expire ==> unlock */
5037 torture_comment(tctx, "let lockout duration expire...\n");
5038 sleep(lockout_seconds + 1);
5040 torture_assert(tctx,
5041 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5042 1, 0, 0),
5043 "expected account to not be locked");
5045 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
5046 *password,
5047 expected_success_status, interactive))
5049 torture_fail(tctx, "failed to authenticate after lockout expired");
5052 if (NT_STATUS_IS_OK(expected_success_status)) {
5053 torture_assert(tctx,
5054 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5055 0, 0, 0),
5056 "expected account to not be locked");
5057 } else {
5058 torture_assert(tctx,
5059 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5060 1, 0, 0),
5061 "expected account to not be locked");
5064 /* Testing ChangePasswordUser behaviour with 3 attempts */
5065 info.info12.lockout_threshold = 3;
5067 torture_assert(tctx,
5068 test_SetDomainInfo(b, tctx, domain_handle,
5069 DomainLockoutInformation, &info),
5070 "failed to set lockout threshold to 3");
5072 if (NT_STATUS_IS_OK(expected_success_status)) {
5073 torture_assert(tctx,
5074 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5075 0, 0, 0),
5076 "expected account to not be locked");
5077 } else {
5078 torture_assert(tctx,
5079 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5080 1, 0, 0),
5081 "expected account to not be locked");
5084 torture_assert(tctx,
5085 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
5086 "got wrong status from ChangePasswordUser2");
5088 /* bad pwd count will get updated */
5089 torture_assert(tctx,
5090 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5091 1, 1, 0),
5092 "expected account to not be locked");
5094 torture_assert(tctx,
5095 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
5096 "got wrong status from ChangePasswordUser2");
5098 /* bad pwd count will get updated */
5099 torture_assert(tctx,
5100 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5101 2, 2, 0),
5102 "expected account to not be locked");
5104 torture_assert(tctx,
5105 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, "random_crap", NT_STATUS_WRONG_PASSWORD),
5106 "got wrong status from ChangePasswordUser2");
5108 /* bad pwd count should get updated */
5109 torture_assert(tctx,
5110 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5111 3, 3, ACB_AUTOLOCK),
5112 "expected account to be locked");
5114 torture_assert(tctx,
5115 test_ChangePasswordUser2_ntstatus(p, tctx, acct_name, *password, NT_STATUS_ACCOUNT_LOCKED_OUT),
5116 "got wrong status from ChangePasswordUser2");
5118 /* bad pwd count should not get updated */
5119 torture_assert(tctx,
5120 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5121 3, 3, ACB_AUTOLOCK),
5122 "expected account to be locked");
5124 /* let lockout duration expire ==> unlock */
5126 torture_comment(tctx, "let lockout duration expire...\n");
5127 sleep(lockout_seconds + 1);
5129 torture_assert(tctx,
5130 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5131 3, 0, 0),
5132 "expected account to not be locked");
5134 torture_assert(tctx,
5135 test_ChangePasswordUser2(p, tctx, acct_name, password, NULL, false),
5136 "got wrong status from ChangePasswordUser2");
5138 torture_assert(tctx,
5139 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5140 3, 0, 0),
5141 "expected account to not be locked");
5143 /* Used to reset the badPwdCount for the other tests */
5144 if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
5145 *password,
5146 expected_success_status, interactive))
5148 torture_fail(tctx, "failed to authenticate after lockout expired");
5151 if (NT_STATUS_IS_OK(expected_success_status)) {
5152 torture_assert(tctx,
5153 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5154 0, 0, 0),
5155 "expected account to not be locked");
5156 } else {
5157 torture_assert(tctx,
5158 test_QueryUserInfo_lockout(b, tctx, domain_handle, acct_name,
5159 3, 0, 0),
5160 "expected account to not be locked");
5163 return true;
5166 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
5167 struct torture_context *tctx,
5168 uint32_t acct_flags,
5169 const char *acct_name,
5170 struct policy_handle *domain_handle,
5171 struct policy_handle *user_handle,
5172 char **password,
5173 struct cli_credentials *machine_credentials)
5175 union samr_DomainInfo *q_info, s_info;
5176 struct samr_DomInfo1 info1, _info1;
5177 struct samr_DomInfo12 info12, _info12;
5178 bool ret = true;
5179 struct dcerpc_binding_handle *b = p->binding_handle;
5180 struct dcerpc_pipe *np;
5181 int i;
5183 struct {
5184 const char *comment;
5185 bool disabled;
5186 bool interactive;
5187 uint32_t password_history_length;
5188 NTSTATUS expected_success_status;
5189 } creds[] = {
5191 .comment = "network logon (disabled account)",
5192 .disabled = true,
5193 .interactive = false,
5194 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
5197 .comment = "network logon (enabled account)",
5198 .disabled = false,
5199 .interactive = false,
5200 .expected_success_status= NT_STATUS_OK
5203 .comment = "network logon (enabled account, history len = 1)",
5204 .disabled = false,
5205 .interactive = false,
5206 .expected_success_status= NT_STATUS_OK,
5207 .password_history_length = 1
5210 .comment = "interactive logon (disabled account)",
5211 .disabled = true,
5212 .interactive = true,
5213 .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
5216 .comment = "interactive logon (enabled account)",
5217 .disabled = false,
5218 .interactive = true,
5219 .expected_success_status= NT_STATUS_OK
5222 .comment = "interactive logon (enabled account, history len = 1)",
5223 .disabled = false,
5224 .interactive = true,
5225 .expected_success_status= NT_STATUS_OK,
5226 .password_history_length = 1
5230 torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
5232 /* backup old policies */
5234 torture_assert(tctx,
5235 test_QueryDomainInfo2_level(b, tctx, domain_handle,
5236 DomainPasswordInformation, &q_info),
5237 "failed to query domain info level 1");
5239 info1 = q_info->info1;
5240 _info1 = info1;
5242 torture_assert(tctx,
5243 test_QueryDomainInfo2_level(b, tctx, domain_handle,
5244 DomainLockoutInformation, &q_info),
5245 "failed to query domain info level 12");
5247 info12 = q_info->info12;
5248 _info12 = info12;
5250 /* run tests */
5252 for (i=0; i < ARRAY_SIZE(creds); i++) {
5253 bool test_passed;
5254 /* skip trust tests for now */
5255 if (acct_flags & ACB_WSTRUST ||
5256 acct_flags & ACB_SVRTRUST ||
5257 acct_flags & ACB_DOMTRUST) {
5258 continue;
5261 test_passed = test_Password_lockout(p, np, tctx, acct_flags, acct_name,
5262 domain_handle, user_handle, password,
5263 machine_credentials,
5264 creds[i].comment,
5265 creds[i].disabled,
5266 creds[i].interactive,
5267 creds[i].password_history_length,
5268 creds[i].expected_success_status,
5269 &_info1, &_info12);
5270 ret &= test_passed;
5271 if (!test_passed) {
5272 torture_result(tctx, TORTURE_FAIL, "TEST #%d (%s) failed\n", i, creds[i].comment);
5273 break;
5274 } else {
5275 torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
5279 /* restore policies */
5281 s_info.info1 = info1;
5283 torture_assert(tctx,
5284 test_SetDomainInfo(b, tctx, domain_handle,
5285 DomainPasswordInformation, &s_info),
5286 "failed to set password information");
5288 s_info.info12 = info12;
5290 torture_assert(tctx,
5291 test_SetDomainInfo(b, tctx, domain_handle,
5292 DomainLockoutInformation, &s_info),
5293 "failed to set lockout information");
5295 return ret;
5298 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
5299 struct dcerpc_pipe *lp,
5300 struct torture_context *tctx,
5301 struct policy_handle *domain_handle,
5302 struct policy_handle *lsa_handle,
5303 struct policy_handle *user_handle,
5304 const struct dom_sid *domain_sid,
5305 uint32_t rid,
5306 struct cli_credentials *machine_credentials)
5308 bool ret = true;
5309 struct dcerpc_binding_handle *b = p->binding_handle;
5310 struct dcerpc_binding_handle *lb = lp->binding_handle;
5312 struct policy_handle lsa_acct_handle;
5313 struct dom_sid *user_sid;
5315 user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
5318 struct lsa_EnumAccountRights r;
5319 struct lsa_RightSet rights;
5321 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
5323 r.in.handle = lsa_handle;
5324 r.in.sid = user_sid;
5325 r.out.rights = &rights;
5327 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
5328 "lsa_EnumAccountRights failed");
5329 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
5330 "Expected enum rights for account to fail");
5334 struct lsa_RightSet rights;
5335 struct lsa_StringLarge names[2];
5336 struct lsa_AddAccountRights r;
5338 torture_comment(tctx, "Testing LSA AddAccountRights\n");
5340 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
5341 init_lsa_StringLarge(&names[1], NULL);
5343 rights.count = 1;
5344 rights.names = names;
5346 r.in.handle = lsa_handle;
5347 r.in.sid = user_sid;
5348 r.in.rights = &rights;
5350 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
5351 "lsa_AddAccountRights failed");
5352 torture_assert_ntstatus_ok(tctx, r.out.result,
5353 "Failed to add privileges");
5357 struct lsa_RightSet rights;
5358 struct lsa_StringLarge names[2];
5359 struct lsa_AddAccountRights r;
5361 torture_comment(tctx, "Testing LSA AddAccountRights 1\n");
5363 init_lsa_StringLarge(&names[0], "SeInteractiveLogonRight");
5364 init_lsa_StringLarge(&names[1], NULL);
5366 rights.count = 1;
5367 rights.names = names;
5369 r.in.handle = lsa_handle;
5370 r.in.sid = user_sid;
5371 r.in.rights = &rights;
5373 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
5374 "lsa_AddAccountRights 1 failed");
5376 if (torture_setting_bool(tctx, "nt4_dc", false)) {
5378 * The NT4 DC doesn't implement Rights.
5380 torture_assert_ntstatus_equal(tctx, r.out.result,
5381 NT_STATUS_NO_SUCH_PRIVILEGE,
5382 "Add rights failed with incorrect error");
5383 } else {
5384 torture_assert_ntstatus_ok(tctx, r.out.result,
5385 "Failed to add rights");
5392 struct lsa_EnumAccounts r;
5393 uint32_t resume_handle = 0;
5394 struct lsa_SidArray lsa_sid_array;
5395 int i;
5396 bool found_sid = false;
5398 torture_comment(tctx, "Testing LSA EnumAccounts\n");
5400 r.in.handle = lsa_handle;
5401 r.in.num_entries = 0x1000;
5402 r.in.resume_handle = &resume_handle;
5403 r.out.sids = &lsa_sid_array;
5404 r.out.resume_handle = &resume_handle;
5406 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
5407 "lsa_EnumAccounts failed");
5408 torture_assert_ntstatus_ok(tctx, r.out.result,
5409 "Failed to enum accounts");
5411 for (i=0; i < lsa_sid_array.num_sids; i++) {
5412 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
5413 found_sid = true;
5417 torture_assert(tctx, found_sid,
5418 "failed to list privileged account");
5422 struct lsa_EnumAccountRights r;
5423 struct lsa_RightSet user_rights;
5424 uint32_t expected_count = 2;
5426 if (torture_setting_bool(tctx, "nt4_dc", false)) {
5428 * NT4 DC doesn't store rights.
5430 expected_count = 1;
5433 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
5435 r.in.handle = lsa_handle;
5436 r.in.sid = user_sid;
5437 r.out.rights = &user_rights;
5439 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
5440 "lsa_EnumAccountRights failed");
5441 torture_assert_ntstatus_ok(tctx, r.out.result,
5442 "Failed to enum rights for account");
5444 if (user_rights.count < expected_count) {
5445 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
5446 return false;
5451 struct lsa_OpenAccount r;
5453 torture_comment(tctx, "Testing LSA OpenAccount\n");
5455 r.in.handle = lsa_handle;
5456 r.in.sid = user_sid;
5457 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5458 r.out.acct_handle = &lsa_acct_handle;
5460 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
5461 "lsa_OpenAccount failed");
5462 torture_assert_ntstatus_ok(tctx, r.out.result,
5463 "Failed to open lsa account");
5467 struct lsa_GetSystemAccessAccount r;
5468 uint32_t access_mask;
5470 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
5472 r.in.handle = &lsa_acct_handle;
5473 r.out.access_mask = &access_mask;
5475 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
5476 "lsa_GetSystemAccessAccount failed");
5477 torture_assert_ntstatus_ok(tctx, r.out.result,
5478 "Failed to get lsa system access account");
5482 struct lsa_Close r;
5484 torture_comment(tctx, "Testing LSA Close\n");
5486 r.in.handle = &lsa_acct_handle;
5487 r.out.handle = &lsa_acct_handle;
5489 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
5490 "lsa_Close failed");
5491 torture_assert_ntstatus_ok(tctx, r.out.result,
5492 "Failed to close lsa");
5496 struct samr_DeleteUser r;
5498 torture_comment(tctx, "Testing SAMR DeleteUser\n");
5500 r.in.user_handle = user_handle;
5501 r.out.user_handle = user_handle;
5503 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
5504 "DeleteUser failed");
5505 torture_assert_ntstatus_ok(tctx, r.out.result,
5506 "DeleteUser failed");
5510 struct lsa_EnumAccounts r;
5511 uint32_t resume_handle = 0;
5512 struct lsa_SidArray lsa_sid_array;
5513 int i;
5514 bool found_sid = false;
5516 torture_comment(tctx, "Testing LSA EnumAccounts\n");
5518 r.in.handle = lsa_handle;
5519 r.in.num_entries = 0x1000;
5520 r.in.resume_handle = &resume_handle;
5521 r.out.sids = &lsa_sid_array;
5522 r.out.resume_handle = &resume_handle;
5524 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
5525 "lsa_EnumAccounts failed");
5526 torture_assert_ntstatus_ok(tctx, r.out.result,
5527 "Failed to enum accounts");
5529 for (i=0; i < lsa_sid_array.num_sids; i++) {
5530 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
5531 found_sid = true;
5535 torture_assert(tctx, found_sid,
5536 "failed to list privileged account");
5540 struct lsa_EnumAccountRights r;
5541 struct lsa_RightSet user_rights;
5543 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
5545 r.in.handle = lsa_handle;
5546 r.in.sid = user_sid;
5547 r.out.rights = &user_rights;
5549 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
5550 "lsa_EnumAccountRights failed");
5551 torture_assert_ntstatus_ok(tctx, r.out.result,
5552 "Failed to enum rights for account");
5554 if (user_rights.count < 1) {
5555 torture_result(tctx, TORTURE_FAIL, "failed to find newly added rights");
5556 return false;
5561 struct lsa_OpenAccount r;
5563 torture_comment(tctx, "Testing LSA OpenAccount\n");
5565 r.in.handle = lsa_handle;
5566 r.in.sid = user_sid;
5567 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5568 r.out.acct_handle = &lsa_acct_handle;
5570 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
5571 "lsa_OpenAccount failed");
5572 torture_assert_ntstatus_ok(tctx, r.out.result,
5573 "Failed to open lsa account");
5577 struct lsa_GetSystemAccessAccount r;
5578 uint32_t access_mask;
5580 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
5582 r.in.handle = &lsa_acct_handle;
5583 r.out.access_mask = &access_mask;
5585 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
5586 "lsa_GetSystemAccessAccount failed");
5587 torture_assert_ntstatus_ok(tctx, r.out.result,
5588 "Failed to get lsa system access account");
5592 struct lsa_DeleteObject r;
5594 torture_comment(tctx, "Testing LSA DeleteObject\n");
5596 r.in.handle = &lsa_acct_handle;
5597 r.out.handle = &lsa_acct_handle;
5599 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
5600 "lsa_DeleteObject failed");
5601 torture_assert_ntstatus_ok(tctx, r.out.result,
5602 "Failed to delete object");
5606 struct lsa_EnumAccounts r;
5607 uint32_t resume_handle = 0;
5608 struct lsa_SidArray lsa_sid_array;
5609 int i;
5610 bool found_sid = false;
5612 torture_comment(tctx, "Testing LSA EnumAccounts\n");
5614 r.in.handle = lsa_handle;
5615 r.in.num_entries = 0x1000;
5616 r.in.resume_handle = &resume_handle;
5617 r.out.sids = &lsa_sid_array;
5618 r.out.resume_handle = &resume_handle;
5620 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
5621 "lsa_EnumAccounts failed");
5622 torture_assert_ntstatus_ok(tctx, r.out.result,
5623 "Failed to enum accounts");
5625 for (i=0; i < lsa_sid_array.num_sids; i++) {
5626 if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
5627 found_sid = true;
5631 torture_assert(tctx, !found_sid,
5632 "should not have listed privileged account");
5636 struct lsa_EnumAccountRights r;
5637 struct lsa_RightSet user_rights;
5639 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
5641 r.in.handle = lsa_handle;
5642 r.in.sid = user_sid;
5643 r.out.rights = &user_rights;
5645 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
5646 "lsa_EnumAccountRights failed");
5647 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
5648 "Failed to enum rights for account");
5651 return ret;
5654 static bool test_user_ops(struct dcerpc_pipe *p,
5655 struct torture_context *tctx,
5656 struct policy_handle *user_handle,
5657 struct policy_handle *domain_handle,
5658 const struct dom_sid *domain_sid,
5659 uint32_t base_acct_flags,
5660 const char *base_acct_name, enum torture_samr_choice which_ops,
5661 struct cli_credentials *machine_credentials)
5663 char *password = NULL;
5664 struct samr_QueryUserInfo q;
5665 union samr_UserInfo *info;
5666 NTSTATUS status;
5667 struct dcerpc_binding_handle *b = p->binding_handle;
5669 bool ret = true;
5670 int i;
5671 uint32_t rid;
5672 const uint32_t password_fields[] = {
5673 SAMR_FIELD_NT_PASSWORD_PRESENT,
5674 SAMR_FIELD_LM_PASSWORD_PRESENT,
5675 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
5679 status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
5680 if (!NT_STATUS_IS_OK(status)) {
5681 ret = false;
5684 switch (which_ops) {
5685 case TORTURE_SAMR_USER_ATTRIBUTES:
5686 if (!test_QuerySecurity(b, tctx, user_handle)) {
5687 ret = false;
5690 if (!test_QueryUserInfo(b, tctx, user_handle)) {
5691 ret = false;
5694 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
5695 ret = false;
5698 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
5699 base_acct_name)) {
5700 ret = false;
5703 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
5704 ret = false;
5707 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
5708 ret = false;
5711 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
5712 ret = false;
5714 break;
5715 case TORTURE_SAMR_PASSWORDS:
5716 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
5717 char simple_pass[9];
5718 char *v = generate_random_str(tctx, 1);
5720 ZERO_STRUCT(simple_pass);
5721 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5723 torture_comment(tctx, "Testing machine account password policy rules\n");
5725 /* Workstation trust accounts don't seem to need to honour password quality policy */
5726 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
5727 ret = false;
5730 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
5731 ret = false;
5734 /* reset again, to allow another 'user' password change */
5735 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
5736 ret = false;
5739 /* Try a 'short' password */
5740 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
5741 ret = false;
5744 /* Try a completely random password */
5745 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
5746 ret = false;
5750 for (i = 0; password_fields[i]; i++) {
5751 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
5752 ret = false;
5755 /* check it was set right */
5756 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5757 ret = false;
5761 for (i = 0; password_fields[i]; i++) {
5762 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
5763 ret = false;
5766 /* check it was set right */
5767 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5768 ret = false;
5772 if (!test_SetUserPass_31(p, tctx, user_handle, false, &password)) {
5773 ret = false;
5776 for (i = 0; password_fields[i]; i++) {
5777 if (!test_SetUserPass_32(p, tctx, user_handle, password_fields[i], &password)) {
5778 ret = false;
5781 /* check it was set right */
5782 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5783 ret = false;
5787 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
5788 ret = false;
5791 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
5792 ret = false;
5795 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
5796 ret = false;
5799 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
5800 ret = false;
5803 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5804 ret = false;
5807 for (i = 0; password_fields[i]; i++) {
5809 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
5810 /* we need to skip as that would break
5811 * the ChangePasswordUser3 verify */
5812 continue;
5815 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
5816 ret = false;
5819 /* check it was set right */
5820 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
5821 ret = false;
5825 q.in.user_handle = user_handle;
5826 q.in.level = 5;
5827 q.out.info = &info;
5829 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5830 "QueryUserInfo failed");
5831 if (!NT_STATUS_IS_OK(q.out.result)) {
5832 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
5833 q.in.level, nt_errstr(q.out.result));
5834 ret = false;
5835 } else {
5836 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5837 if ((info->info5.acct_flags) != expected_flags) {
5838 /* FIXME: GD */
5839 if (!torture_setting_bool(tctx, "samba3", false)) {
5840 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5841 info->info5.acct_flags,
5842 expected_flags);
5843 ret = false;
5846 if (info->info5.rid != rid) {
5847 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
5848 info->info5.rid, rid);
5853 break;
5855 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
5857 /* test last password change timestamp behaviour */
5858 torture_assert(tctx, test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
5859 base_acct_name,
5860 user_handle, &password,
5861 machine_credentials),
5862 "pwdLastSet test failed\n");
5863 break;
5865 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
5867 /* test bad pwd count change behaviour */
5868 torture_assert(tctx, test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
5869 base_acct_name,
5870 domain_handle,
5871 user_handle, &password,
5872 machine_credentials),
5873 "badPwdCount test failed\n");
5874 break;
5876 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
5878 torture_assert(tctx, test_Password_lockout_wrap(p, tctx, base_acct_flags,
5879 base_acct_name,
5880 domain_handle,
5881 user_handle, &password,
5882 machine_credentials),
5883 "Lockout test failed");
5884 break;
5887 case TORTURE_SAMR_USER_PRIVILEGES: {
5889 struct dcerpc_pipe *lp;
5890 struct policy_handle *lsa_handle;
5891 struct dcerpc_binding_handle *lb;
5893 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
5894 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
5895 lb = lp->binding_handle;
5897 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
5898 ret = false;
5901 if (!test_DeleteUser_with_privs(p, lp, tctx,
5902 domain_handle, lsa_handle, user_handle,
5903 domain_sid, rid,
5904 machine_credentials)) {
5905 ret = false;
5908 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
5909 ret = false;
5912 if (!ret) {
5913 torture_result(tctx, TORTURE_FAIL, "privileged user delete test failed\n");
5916 break;
5918 case TORTURE_SAMR_OTHER:
5919 case TORTURE_SAMR_MANY_ACCOUNTS:
5920 case TORTURE_SAMR_MANY_GROUPS:
5921 case TORTURE_SAMR_MANY_ALIASES:
5922 /* We just need the account to exist */
5923 break;
5925 return ret;
5928 static bool test_alias_ops(struct dcerpc_binding_handle *b,
5929 struct torture_context *tctx,
5930 struct policy_handle *alias_handle,
5931 const struct dom_sid *domain_sid)
5933 bool ret = true;
5935 if (!torture_setting_bool(tctx, "samba3", false)) {
5936 if (!test_QuerySecurity(b, tctx, alias_handle)) {
5937 ret = false;
5941 if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
5942 ret = false;
5945 if (!test_SetAliasInfo(b, tctx, alias_handle)) {
5946 ret = false;
5949 if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
5950 ret = false;
5953 if (torture_setting_bool(tctx, "samba3", false) ||
5954 torture_setting_bool(tctx, "samba4", false)) {
5955 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
5956 return ret;
5959 if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
5960 ret = false;
5963 return ret;
5967 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
5968 struct torture_context *tctx,
5969 struct policy_handle *user_handle)
5971 struct samr_DeleteUser d;
5972 torture_comment(tctx, "Testing DeleteUser\n");
5974 d.in.user_handle = user_handle;
5975 d.out.user_handle = user_handle;
5977 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
5978 "DeleteUser failed");
5979 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
5981 return true;
5984 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
5985 struct torture_context *tctx,
5986 struct policy_handle *handle, const char *name)
5988 NTSTATUS status;
5989 struct samr_DeleteUser d;
5990 struct policy_handle user_handle;
5991 uint32_t rid;
5993 status = test_LookupName(b, tctx, handle, name, &rid);
5994 if (!NT_STATUS_IS_OK(status)) {
5995 goto failed;
5998 status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
5999 if (!NT_STATUS_IS_OK(status)) {
6000 goto failed;
6003 d.in.user_handle = &user_handle;
6004 d.out.user_handle = &user_handle;
6005 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
6006 "DeleteUser failed");
6007 if (!NT_STATUS_IS_OK(d.out.result)) {
6008 status = d.out.result;
6009 goto failed;
6012 return true;
6014 failed:
6015 torture_result(tctx, TORTURE_FAIL, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
6016 return false;
6020 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
6021 struct torture_context *tctx,
6022 struct policy_handle *handle, const char *name)
6024 NTSTATUS status;
6025 struct samr_OpenGroup r;
6026 struct samr_DeleteDomainGroup d;
6027 struct policy_handle group_handle;
6028 uint32_t rid;
6030 status = test_LookupName(b, tctx, handle, name, &rid);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 goto failed;
6035 r.in.domain_handle = handle;
6036 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6037 r.in.rid = rid;
6038 r.out.group_handle = &group_handle;
6039 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
6040 "OpenGroup failed");
6041 if (!NT_STATUS_IS_OK(r.out.result)) {
6042 status = r.out.result;
6043 goto failed;
6046 d.in.group_handle = &group_handle;
6047 d.out.group_handle = &group_handle;
6048 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
6049 "DeleteDomainGroup failed");
6050 if (!NT_STATUS_IS_OK(d.out.result)) {
6051 status = d.out.result;
6052 goto failed;
6055 return true;
6057 failed:
6058 torture_result(tctx, TORTURE_FAIL, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
6059 return false;
6063 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
6064 struct torture_context *tctx,
6065 struct policy_handle *domain_handle,
6066 const char *name)
6068 NTSTATUS status;
6069 struct samr_OpenAlias r;
6070 struct samr_DeleteDomAlias d;
6071 struct policy_handle alias_handle;
6072 uint32_t rid;
6074 torture_comment(tctx, "Testing DeleteAlias_byname\n");
6076 status = test_LookupName(b, tctx, domain_handle, name, &rid);
6077 if (!NT_STATUS_IS_OK(status)) {
6078 goto failed;
6081 r.in.domain_handle = domain_handle;
6082 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6083 r.in.rid = rid;
6084 r.out.alias_handle = &alias_handle;
6085 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
6086 "OpenAlias failed");
6087 if (!NT_STATUS_IS_OK(r.out.result)) {
6088 status = r.out.result;
6089 goto failed;
6092 d.in.alias_handle = &alias_handle;
6093 d.out.alias_handle = &alias_handle;
6094 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
6095 "DeleteDomAlias failed");
6096 if (!NT_STATUS_IS_OK(d.out.result)) {
6097 status = d.out.result;
6098 goto failed;
6101 return true;
6103 failed:
6104 torture_result(tctx, TORTURE_FAIL, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
6105 return false;
6108 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
6109 struct torture_context *tctx,
6110 struct policy_handle *alias_handle)
6112 struct samr_DeleteDomAlias d;
6113 bool ret = true;
6115 torture_comment(tctx, "Testing DeleteAlias\n");
6117 d.in.alias_handle = alias_handle;
6118 d.out.alias_handle = alias_handle;
6120 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
6121 "DeleteDomAlias failed");
6122 if (!NT_STATUS_IS_OK(d.out.result)) {
6123 torture_result(tctx, TORTURE_FAIL, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
6124 ret = false;
6127 return ret;
6130 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
6131 struct torture_context *tctx,
6132 struct policy_handle *domain_handle,
6133 const char *alias_name,
6134 struct policy_handle *alias_handle,
6135 const struct dom_sid *domain_sid,
6136 bool test_alias)
6138 struct samr_CreateDomAlias r;
6139 struct lsa_String name;
6140 uint32_t rid;
6141 bool ret = true;
6143 init_lsa_String(&name, alias_name);
6144 r.in.domain_handle = domain_handle;
6145 r.in.alias_name = &name;
6146 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6147 r.out.alias_handle = alias_handle;
6148 r.out.rid = &rid;
6150 torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
6152 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
6153 "CreateDomAlias failed");
6155 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6156 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
6157 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
6158 return true;
6159 } else {
6160 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
6161 nt_errstr(r.out.result));
6162 return false;
6166 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
6167 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
6168 return false;
6170 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
6171 "CreateDomAlias failed");
6174 if (!NT_STATUS_IS_OK(r.out.result)) {
6175 torture_result(tctx, TORTURE_FAIL, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
6176 return false;
6179 if (!test_alias) {
6180 return ret;
6183 if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
6184 ret = false;
6187 return ret;
6190 static bool test_ChangePassword(struct dcerpc_pipe *p,
6191 struct torture_context *tctx,
6192 const char *acct_name,
6193 struct policy_handle *domain_handle, char **password)
6195 bool ret = true;
6196 struct dcerpc_binding_handle *b = p->binding_handle;
6198 if (!*password) {
6199 return false;
6202 if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
6203 ret = false;
6206 if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
6207 ret = false;
6210 if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
6211 ret = false;
6214 /* test what happens when setting the old password again */
6215 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
6216 ret = false;
6220 char simple_pass[9];
6221 char *v = generate_random_str(tctx, 1);
6223 ZERO_STRUCT(simple_pass);
6224 memset(simple_pass, *v, sizeof(simple_pass) - 1);
6226 /* test what happens when picking a simple password */
6227 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
6228 ret = false;
6232 /* set samr_SetDomainInfo level 1 with min_length 5 */
6234 struct samr_QueryDomainInfo r;
6235 union samr_DomainInfo *info = NULL;
6236 struct samr_SetDomainInfo s;
6237 uint16_t len_old, len;
6238 uint32_t pwd_prop_old;
6239 int64_t min_pwd_age_old;
6241 len = 5;
6243 r.in.domain_handle = domain_handle;
6244 r.in.level = 1;
6245 r.out.info = &info;
6247 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
6248 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6249 "QueryDomainInfo failed");
6250 if (!NT_STATUS_IS_OK(r.out.result)) {
6251 return false;
6254 s.in.domain_handle = domain_handle;
6255 s.in.level = 1;
6256 s.in.info = info;
6258 /* remember the old min length, so we can reset it */
6259 len_old = s.in.info->info1.min_password_length;
6260 s.in.info->info1.min_password_length = len;
6261 pwd_prop_old = s.in.info->info1.password_properties;
6262 /* turn off password complexity checks for this test */
6263 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
6265 min_pwd_age_old = s.in.info->info1.min_password_age;
6266 s.in.info->info1.min_password_age = 0;
6268 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
6269 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6270 "SetDomainInfo failed");
6271 if (!NT_STATUS_IS_OK(s.out.result)) {
6272 return false;
6275 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
6277 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
6278 ret = false;
6281 s.in.info->info1.min_password_length = len_old;
6282 s.in.info->info1.password_properties = pwd_prop_old;
6283 s.in.info->info1.min_password_age = min_pwd_age_old;
6285 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
6286 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6287 "SetDomainInfo failed");
6288 if (!NT_STATUS_IS_OK(s.out.result)) {
6289 return false;
6295 struct samr_OpenUser r;
6296 struct samr_QueryUserInfo q;
6297 union samr_UserInfo *info;
6298 struct samr_LookupNames n;
6299 struct policy_handle user_handle;
6300 struct samr_Ids rids, types;
6302 n.in.domain_handle = domain_handle;
6303 n.in.num_names = 1;
6304 n.in.names = talloc_array(tctx, struct lsa_String, 1);
6305 n.in.names[0].string = acct_name;
6306 n.out.rids = &rids;
6307 n.out.types = &types;
6309 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6310 "LookupNames failed");
6311 if (!NT_STATUS_IS_OK(n.out.result)) {
6312 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6313 return false;
6316 r.in.domain_handle = domain_handle;
6317 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6318 r.in.rid = n.out.rids->ids[0];
6319 r.out.user_handle = &user_handle;
6321 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6322 "OpenUser failed");
6323 if (!NT_STATUS_IS_OK(r.out.result)) {
6324 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
6325 return false;
6328 q.in.user_handle = &user_handle;
6329 q.in.level = 5;
6330 q.out.info = &info;
6332 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6333 "QueryUserInfo failed");
6334 if (!NT_STATUS_IS_OK(q.out.result)) {
6335 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
6336 return false;
6339 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
6341 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
6342 info->info5.last_password_change, true)) {
6343 ret = false;
6347 /* we change passwords twice - this has the effect of verifying
6348 they were changed correctly for the final call */
6349 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
6350 ret = false;
6353 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
6354 ret = false;
6357 if (!test_ChangePasswordUser4(p, tctx, acct_name, 0, password, NULL)) {
6358 ret = false;
6361 return ret;
6364 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
6365 struct policy_handle *domain_handle,
6366 const char *user_name,
6367 struct policy_handle *user_handle_out,
6368 struct dom_sid *domain_sid,
6369 enum torture_samr_choice which_ops,
6370 struct cli_credentials *machine_credentials,
6371 bool test_user)
6374 TALLOC_CTX *user_ctx;
6376 struct samr_CreateUser r;
6377 struct samr_QueryUserInfo q;
6378 union samr_UserInfo *info;
6379 struct samr_DeleteUser d;
6380 uint32_t rid;
6382 /* This call creates a 'normal' account - check that it really does */
6383 const uint32_t acct_flags = ACB_NORMAL;
6384 struct lsa_String name;
6385 bool ret = true;
6386 struct dcerpc_binding_handle *b = p->binding_handle;
6388 struct policy_handle user_handle;
6389 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
6390 init_lsa_String(&name, user_name);
6392 r.in.domain_handle = domain_handle;
6393 r.in.account_name = &name;
6394 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6395 r.out.user_handle = &user_handle;
6396 r.out.rid = &rid;
6398 torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
6400 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
6401 "CreateUser failed");
6403 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6404 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
6405 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
6406 return true;
6407 } else {
6408 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
6409 nt_errstr(r.out.result));
6410 return false;
6414 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
6415 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
6416 talloc_free(user_ctx);
6417 return false;
6419 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
6420 "CreateUser failed");
6423 if (!NT_STATUS_IS_OK(r.out.result)) {
6424 talloc_free(user_ctx);
6425 torture_result(tctx, TORTURE_FAIL, "CreateUser failed - %s\n", nt_errstr(r.out.result));
6426 return false;
6429 if (!test_user) {
6430 if (user_handle_out) {
6431 *user_handle_out = user_handle;
6433 return ret;
6437 q.in.user_handle = &user_handle;
6438 q.in.level = 16;
6439 q.out.info = &info;
6441 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
6442 "QueryUserInfo failed");
6443 if (!NT_STATUS_IS_OK(q.out.result)) {
6444 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
6445 q.in.level, nt_errstr(q.out.result));
6446 ret = false;
6447 } else {
6448 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
6449 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
6450 info->info16.acct_flags,
6451 acct_flags);
6452 ret = false;
6456 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
6457 domain_sid, acct_flags, name.string, which_ops,
6458 machine_credentials)) {
6459 ret = false;
6462 if (user_handle_out) {
6463 *user_handle_out = user_handle;
6464 } else {
6465 torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
6467 d.in.user_handle = &user_handle;
6468 d.out.user_handle = &user_handle;
6470 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
6471 "DeleteUser failed");
6472 if (!NT_STATUS_IS_OK(d.out.result)) {
6473 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
6474 ret = false;
6480 talloc_free(user_ctx);
6482 return ret;
6486 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
6487 struct policy_handle *domain_handle,
6488 struct dom_sid *domain_sid,
6489 enum torture_samr_choice which_ops,
6490 struct cli_credentials *machine_credentials)
6492 struct samr_CreateUser2 r;
6493 struct samr_QueryUserInfo q;
6494 union samr_UserInfo *info;
6495 struct samr_DeleteUser d;
6496 struct policy_handle user_handle;
6497 uint32_t rid;
6498 struct lsa_String name;
6499 bool ret = true;
6500 int i;
6501 struct dcerpc_binding_handle *b = p->binding_handle;
6503 struct {
6504 uint32_t acct_flags;
6505 const char *account_name;
6506 NTSTATUS nt_status;
6507 } account_types[] = {
6508 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
6509 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
6510 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
6511 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
6512 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
6513 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
6514 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
6515 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
6516 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
6517 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
6518 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
6519 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
6520 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
6521 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
6522 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
6525 for (i = 0; account_types[i].account_name; i++) {
6526 TALLOC_CTX *user_ctx;
6527 uint32_t acct_flags = account_types[i].acct_flags;
6528 uint32_t access_granted;
6529 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
6530 init_lsa_String(&name, account_types[i].account_name);
6532 r.in.domain_handle = domain_handle;
6533 r.in.account_name = &name;
6534 r.in.acct_flags = acct_flags;
6535 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6536 r.out.user_handle = &user_handle;
6537 r.out.access_granted = &access_granted;
6538 r.out.rid = &rid;
6540 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
6542 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
6543 "CreateUser2 failed");
6545 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6546 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
6547 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
6548 continue;
6549 } else {
6550 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
6551 nt_errstr(r.out.result));
6552 ret = false;
6553 continue;
6557 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
6558 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
6559 talloc_free(user_ctx);
6560 ret = false;
6561 continue;
6563 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
6564 "CreateUser2 failed");
6567 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
6568 torture_result(tctx, TORTURE_FAIL, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
6569 nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
6570 ret = false;
6573 if (NT_STATUS_IS_OK(r.out.result)) {
6574 q.in.user_handle = &user_handle;
6575 q.in.level = 5;
6576 q.out.info = &info;
6578 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
6579 "QueryUserInfo failed");
6580 if (!NT_STATUS_IS_OK(q.out.result)) {
6581 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
6582 q.in.level, nt_errstr(q.out.result));
6583 ret = false;
6584 } else {
6585 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
6586 if (acct_flags == ACB_NORMAL) {
6587 expected_flags |= ACB_PW_EXPIRED;
6589 if ((info->info5.acct_flags) != expected_flags) {
6590 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
6591 info->info5.acct_flags,
6592 expected_flags);
6593 ret = false;
6595 switch (acct_flags) {
6596 case ACB_SVRTRUST:
6597 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
6598 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
6599 DOMAIN_RID_DCS, info->info5.primary_gid);
6600 ret = false;
6602 break;
6603 case ACB_WSTRUST:
6604 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
6605 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
6606 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
6607 ret = false;
6609 break;
6610 case ACB_NORMAL:
6611 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
6612 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
6613 DOMAIN_RID_USERS, info->info5.primary_gid);
6614 ret = false;
6616 break;
6620 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
6621 domain_sid, acct_flags, name.string, which_ops,
6622 machine_credentials)) {
6623 ret = false;
6626 if (!ndr_policy_handle_empty(&user_handle)) {
6627 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
6629 d.in.user_handle = &user_handle;
6630 d.out.user_handle = &user_handle;
6632 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
6633 "DeleteUser failed");
6634 if (!NT_STATUS_IS_OK(d.out.result)) {
6635 torture_result(tctx, TORTURE_FAIL, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
6636 ret = false;
6640 talloc_free(user_ctx);
6643 return ret;
6646 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
6647 struct torture_context *tctx,
6648 struct policy_handle *handle)
6650 struct samr_QueryAliasInfo r;
6651 union samr_AliasInfo *info;
6652 uint16_t levels[] = {1, 2, 3};
6653 int i;
6654 bool ret = true;
6656 for (i=0;i<ARRAY_SIZE(levels);i++) {
6657 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
6659 r.in.alias_handle = handle;
6660 r.in.level = levels[i];
6661 r.out.info = &info;
6663 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
6664 "QueryAliasInfo failed");
6665 if (!NT_STATUS_IS_OK(r.out.result)) {
6666 torture_result(tctx, TORTURE_FAIL, "QueryAliasInfo level %u failed - %s\n",
6667 levels[i], nt_errstr(r.out.result));
6668 ret = false;
6672 return ret;
6675 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
6676 struct torture_context *tctx,
6677 struct policy_handle *handle)
6679 struct samr_QueryGroupInfo r;
6680 union samr_GroupInfo *info;
6681 uint16_t levels[] = {1, 2, 3, 4, 5};
6682 int i;
6683 bool ret = true;
6685 for (i=0;i<ARRAY_SIZE(levels);i++) {
6686 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
6688 r.in.group_handle = handle;
6689 r.in.level = levels[i];
6690 r.out.info = &info;
6692 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
6693 "QueryGroupInfo failed");
6694 if (!NT_STATUS_IS_OK(r.out.result)) {
6695 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
6696 levels[i], nt_errstr(r.out.result));
6697 ret = false;
6701 return ret;
6704 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
6705 struct torture_context *tctx,
6706 struct policy_handle *handle)
6708 struct samr_QueryGroupMember r;
6709 struct samr_RidAttrArray *rids = NULL;
6710 bool ret = true;
6712 torture_comment(tctx, "Testing QueryGroupMember\n");
6714 r.in.group_handle = handle;
6715 r.out.rids = &rids;
6717 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
6718 "QueryGroupMember failed");
6719 if (!NT_STATUS_IS_OK(r.out.result)) {
6720 torture_result(tctx, TORTURE_FAIL, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
6721 ret = false;
6724 return ret;
6728 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
6729 struct torture_context *tctx,
6730 struct policy_handle *handle)
6732 struct samr_QueryGroupInfo r;
6733 union samr_GroupInfo *info;
6734 struct samr_SetGroupInfo s;
6735 uint16_t levels[] = {1, 2, 3, 4};
6736 uint16_t set_ok[] = {0, 1, 1, 1};
6737 int i;
6738 bool ret = true;
6740 for (i=0;i<ARRAY_SIZE(levels);i++) {
6741 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
6743 r.in.group_handle = handle;
6744 r.in.level = levels[i];
6745 r.out.info = &info;
6747 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
6748 "QueryGroupInfo failed");
6749 if (!NT_STATUS_IS_OK(r.out.result)) {
6750 torture_result(tctx, TORTURE_FAIL, "QueryGroupInfo level %u failed - %s\n",
6751 levels[i], nt_errstr(r.out.result));
6752 ret = false;
6755 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
6757 s.in.group_handle = handle;
6758 s.in.level = levels[i];
6759 s.in.info = *r.out.info;
6761 #if 0
6762 /* disabled this, as it changes the name only from the point of view of samr,
6763 but leaves the name from the point of view of w2k3 internals (and ldap). This means
6764 the name is still reserved, so creating the old name fails, but deleting by the old name
6765 also fails */
6766 if (s.in.level == 2) {
6767 init_lsa_String(&s.in.info->string, "NewName");
6769 #endif
6771 if (s.in.level == 4) {
6772 init_lsa_String(&s.in.info->description, "test description");
6775 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
6776 "SetGroupInfo failed");
6777 if (set_ok[i]) {
6778 if (!NT_STATUS_IS_OK(s.out.result)) {
6779 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u failed - %s\n",
6780 r.in.level, nt_errstr(s.out.result));
6781 ret = false;
6782 continue;
6784 } else {
6785 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6786 torture_result(tctx, TORTURE_FAIL, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6787 r.in.level, nt_errstr(s.out.result));
6788 ret = false;
6789 continue;
6794 return ret;
6797 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
6798 struct torture_context *tctx,
6799 struct policy_handle *handle)
6801 struct samr_QueryUserInfo r;
6802 union samr_UserInfo *info;
6803 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6804 11, 12, 13, 14, 16, 17, 20, 21};
6805 int i;
6806 bool ret = true;
6808 for (i=0;i<ARRAY_SIZE(levels);i++) {
6809 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
6811 r.in.user_handle = handle;
6812 r.in.level = levels[i];
6813 r.out.info = &info;
6815 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
6816 "QueryUserInfo failed");
6817 if (!NT_STATUS_IS_OK(r.out.result)) {
6818 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level %u failed - %s\n",
6819 levels[i], nt_errstr(r.out.result));
6820 ret = false;
6824 return ret;
6827 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
6828 struct torture_context *tctx,
6829 struct policy_handle *handle)
6831 struct samr_QueryUserInfo2 r;
6832 union samr_UserInfo *info;
6833 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6834 11, 12, 13, 14, 16, 17, 20, 21};
6835 int i;
6836 bool ret = true;
6838 for (i=0;i<ARRAY_SIZE(levels);i++) {
6839 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
6841 r.in.user_handle = handle;
6842 r.in.level = levels[i];
6843 r.out.info = &info;
6845 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
6846 "QueryUserInfo2 failed");
6847 if (!NT_STATUS_IS_OK(r.out.result)) {
6848 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo2 level %u failed - %s\n",
6849 levels[i], nt_errstr(r.out.result));
6850 ret = false;
6854 return ret;
6857 static bool test_OpenUser(struct dcerpc_binding_handle *b,
6858 struct torture_context *tctx,
6859 struct policy_handle *handle, uint32_t rid)
6861 struct samr_OpenUser r;
6862 struct policy_handle user_handle;
6863 bool ret = true;
6865 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
6867 r.in.domain_handle = handle;
6868 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6869 r.in.rid = rid;
6870 r.out.user_handle = &user_handle;
6872 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6873 "OpenUser failed");
6874 if (!NT_STATUS_IS_OK(r.out.result)) {
6875 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6876 return false;
6879 if (!test_QuerySecurity(b, tctx, &user_handle)) {
6880 ret = false;
6883 if (!test_QueryUserInfo(b, tctx, &user_handle)) {
6884 ret = false;
6887 if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
6888 ret = false;
6891 if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
6892 ret = false;
6895 if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
6896 ret = false;
6899 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6900 ret = false;
6903 return ret;
6906 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
6907 struct torture_context *tctx,
6908 struct policy_handle *handle, uint32_t rid)
6910 struct samr_OpenGroup r;
6911 struct policy_handle group_handle;
6912 bool ret = true;
6914 torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
6916 r.in.domain_handle = handle;
6917 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6918 r.in.rid = rid;
6919 r.out.group_handle = &group_handle;
6921 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
6922 "OpenGroup failed");
6923 if (!NT_STATUS_IS_OK(r.out.result)) {
6924 torture_result(tctx, TORTURE_FAIL, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6925 return false;
6928 if (!torture_setting_bool(tctx, "samba3", false)) {
6929 if (!test_QuerySecurity(b, tctx, &group_handle)) {
6930 ret = false;
6934 if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
6935 ret = false;
6938 if (!test_QueryGroupMember(b, tctx, &group_handle)) {
6939 ret = false;
6942 if (!test_samr_handle_Close(b, tctx, &group_handle)) {
6943 ret = false;
6946 return ret;
6949 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
6950 struct torture_context *tctx,
6951 struct policy_handle *handle, uint32_t rid)
6953 struct samr_OpenAlias r;
6954 struct policy_handle alias_handle;
6955 bool ret = true;
6957 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
6959 r.in.domain_handle = handle;
6960 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6961 r.in.rid = rid;
6962 r.out.alias_handle = &alias_handle;
6964 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
6965 "OpenAlias failed");
6966 if (!NT_STATUS_IS_OK(r.out.result)) {
6967 torture_result(tctx, TORTURE_FAIL, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
6968 return false;
6971 if (!torture_setting_bool(tctx, "samba3", false)) {
6972 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
6973 ret = false;
6977 if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
6978 ret = false;
6981 if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
6982 ret = false;
6985 if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
6986 ret = false;
6989 return ret;
6992 static bool check_mask(struct dcerpc_binding_handle *b,
6993 struct torture_context *tctx,
6994 struct policy_handle *handle, uint32_t rid,
6995 uint32_t acct_flag_mask)
6997 struct samr_OpenUser r;
6998 struct samr_QueryUserInfo q;
6999 union samr_UserInfo *info;
7000 struct policy_handle user_handle;
7001 bool ret = true;
7003 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
7005 r.in.domain_handle = handle;
7006 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7007 r.in.rid = rid;
7008 r.out.user_handle = &user_handle;
7010 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
7011 "OpenUser failed");
7012 if (!NT_STATUS_IS_OK(r.out.result)) {
7013 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
7014 return false;
7017 q.in.user_handle = &user_handle;
7018 q.in.level = 16;
7019 q.out.info = &info;
7021 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
7022 "QueryUserInfo failed");
7023 if (!NT_STATUS_IS_OK(q.out.result)) {
7024 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo level 16 failed - %s\n",
7025 nt_errstr(q.out.result));
7026 ret = false;
7027 } else {
7028 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
7029 torture_result(tctx, TORTURE_FAIL, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
7030 acct_flag_mask, info->info16.acct_flags, rid);
7031 ret = false;
7035 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
7036 ret = false;
7039 return ret;
7042 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
7043 struct torture_context *tctx,
7044 struct policy_handle *handle)
7046 struct samr_EnumDomainUsers r;
7047 uint32_t mask, resume_handle=0;
7048 int i, mask_idx;
7049 bool ret = true;
7050 struct samr_LookupNames n;
7051 struct samr_LookupRids lr ;
7052 struct lsa_Strings names;
7053 struct samr_Ids rids, types;
7054 struct samr_SamArray *sam = NULL;
7055 uint32_t num_entries = 0;
7057 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
7058 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
7059 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
7060 ACB_PWNOEXP, 0};
7062 torture_comment(tctx, "Testing EnumDomainUsers\n");
7064 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
7065 r.in.domain_handle = handle;
7066 r.in.resume_handle = &resume_handle;
7067 r.in.acct_flags = mask = masks[mask_idx];
7068 r.in.max_size = (uint32_t)-1;
7069 r.out.resume_handle = &resume_handle;
7070 r.out.num_entries = &num_entries;
7071 r.out.sam = &sam;
7073 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7074 "EnumDomainUsers failed");
7075 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
7076 !NT_STATUS_IS_OK(r.out.result)) {
7077 torture_result(tctx, TORTURE_FAIL, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
7078 return false;
7081 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
7083 if (sam->count == 0) {
7084 continue;
7087 for (i=0;i<sam->count;i++) {
7088 if (mask) {
7089 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
7090 ret = false;
7092 } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
7093 ret = false;
7098 torture_comment(tctx, "Testing LookupNames\n");
7099 n.in.domain_handle = handle;
7100 n.in.num_names = sam->count;
7101 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
7102 n.out.rids = &rids;
7103 n.out.types = &types;
7104 for (i=0;i<sam->count;i++) {
7105 n.in.names[i].string = sam->entries[i].name.string;
7107 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
7108 "LookupNames failed");
7109 if (!NT_STATUS_IS_OK(n.out.result)) {
7110 torture_result(tctx, TORTURE_FAIL, "LookupNames failed - %s\n", nt_errstr(n.out.result));
7111 ret = false;
7115 torture_comment(tctx, "Testing LookupRids\n");
7116 lr.in.domain_handle = handle;
7117 lr.in.num_rids = sam->count;
7118 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
7119 lr.out.names = &names;
7120 lr.out.types = &types;
7121 for (i=0;i<sam->count;i++) {
7122 lr.in.rids[i] = sam->entries[i].idx;
7124 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
7125 "LookupRids failed");
7126 torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
7128 return ret;
7132 try blasting the server with a bunch of sync requests
7134 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
7135 struct policy_handle *handle)
7137 struct samr_EnumDomainUsers r;
7138 uint32_t resume_handle=0;
7139 int i;
7140 #define ASYNC_COUNT 100
7141 struct tevent_req *req[ASYNC_COUNT];
7143 if (!torture_setting_bool(tctx, "dangerous", false)) {
7144 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
7147 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
7149 r.in.domain_handle = handle;
7150 r.in.resume_handle = &resume_handle;
7151 r.in.acct_flags = 0;
7152 r.in.max_size = (uint32_t)-1;
7153 r.out.resume_handle = &resume_handle;
7155 for (i=0;i<ASYNC_COUNT;i++) {
7156 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
7159 for (i=0;i<ASYNC_COUNT;i++) {
7160 tevent_req_poll(req[i], tctx->ev);
7161 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
7162 talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
7163 i, nt_errstr(r.out.result)));
7166 torture_comment(tctx, "%d async requests OK\n", i);
7168 return true;
7171 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
7172 struct torture_context *tctx,
7173 struct policy_handle *handle)
7175 struct samr_EnumDomainGroups r;
7176 uint32_t resume_handle=0;
7177 struct samr_SamArray *sam = NULL;
7178 uint32_t num_entries = 0;
7179 int i;
7180 bool ret = true;
7181 bool universal_group_found = false;
7183 torture_comment(tctx, "Testing EnumDomainGroups\n");
7185 r.in.domain_handle = handle;
7186 r.in.resume_handle = &resume_handle;
7187 r.in.max_size = (uint32_t)-1;
7188 r.out.resume_handle = &resume_handle;
7189 r.out.num_entries = &num_entries;
7190 r.out.sam = &sam;
7192 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7193 "EnumDomainGroups failed");
7194 if (!NT_STATUS_IS_OK(r.out.result)) {
7195 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
7196 return false;
7199 if (!sam) {
7200 return false;
7203 for (i=0;i<sam->count;i++) {
7204 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
7205 ret = false;
7207 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
7208 "Enterprise Admins") == 0)) {
7209 universal_group_found = true;
7213 /* when we are running this on s4 we should get back at least the
7214 * "Enterprise Admins" universal group. If we don't get a group entry
7215 * at all we probably are performing the test on the builtin domain.
7216 * So ignore this case. */
7217 if (torture_setting_bool(tctx, "samba4", false)) {
7218 if ((sam->count > 0) && (!universal_group_found)) {
7219 ret = false;
7223 return ret;
7226 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
7227 struct torture_context *tctx,
7228 struct policy_handle *handle)
7230 struct samr_EnumDomainAliases r;
7231 uint32_t resume_handle=0;
7232 struct samr_SamArray *sam = NULL;
7233 uint32_t num_entries = 0;
7234 int i;
7235 bool ret = true;
7237 torture_comment(tctx, "Testing EnumDomainAliases\n");
7239 r.in.domain_handle = handle;
7240 r.in.resume_handle = &resume_handle;
7241 r.in.max_size = (uint32_t)-1;
7242 r.out.sam = &sam;
7243 r.out.num_entries = &num_entries;
7244 r.out.resume_handle = &resume_handle;
7246 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7247 "EnumDomainAliases failed");
7248 if (!NT_STATUS_IS_OK(r.out.result)) {
7249 torture_result(tctx, TORTURE_FAIL, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
7250 return false;
7253 if (!sam) {
7254 return false;
7257 for (i=0;i<sam->count;i++) {
7258 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
7259 ret = false;
7263 return ret;
7266 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
7267 struct torture_context *tctx,
7268 struct policy_handle *handle)
7270 struct samr_GetDisplayEnumerationIndex r;
7271 bool ret = true;
7272 uint16_t levels[] = {1, 2, 3, 4, 5};
7273 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
7274 struct lsa_String name;
7275 uint32_t idx = 0;
7276 int i;
7278 for (i=0;i<ARRAY_SIZE(levels);i++) {
7279 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
7281 init_lsa_String(&name, TEST_ACCOUNT_NAME);
7283 r.in.domain_handle = handle;
7284 r.in.level = levels[i];
7285 r.in.name = &name;
7286 r.out.idx = &idx;
7288 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
7289 "GetDisplayEnumerationIndex failed");
7291 if (ok_lvl[i] &&
7292 !NT_STATUS_IS_OK(r.out.result) &&
7293 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
7294 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
7295 levels[i], nt_errstr(r.out.result));
7296 ret = false;
7299 init_lsa_String(&name, "zzzzzzzz");
7301 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
7302 "GetDisplayEnumerationIndex failed");
7304 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
7305 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex level %u failed - %s\n",
7306 levels[i], nt_errstr(r.out.result));
7307 ret = false;
7311 return ret;
7314 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
7315 struct torture_context *tctx,
7316 struct policy_handle *handle)
7318 struct samr_GetDisplayEnumerationIndex2 r;
7319 bool ret = true;
7320 uint16_t levels[] = {1, 2, 3, 4, 5};
7321 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
7322 struct lsa_String name;
7323 uint32_t idx = 0;
7324 int i;
7326 for (i=0;i<ARRAY_SIZE(levels);i++) {
7327 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
7329 init_lsa_String(&name, TEST_ACCOUNT_NAME);
7331 r.in.domain_handle = handle;
7332 r.in.level = levels[i];
7333 r.in.name = &name;
7334 r.out.idx = &idx;
7336 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
7337 "GetDisplayEnumerationIndex2 failed");
7338 if (ok_lvl[i] &&
7339 !NT_STATUS_IS_OK(r.out.result) &&
7340 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
7341 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
7342 levels[i], nt_errstr(r.out.result));
7343 ret = false;
7346 init_lsa_String(&name, "zzzzzzzz");
7348 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
7349 "GetDisplayEnumerationIndex2 failed");
7350 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
7351 torture_result(tctx, TORTURE_FAIL, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
7352 levels[i], nt_errstr(r.out.result));
7353 ret = false;
7357 return ret;
7360 #define STRING_EQUAL_QUERY(s1, s2, user) \
7361 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
7362 /* odd, but valid */ \
7363 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
7364 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: %s != %s (%s)\n", \
7365 #s1, user.string, s1.string, s2.string, __location__); \
7366 ret = false; \
7368 #define INT_EQUAL_QUERY(s1, s2, user) \
7369 if (s1 != s2) { \
7370 torture_result(tctx, TORTURE_FAIL, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
7371 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
7372 ret = false; \
7375 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
7376 struct torture_context *tctx,
7377 struct samr_QueryDisplayInfo *querydisplayinfo,
7378 bool *seen_testuser)
7380 struct samr_OpenUser r = {
7381 .in = {
7382 .domain_handle = querydisplayinfo->in.domain_handle,
7383 .access_mask = SEC_FLAG_MAXIMUM_ALLOWED,
7386 struct samr_QueryUserInfo q;
7387 union samr_UserInfo *info;
7388 struct policy_handle user_handle;
7389 int i, ret = true;
7391 for (i = 0; ; i++) {
7392 switch (querydisplayinfo->in.level) {
7393 case 1:
7394 if (i >= querydisplayinfo->out.info->info1.count) {
7395 return ret;
7397 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
7398 break;
7399 case 2:
7400 if (i >= querydisplayinfo->out.info->info2.count) {
7401 return ret;
7403 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
7404 break;
7405 case 3:
7406 /* Groups */
7407 case 4:
7408 case 5:
7409 /* Not interested in validating just the account name */
7410 return true;
7413 r.out.user_handle = &user_handle;
7415 switch (querydisplayinfo->in.level) {
7416 case 1:
7417 case 2:
7418 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
7419 "OpenUser failed");
7420 if (!NT_STATUS_IS_OK(r.out.result)) {
7421 torture_result(tctx, TORTURE_FAIL, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
7422 return false;
7426 q.in.user_handle = &user_handle;
7427 q.in.level = 21;
7428 q.out.info = &info;
7429 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
7430 "QueryUserInfo failed");
7431 if (!NT_STATUS_IS_OK(r.out.result)) {
7432 torture_result(tctx, TORTURE_FAIL, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
7433 return false;
7436 switch (querydisplayinfo->in.level) {
7437 case 1:
7438 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
7439 *seen_testuser = true;
7441 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
7442 info->info21.full_name, info->info21.account_name);
7443 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
7444 info->info21.account_name, info->info21.account_name);
7445 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
7446 info->info21.description, info->info21.account_name);
7447 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
7448 info->info21.rid, info->info21.account_name);
7449 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
7450 info->info21.acct_flags, info->info21.account_name);
7452 break;
7453 case 2:
7454 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
7455 info->info21.account_name, info->info21.account_name);
7456 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
7457 info->info21.description, info->info21.account_name);
7458 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
7459 info->info21.rid, info->info21.account_name);
7460 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
7461 info->info21.acct_flags, info->info21.account_name);
7463 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
7464 torture_result(tctx, TORTURE_FAIL, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
7465 info->info21.account_name.string);
7468 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
7469 torture_result(tctx, TORTURE_FAIL, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
7470 info->info21.account_name.string,
7471 querydisplayinfo->out.info->info2.entries[i].acct_flags,
7472 info->info21.acct_flags);
7473 return false;
7476 break;
7479 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
7480 return false;
7483 return ret;
7486 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
7487 struct torture_context *tctx,
7488 struct policy_handle *handle)
7490 struct samr_QueryDisplayInfo r;
7491 struct samr_QueryDomainInfo dom_info;
7492 union samr_DomainInfo *info = NULL;
7493 bool ret = true;
7494 uint16_t levels[] = {1, 2, 3, 4, 5};
7495 int i;
7496 bool seen_testuser = false;
7497 uint32_t total_size;
7498 uint32_t returned_size;
7499 union samr_DispInfo disp_info;
7502 for (i=0;i<ARRAY_SIZE(levels);i++) {
7503 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
7505 r.in.start_idx = 0;
7506 r.out.result = STATUS_MORE_ENTRIES;
7507 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
7508 r.in.domain_handle = handle;
7509 r.in.level = levels[i];
7510 r.in.max_entries = 2;
7511 r.in.buf_size = (uint32_t)-1;
7512 r.out.total_size = &total_size;
7513 r.out.returned_size = &returned_size;
7514 r.out.info = &disp_info;
7516 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7517 "QueryDisplayInfo failed");
7518 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
7519 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
7520 levels[i], nt_errstr(r.out.result));
7521 ret = false;
7523 switch (r.in.level) {
7524 case 1:
7525 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
7526 ret = false;
7528 r.in.start_idx += r.out.info->info1.count;
7529 break;
7530 case 2:
7531 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
7532 ret = false;
7534 r.in.start_idx += r.out.info->info2.count;
7535 break;
7536 case 3:
7537 r.in.start_idx += r.out.info->info3.count;
7538 break;
7539 case 4:
7540 r.in.start_idx += r.out.info->info4.count;
7541 break;
7542 case 5:
7543 r.in.start_idx += r.out.info->info5.count;
7544 break;
7547 dom_info.in.domain_handle = handle;
7548 dom_info.in.level = 2;
7549 dom_info.out.info = &info;
7551 /* Check number of users returned is correct */
7552 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
7553 "QueryDomainInfo failed");
7554 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
7555 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7556 r.in.level, nt_errstr(dom_info.out.result));
7557 ret = false;
7558 break;
7560 switch (r.in.level) {
7561 case 1:
7562 case 4:
7563 if (info->general.num_users < r.in.start_idx) {
7564 /* On AD deployments this numbers don't match
7565 * since QueryDisplayInfo returns universal and
7566 * global groups, QueryDomainInfo only global
7567 * ones. */
7568 if (torture_setting_bool(tctx, "samba3", false)) {
7569 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
7570 r.in.start_idx, info->general.num_groups,
7571 info->general.domain_name.string);
7572 ret = false;
7575 if (!seen_testuser) {
7576 struct policy_handle user_handle;
7577 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
7578 torture_result(tctx, TORTURE_FAIL, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
7579 info->general.domain_name.string);
7580 ret = false;
7581 test_samr_handle_Close(b, tctx, &user_handle);
7584 break;
7585 case 3:
7586 case 5:
7587 if (info->general.num_groups != r.in.start_idx) {
7588 /* On AD deployments this numbers don't match
7589 * since QueryDisplayInfo returns universal and
7590 * global groups, QueryDomainInfo only global
7591 * ones. */
7592 if (torture_setting_bool(tctx, "samba3", false)) {
7593 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
7594 r.in.start_idx, info->general.num_groups,
7595 info->general.domain_name.string);
7596 ret = false;
7600 break;
7605 return ret;
7608 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
7609 struct torture_context *tctx,
7610 struct policy_handle *handle)
7612 struct samr_QueryDisplayInfo2 r;
7613 bool ret = true;
7614 uint16_t levels[] = {1, 2, 3, 4, 5};
7615 int i;
7616 uint32_t total_size;
7617 uint32_t returned_size;
7618 union samr_DispInfo info;
7620 for (i=0;i<ARRAY_SIZE(levels);i++) {
7621 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
7623 r.in.domain_handle = handle;
7624 r.in.level = levels[i];
7625 r.in.start_idx = 0;
7626 r.in.max_entries = 1000;
7627 r.in.buf_size = (uint32_t)-1;
7628 r.out.total_size = &total_size;
7629 r.out.returned_size = &returned_size;
7630 r.out.info = &info;
7632 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
7633 "QueryDisplayInfo2 failed");
7634 if (!NT_STATUS_IS_OK(r.out.result)) {
7635 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo2 level %u failed - %s\n",
7636 levels[i], nt_errstr(r.out.result));
7637 ret = false;
7641 return ret;
7644 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
7645 struct torture_context *tctx,
7646 struct policy_handle *handle)
7648 struct samr_QueryDisplayInfo3 r;
7649 bool ret = true;
7650 uint16_t levels[] = {1, 2, 3, 4, 5};
7651 int i;
7652 uint32_t total_size;
7653 uint32_t returned_size;
7654 union samr_DispInfo info;
7656 for (i=0;i<ARRAY_SIZE(levels);i++) {
7657 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
7659 r.in.domain_handle = handle;
7660 r.in.level = levels[i];
7661 r.in.start_idx = 0;
7662 r.in.max_entries = 1000;
7663 r.in.buf_size = (uint32_t)-1;
7664 r.out.total_size = &total_size;
7665 r.out.returned_size = &returned_size;
7666 r.out.info = &info;
7668 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
7669 "QueryDisplayInfo3 failed");
7670 if (!NT_STATUS_IS_OK(r.out.result)) {
7671 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo3 level %u failed - %s\n",
7672 levels[i], nt_errstr(r.out.result));
7673 ret = false;
7677 return ret;
7681 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
7682 struct torture_context *tctx,
7683 struct policy_handle *handle)
7685 struct samr_QueryDisplayInfo r;
7686 bool ret = true;
7687 uint32_t total_size;
7688 uint32_t returned_size;
7689 union samr_DispInfo info;
7691 torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
7693 r.in.domain_handle = handle;
7694 r.in.level = 1;
7695 r.in.start_idx = 0;
7696 r.in.max_entries = 1;
7697 r.in.buf_size = (uint32_t)-1;
7698 r.out.total_size = &total_size;
7699 r.out.returned_size = &returned_size;
7700 r.out.info = &info;
7702 do {
7703 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7704 "QueryDisplayInfo failed");
7705 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
7706 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
7707 torture_result(tctx, TORTURE_FAIL, "expected idx %d but got %d\n",
7708 r.in.start_idx + 1,
7709 r.out.info->info1.entries[0].idx);
7710 break;
7713 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
7714 !NT_STATUS_IS_OK(r.out.result)) {
7715 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level %u failed - %s\n",
7716 r.in.level, nt_errstr(r.out.result));
7717 ret = false;
7718 break;
7720 r.in.start_idx++;
7721 } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
7722 NT_STATUS_IS_OK(r.out.result)) &&
7723 *r.out.returned_size != 0);
7725 return ret;
7728 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
7729 struct torture_context *tctx,
7730 struct policy_handle *handle)
7732 struct samr_QueryDomainInfo r;
7733 union samr_DomainInfo *info = NULL;
7734 struct samr_SetDomainInfo s;
7735 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
7736 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
7737 int i;
7738 bool ret = true;
7739 struct dcerpc_binding_handle *b = p->binding_handle;
7740 const char *domain_comment = talloc_asprintf(tctx,
7741 "Tortured by Samba4 RPC-SAMR: %s",
7742 timestring(tctx, time(NULL)));
7744 s.in.domain_handle = handle;
7745 s.in.level = 4;
7746 s.in.info = talloc(tctx, union samr_DomainInfo);
7748 s.in.info->oem.oem_information.string = domain_comment;
7749 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
7750 "SetDomainInfo failed");
7751 if (!NT_STATUS_IS_OK(s.out.result)) {
7752 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u (set comment) failed - %s\n",
7753 s.in.level, nt_errstr(s.out.result));
7754 return false;
7757 for (i=0;i<ARRAY_SIZE(levels);i++) {
7758 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
7760 r.in.domain_handle = handle;
7761 r.in.level = levels[i];
7762 r.out.info = &info;
7764 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
7765 "QueryDomainInfo failed");
7766 if (!NT_STATUS_IS_OK(r.out.result)) {
7767 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7768 r.in.level, nt_errstr(r.out.result));
7769 ret = false;
7770 continue;
7773 switch (levels[i]) {
7774 case 2:
7775 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
7776 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
7777 levels[i], info->general.oem_information.string, domain_comment);
7778 if (!torture_setting_bool(tctx, "samba3", false)) {
7779 ret = false;
7782 if (!info->general.primary.string) {
7783 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
7784 levels[i]);
7785 ret = false;
7786 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
7787 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
7788 if (torture_setting_bool(tctx, "samba3", false)) {
7789 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
7790 levels[i], info->general.primary.string, dcerpc_server_name(p));
7794 break;
7795 case 4:
7796 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
7797 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
7798 levels[i], info->oem.oem_information.string, domain_comment);
7799 if (!torture_setting_bool(tctx, "samba3", false)) {
7800 ret = false;
7803 break;
7804 case 6:
7805 if (!info->info6.primary.string) {
7806 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned no PDC name\n",
7807 levels[i]);
7808 ret = false;
7810 break;
7811 case 11:
7812 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
7813 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
7814 levels[i], info->general2.general.oem_information.string, domain_comment);
7815 if (!torture_setting_bool(tctx, "samba3", false)) {
7816 ret = false;
7819 break;
7822 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
7824 s.in.domain_handle = handle;
7825 s.in.level = levels[i];
7826 s.in.info = info;
7828 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
7829 "SetDomainInfo failed");
7830 if (set_ok[i]) {
7831 if (!NT_STATUS_IS_OK(s.out.result)) {
7832 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u failed - %s\n",
7833 r.in.level, nt_errstr(s.out.result));
7834 ret = false;
7835 continue;
7837 } else {
7838 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
7839 torture_result(tctx, TORTURE_FAIL, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
7840 r.in.level, nt_errstr(s.out.result));
7841 ret = false;
7842 continue;
7846 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
7847 "QueryDomainInfo failed");
7848 if (!NT_STATUS_IS_OK(r.out.result)) {
7849 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo level %u failed - %s\n",
7850 r.in.level, nt_errstr(r.out.result));
7851 ret = false;
7852 continue;
7856 return ret;
7860 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
7861 struct torture_context *tctx,
7862 struct policy_handle *handle)
7864 struct samr_QueryDomainInfo2 r;
7865 union samr_DomainInfo *info = NULL;
7866 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
7867 int i;
7868 bool ret = true;
7870 for (i=0;i<ARRAY_SIZE(levels);i++) {
7871 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
7873 r.in.domain_handle = handle;
7874 r.in.level = levels[i];
7875 r.out.info = &info;
7877 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7878 "QueryDomainInfo2 failed");
7879 if (!NT_STATUS_IS_OK(r.out.result)) {
7880 torture_result(tctx, TORTURE_FAIL, "QueryDomainInfo2 level %u failed - %s\n",
7881 r.in.level, nt_errstr(r.out.result));
7882 ret = false;
7883 continue;
7887 return ret;
7890 /* Test whether querydispinfo level 5 and enumdomgroups return the same
7891 set of group names. */
7892 static bool test_GroupList(struct dcerpc_binding_handle *b,
7893 struct torture_context *tctx,
7894 struct dom_sid *domain_sid,
7895 struct policy_handle *handle)
7897 struct samr_EnumDomainGroups q1;
7898 struct samr_QueryDisplayInfo q2;
7899 NTSTATUS status;
7900 uint32_t resume_handle=0;
7901 struct samr_SamArray *sam = NULL;
7902 uint32_t num_entries = 0;
7903 int i;
7904 bool ret = true;
7905 uint32_t total_size;
7906 uint32_t returned_size;
7907 union samr_DispInfo info;
7909 size_t num_names = 0;
7910 const char **names = NULL;
7912 bool builtin_domain = dom_sid_compare(domain_sid,
7913 &global_sid_Builtin) == 0;
7915 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
7917 q1.in.domain_handle = handle;
7918 q1.in.resume_handle = &resume_handle;
7919 q1.in.max_size = 5;
7920 q1.out.resume_handle = &resume_handle;
7921 q1.out.num_entries = &num_entries;
7922 q1.out.sam = &sam;
7924 status = STATUS_MORE_ENTRIES;
7925 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7926 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
7927 "EnumDomainGroups failed");
7928 status = q1.out.result;
7930 if (!NT_STATUS_IS_OK(status) &&
7931 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7932 break;
7934 for (i=0; i<*q1.out.num_entries; i++) {
7935 add_string_to_array(tctx,
7936 sam->entries[i].name.string,
7937 &names, &num_names);
7941 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
7943 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
7945 if (builtin_domain) {
7946 torture_assert(tctx, num_names == 0,
7947 "EnumDomainGroups shouldn't return any group in the builtin domain!");
7950 q2.in.domain_handle = handle;
7951 q2.in.level = 5;
7952 q2.in.start_idx = 0;
7953 q2.in.max_entries = 5;
7954 q2.in.buf_size = (uint32_t)-1;
7955 q2.out.total_size = &total_size;
7956 q2.out.returned_size = &returned_size;
7957 q2.out.info = &info;
7959 status = STATUS_MORE_ENTRIES;
7960 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
7961 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
7962 "QueryDisplayInfo failed");
7963 status = q2.out.result;
7964 if (!NT_STATUS_IS_OK(status) &&
7965 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
7966 break;
7968 for (i=0; i<q2.out.info->info5.count; i++) {
7969 int j;
7970 const char *name = q2.out.info->info5.entries[i].account_name.string;
7971 bool found = false;
7972 for (j=0; j<num_names; j++) {
7973 if (names[j] == NULL)
7974 continue;
7975 if (strequal(names[j], name)) {
7976 names[j] = NULL;
7977 found = true;
7978 break;
7982 if ((!found) && (!builtin_domain)) {
7983 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
7984 name);
7985 ret = false;
7988 q2.in.start_idx += q2.out.info->info5.count;
7991 if (!NT_STATUS_IS_OK(status)) {
7992 torture_result(tctx, TORTURE_FAIL, "QueryDisplayInfo level 5 failed - %s\n",
7993 nt_errstr(status));
7994 ret = false;
7997 if (builtin_domain) {
7998 torture_assert(tctx, q2.in.start_idx != 0,
7999 "QueryDisplayInfo should return all domain groups also on the builtin domain handle!");
8002 for (i=0; i<num_names; i++) {
8003 if (names[i] != NULL) {
8004 torture_result(tctx, TORTURE_FAIL, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
8005 names[i]);
8006 ret = false;
8010 return ret;
8013 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
8014 struct torture_context *tctx,
8015 struct policy_handle *group_handle)
8017 struct samr_DeleteDomainGroup d;
8019 torture_comment(tctx, "Testing DeleteDomainGroup\n");
8021 d.in.group_handle = group_handle;
8022 d.out.group_handle = group_handle;
8024 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
8025 "DeleteDomainGroup failed");
8026 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
8028 return true;
8031 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
8032 struct torture_context *tctx,
8033 struct policy_handle *domain_handle)
8035 struct samr_TestPrivateFunctionsDomain r;
8036 bool ret = true;
8038 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
8040 r.in.domain_handle = domain_handle;
8042 torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
8043 "TestPrivateFunctionsDomain failed");
8044 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
8046 return ret;
8049 static bool test_RidToSid(struct dcerpc_binding_handle *b,
8050 struct torture_context *tctx,
8051 struct dom_sid *domain_sid,
8052 struct policy_handle *domain_handle)
8054 struct samr_RidToSid r;
8055 bool ret = true;
8056 struct dom_sid *calc_sid, *out_sid;
8057 int rids[] = { 0, 42, 512, 10200 };
8058 int i;
8060 for (i=0;i<ARRAY_SIZE(rids);i++) {
8061 torture_comment(tctx, "Testing RidToSid\n");
8063 calc_sid = dom_sid_dup(tctx, domain_sid);
8064 r.in.domain_handle = domain_handle;
8065 r.in.rid = rids[i];
8066 r.out.sid = &out_sid;
8068 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
8069 "RidToSid failed");
8070 if (!NT_STATUS_IS_OK(r.out.result)) {
8071 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
8072 ret = false;
8073 } else {
8074 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
8076 if (!dom_sid_equal(calc_sid, out_sid)) {
8077 torture_result(tctx, TORTURE_FAIL, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
8078 dom_sid_string(tctx, out_sid),
8079 dom_sid_string(tctx, calc_sid));
8080 ret = false;
8085 return ret;
8088 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
8089 struct torture_context *tctx,
8090 struct policy_handle *domain_handle)
8092 struct samr_GetBootKeyInformation r;
8093 bool ret = true;
8094 uint32_t unknown = 0;
8095 NTSTATUS status;
8097 torture_comment(tctx, "Testing GetBootKeyInformation\n");
8099 r.in.domain_handle = domain_handle;
8100 r.out.unknown = &unknown;
8102 status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
8103 if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
8104 status = r.out.result;
8106 if (!NT_STATUS_IS_OK(status)) {
8107 /* w2k3 seems to fail this sometimes and pass it sometimes */
8108 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
8111 return ret;
8114 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
8115 struct torture_context *tctx,
8116 struct policy_handle *domain_handle,
8117 struct policy_handle *group_handle)
8119 NTSTATUS status;
8120 struct samr_AddGroupMember r;
8121 struct samr_DeleteGroupMember d;
8122 struct samr_QueryGroupMember q;
8123 struct samr_RidAttrArray *rids = NULL;
8124 struct samr_SetMemberAttributesOfGroup s;
8125 uint32_t rid;
8126 bool found_member = false;
8127 int i;
8129 status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
8130 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
8132 r.in.group_handle = group_handle;
8133 r.in.rid = rid;
8134 r.in.flags = 0; /* ??? */
8136 torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
8138 d.in.group_handle = group_handle;
8139 d.in.rid = rid;
8141 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
8142 "DeleteGroupMember failed");
8143 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
8145 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
8146 "AddGroupMember failed");
8147 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
8149 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
8150 "AddGroupMember failed");
8151 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
8153 if (torture_setting_bool(tctx, "samba4", false) ||
8154 torture_setting_bool(tctx, "samba3", false)) {
8155 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
8156 } else {
8157 /* this one is quite strange. I am using random inputs in the
8158 hope of triggering an error that might give us a clue */
8160 s.in.group_handle = group_handle;
8161 s.in.unknown1 = random();
8162 s.in.unknown2 = random();
8164 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
8165 "SetMemberAttributesOfGroup failed");
8166 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
8169 q.in.group_handle = group_handle;
8170 q.out.rids = &rids;
8172 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
8173 "QueryGroupMember failed");
8174 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
8175 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
8177 for (i=0; i < rids->count; i++) {
8178 if (rids->rids[i] == rid) {
8179 found_member = true;
8183 torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
8185 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
8186 "DeleteGroupMember failed");
8187 torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
8189 rids = NULL;
8190 found_member = false;
8192 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
8193 "QueryGroupMember failed");
8194 torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
8195 torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
8197 for (i=0; i < rids->count; i++) {
8198 if (rids->rids[i] == rid) {
8199 found_member = true;
8203 torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
8205 torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
8206 "AddGroupMember failed");
8207 torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
8209 return true;
8213 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
8214 struct torture_context *tctx,
8215 struct policy_handle *domain_handle,
8216 const char *group_name,
8217 struct policy_handle *group_handle,
8218 struct dom_sid *domain_sid,
8219 bool test_group)
8221 struct samr_CreateDomainGroup r;
8222 uint32_t rid;
8223 struct lsa_String name;
8224 bool ret = true;
8226 init_lsa_String(&name, group_name);
8228 r.in.domain_handle = domain_handle;
8229 r.in.name = &name;
8230 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8231 r.out.group_handle = group_handle;
8232 r.out.rid = &rid;
8234 torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
8236 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
8237 "CreateDomainGroup failed");
8239 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
8240 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
8241 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
8242 return true;
8243 } else {
8244 torture_result(tctx, TORTURE_FAIL, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
8245 nt_errstr(r.out.result));
8246 return false;
8250 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
8251 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
8252 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
8253 nt_errstr(r.out.result));
8254 return false;
8256 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
8257 "CreateDomainGroup failed");
8259 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
8260 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
8262 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
8263 nt_errstr(r.out.result));
8264 return false;
8266 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
8267 "CreateDomainGroup failed");
8269 torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
8271 if (!test_group) {
8272 return ret;
8275 if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
8276 torture_result(tctx, TORTURE_FAIL, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
8277 ret = false;
8280 if (!test_SetGroupInfo(b, tctx, group_handle)) {
8281 ret = false;
8284 return ret;
8289 its not totally clear what this does. It seems to accept any sid you like.
8291 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
8292 struct torture_context *tctx,
8293 struct policy_handle *domain_handle)
8295 struct samr_RemoveMemberFromForeignDomain r;
8297 r.in.domain_handle = domain_handle;
8298 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
8300 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
8301 "RemoveMemberFromForeignDomain failed");
8302 torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
8304 return true;
8307 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
8308 struct torture_context *tctx,
8309 struct policy_handle *domain_handle,
8310 uint32_t *total_num_entries_p)
8312 NTSTATUS status;
8313 struct samr_EnumDomainUsers r;
8314 uint32_t resume_handle = 0;
8315 uint32_t num_entries = 0;
8316 uint32_t total_num_entries = 0;
8317 struct samr_SamArray *sam;
8319 r.in.domain_handle = domain_handle;
8320 r.in.acct_flags = 0;
8321 r.in.max_size = (uint32_t)-1;
8322 r.in.resume_handle = &resume_handle;
8324 r.out.sam = &sam;
8325 r.out.num_entries = &num_entries;
8326 r.out.resume_handle = &resume_handle;
8328 torture_comment(tctx, "Testing EnumDomainUsers\n");
8330 do {
8331 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
8332 "EnumDomainUsers failed");
8333 if (NT_STATUS_IS_ERR(r.out.result)) {
8334 torture_assert_ntstatus_ok(tctx, r.out.result,
8335 "failed to enumerate users");
8337 status = r.out.result;
8339 total_num_entries += num_entries;
8340 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
8342 if (total_num_entries_p) {
8343 *total_num_entries_p = total_num_entries;
8346 return true;
8349 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
8350 struct torture_context *tctx,
8351 struct policy_handle *domain_handle,
8352 uint32_t *total_num_entries_p)
8354 NTSTATUS status;
8355 struct samr_EnumDomainGroups r;
8356 uint32_t resume_handle = 0;
8357 uint32_t num_entries = 0;
8358 uint32_t total_num_entries = 0;
8359 struct samr_SamArray *sam;
8361 r.in.domain_handle = domain_handle;
8362 r.in.max_size = (uint32_t)-1;
8363 r.in.resume_handle = &resume_handle;
8365 r.out.sam = &sam;
8366 r.out.num_entries = &num_entries;
8367 r.out.resume_handle = &resume_handle;
8369 torture_comment(tctx, "Testing EnumDomainGroups\n");
8371 do {
8372 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
8373 "EnumDomainGroups failed");
8374 if (NT_STATUS_IS_ERR(r.out.result)) {
8375 torture_assert_ntstatus_ok(tctx, r.out.result,
8376 "failed to enumerate groups");
8378 status = r.out.result;
8380 total_num_entries += num_entries;
8381 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
8383 if (total_num_entries_p) {
8384 *total_num_entries_p = total_num_entries;
8387 return true;
8390 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
8391 struct torture_context *tctx,
8392 struct policy_handle *domain_handle,
8393 uint32_t *total_num_entries_p)
8395 NTSTATUS status;
8396 struct samr_EnumDomainAliases r;
8397 uint32_t resume_handle = 0;
8398 uint32_t num_entries = 0;
8399 uint32_t total_num_entries = 0;
8400 struct samr_SamArray *sam;
8402 r.in.domain_handle = domain_handle;
8403 r.in.max_size = (uint32_t)-1;
8404 r.in.resume_handle = &resume_handle;
8406 r.out.sam = &sam;
8407 r.out.num_entries = &num_entries;
8408 r.out.resume_handle = &resume_handle;
8410 torture_comment(tctx, "Testing EnumDomainAliases\n");
8412 do {
8413 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
8414 "EnumDomainAliases failed");
8415 if (NT_STATUS_IS_ERR(r.out.result)) {
8416 torture_assert_ntstatus_ok(tctx, r.out.result,
8417 "failed to enumerate aliases");
8419 status = r.out.result;
8421 total_num_entries += num_entries;
8422 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
8424 if (total_num_entries_p) {
8425 *total_num_entries_p = total_num_entries;
8428 return true;
8431 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
8432 struct torture_context *tctx,
8433 struct policy_handle *handle,
8434 uint16_t level,
8435 uint32_t *total_num_entries_p)
8437 NTSTATUS status;
8438 struct samr_QueryDisplayInfo r;
8439 uint32_t total_num_entries = 0;
8441 r.in.domain_handle = handle;
8442 r.in.level = level;
8443 r.in.start_idx = 0;
8444 r.in.max_entries = (uint32_t)-1;
8445 r.in.buf_size = (uint32_t)-1;
8447 torture_comment(tctx, "Testing QueryDisplayInfo\n");
8449 do {
8450 uint32_t total_size;
8451 uint32_t returned_size;
8452 union samr_DispInfo info;
8454 r.out.total_size = &total_size;
8455 r.out.returned_size = &returned_size;
8456 r.out.info = &info;
8458 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
8459 "failed to query displayinfo");
8460 if (NT_STATUS_IS_ERR(r.out.result)) {
8461 torture_assert_ntstatus_ok(tctx, r.out.result,
8462 "failed to query displayinfo");
8464 status = r.out.result;
8466 if (*r.out.returned_size == 0) {
8467 break;
8470 switch (r.in.level) {
8471 case 1:
8472 total_num_entries += info.info1.count;
8473 r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
8474 break;
8475 case 2:
8476 total_num_entries += info.info2.count;
8477 r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
8478 break;
8479 case 3:
8480 total_num_entries += info.info3.count;
8481 r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
8482 break;
8483 case 4:
8484 total_num_entries += info.info4.count;
8485 r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
8486 break;
8487 case 5:
8488 total_num_entries += info.info5.count;
8489 r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
8490 break;
8491 default:
8492 return false;
8495 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
8497 if (total_num_entries_p) {
8498 *total_num_entries_p = total_num_entries;
8501 return true;
8504 static bool test_ManyObjects(struct dcerpc_pipe *p,
8505 struct torture_context *tctx,
8506 struct policy_handle *domain_handle,
8507 struct dom_sid *domain_sid,
8508 struct torture_samr_context *ctx)
8510 uint32_t num_total = ctx->num_objects_large_dc;
8511 uint32_t num_enum = 0;
8512 uint32_t num_disp = 0;
8513 uint32_t num_created = 0;
8514 uint32_t num_anounced = 0;
8515 uint32_t i;
8516 struct dcerpc_binding_handle *b = p->binding_handle;
8518 struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
8520 /* query */
8523 struct samr_QueryDomainInfo2 r;
8524 union samr_DomainInfo *info;
8525 r.in.domain_handle = domain_handle;
8526 r.in.level = 2;
8527 r.out.info = &info;
8529 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
8530 "QueryDomainInfo2 failed");
8531 torture_assert_ntstatus_ok(tctx, r.out.result,
8532 "failed to query domain info");
8534 switch (ctx->choice) {
8535 case TORTURE_SAMR_MANY_ACCOUNTS:
8536 num_anounced = info->general.num_users;
8537 break;
8538 case TORTURE_SAMR_MANY_GROUPS:
8539 num_anounced = info->general.num_groups;
8540 break;
8541 case TORTURE_SAMR_MANY_ALIASES:
8542 num_anounced = info->general.num_aliases;
8543 break;
8544 default:
8545 return false;
8549 /* create */
8551 for (i=0; i < num_total; i++) {
8553 const char *name = NULL;
8555 switch (ctx->choice) {
8556 case TORTURE_SAMR_MANY_ACCOUNTS:
8557 name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
8558 torture_assert(tctx,
8559 test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false),
8560 "failed to create user");
8561 break;
8562 case TORTURE_SAMR_MANY_GROUPS:
8563 name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
8564 torture_assert(tctx,
8565 test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
8566 "failed to create group");
8567 break;
8568 case TORTURE_SAMR_MANY_ALIASES:
8569 name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
8570 torture_assert(tctx,
8571 test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false),
8572 "failed to create alias");
8573 break;
8574 default:
8575 return false;
8577 if (!ndr_policy_handle_empty(&handles[i])) {
8578 num_created++;
8582 /* enum */
8584 switch (ctx->choice) {
8585 case TORTURE_SAMR_MANY_ACCOUNTS:
8586 torture_assert(tctx,
8587 test_EnumDomainUsers(b, tctx, domain_handle, &num_enum),
8588 "failed to enum users");
8589 break;
8590 case TORTURE_SAMR_MANY_GROUPS:
8591 torture_assert(tctx,
8592 test_EnumDomainGroups(b, tctx, domain_handle, &num_enum),
8593 "failed to enum groups");
8594 break;
8595 case TORTURE_SAMR_MANY_ALIASES:
8596 torture_assert(tctx,
8597 test_EnumDomainAliases(b, tctx, domain_handle, &num_enum),
8598 "failed to enum aliases");
8599 break;
8600 default:
8601 return false;
8604 /* dispinfo */
8606 switch (ctx->choice) {
8607 case TORTURE_SAMR_MANY_ACCOUNTS:
8608 torture_assert(tctx,
8609 test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp),
8610 "failed to query display info");
8611 break;
8612 case TORTURE_SAMR_MANY_GROUPS:
8613 torture_assert(tctx,
8614 test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp),
8615 "failed to query display info");
8616 break;
8617 case TORTURE_SAMR_MANY_ALIASES:
8618 /* no aliases in dispinfo */
8619 break;
8620 default:
8621 return false;
8624 /* close or delete */
8626 for (i=0; i < num_total; i++) {
8628 if (ndr_policy_handle_empty(&handles[i])) {
8629 continue;
8632 if (torture_setting_bool(tctx, "samba3", false)) {
8633 torture_assert(tctx,
8634 test_samr_handle_Close(b, tctx, &handles[i]),
8635 "failed to close handle");
8636 } else {
8637 switch (ctx->choice) {
8638 case TORTURE_SAMR_MANY_ACCOUNTS:
8639 torture_assert(tctx,
8640 test_DeleteUser(b, tctx, &handles[i]),
8641 "failed to delete user");
8642 break;
8643 case TORTURE_SAMR_MANY_GROUPS:
8644 torture_assert(tctx,
8645 test_DeleteDomainGroup(b, tctx, &handles[i]),
8646 "failed to delete group");
8647 break;
8648 case TORTURE_SAMR_MANY_ALIASES:
8649 torture_assert(tctx,
8650 test_DeleteAlias(b, tctx, &handles[i]),
8651 "failed to delete alias");
8652 break;
8653 default:
8654 return false;
8659 talloc_free(handles);
8661 if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
8662 torture_comment(tctx,
8663 "unexpected number of results (%u) returned in enum call, expected %u\n",
8664 num_enum, num_anounced + num_created);
8666 torture_comment(tctx,
8667 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
8668 num_disp, num_anounced + num_created);
8671 return true;
8674 static bool test_Connect(struct dcerpc_binding_handle *b,
8675 struct torture_context *tctx,
8676 struct policy_handle *handle);
8678 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
8679 struct torture_samr_context *ctx, struct dom_sid *sid)
8681 struct samr_OpenDomain r;
8682 struct policy_handle domain_handle;
8683 struct policy_handle alias_handle;
8684 struct policy_handle user_handle;
8685 struct policy_handle group_handle;
8686 bool ret = true;
8687 struct dcerpc_binding_handle *b = p->binding_handle;
8689 ZERO_STRUCT(alias_handle);
8690 ZERO_STRUCT(user_handle);
8691 ZERO_STRUCT(group_handle);
8692 ZERO_STRUCT(domain_handle);
8694 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
8696 r.in.connect_handle = &ctx->handle;
8697 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8698 r.in.sid = sid;
8699 r.out.domain_handle = &domain_handle;
8701 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
8702 "OpenDomain failed");
8703 torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
8705 /* run the domain tests with the main handle closed - this tests
8706 the servers reference counting */
8707 torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
8709 switch (ctx->choice) {
8710 case TORTURE_SAMR_PASSWORDS:
8711 case TORTURE_SAMR_USER_PRIVILEGES:
8712 if (!torture_setting_bool(tctx, "samba3", false)) {
8713 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
8715 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8716 if (!ret) {
8717 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
8719 break;
8720 case TORTURE_SAMR_USER_ATTRIBUTES:
8721 if (!torture_setting_bool(tctx, "samba3", false)) {
8722 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
8724 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8725 /* This test needs 'complex' users to validate */
8726 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
8727 if (!ret) {
8728 torture_result(tctx, TORTURE_FAIL, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
8730 break;
8731 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
8732 case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
8733 case TORTURE_SAMR_PASSWORDS_LOCKOUT:
8734 if (!torture_setting_bool(tctx, "samba3", false)) {
8735 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
8737 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
8738 if (!ret) {
8739 torture_result(tctx, TORTURE_FAIL, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
8741 break;
8742 case TORTURE_SAMR_MANY_ACCOUNTS:
8743 case TORTURE_SAMR_MANY_GROUPS:
8744 case TORTURE_SAMR_MANY_ALIASES:
8745 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
8746 if (!ret) {
8747 torture_result(tctx, TORTURE_FAIL, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
8749 break;
8750 case TORTURE_SAMR_OTHER:
8751 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
8752 if (!ret) {
8753 torture_result(tctx, TORTURE_FAIL, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
8755 if (!torture_setting_bool(tctx, "samba3", false)) {
8756 ret &= test_QuerySecurity(b, tctx, &domain_handle);
8758 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
8759 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
8760 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
8761 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
8762 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
8763 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
8764 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
8765 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
8766 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
8767 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
8768 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
8769 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
8770 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
8772 if (torture_setting_bool(tctx, "samba4", false)) {
8773 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
8774 } else {
8775 ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
8776 ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
8778 ret &= test_GroupList(b, tctx, sid, &domain_handle);
8779 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
8780 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
8781 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
8782 if (!ret) {
8783 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
8785 break;
8788 if (!ndr_policy_handle_empty(&user_handle) &&
8789 !test_DeleteUser(b, tctx, &user_handle)) {
8790 ret = false;
8793 if (!ndr_policy_handle_empty(&alias_handle) &&
8794 !test_DeleteAlias(b, tctx, &alias_handle)) {
8795 ret = false;
8798 if (!ndr_policy_handle_empty(&group_handle) &&
8799 !test_DeleteDomainGroup(b, tctx, &group_handle)) {
8800 ret = false;
8803 torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
8805 torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Failed to re-connect SAMR handle");
8806 /* reconnect the main handle */
8808 if (!ret) {
8809 torture_result(tctx, TORTURE_FAIL, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
8812 return ret;
8815 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
8816 struct torture_samr_context *ctx, const char *domain)
8818 struct samr_LookupDomain r;
8819 struct dom_sid2 *sid = NULL;
8820 struct lsa_String n1;
8821 struct lsa_String n2;
8822 bool ret = true;
8823 struct dcerpc_binding_handle *b = p->binding_handle;
8825 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
8827 /* check for correct error codes */
8828 r.in.connect_handle = &ctx->handle;
8829 r.in.domain_name = &n2;
8830 r.out.sid = &sid;
8831 n2.string = NULL;
8833 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8834 "LookupDomain failed");
8835 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
8837 init_lsa_String(&n2, "xxNODOMAINxx");
8839 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8840 "LookupDomain failed");
8841 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
8843 r.in.connect_handle = &ctx->handle;
8845 init_lsa_String(&n1, domain);
8846 r.in.domain_name = &n1;
8848 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
8849 "LookupDomain failed");
8850 torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
8852 if (!test_GetDomPwInfo(p, tctx, &n1)) {
8853 ret = false;
8856 if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
8857 ret = false;
8860 return ret;
8864 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
8865 struct torture_samr_context *ctx)
8867 struct samr_EnumDomains r;
8868 uint32_t resume_handle = 0;
8869 uint32_t num_entries = 0;
8870 struct samr_SamArray *sam = NULL;
8871 int i;
8872 bool ret = true;
8873 struct dcerpc_binding_handle *b = p->binding_handle;
8875 r.in.connect_handle = &ctx->handle;
8876 r.in.resume_handle = &resume_handle;
8877 r.in.buf_size = (uint32_t)-1;
8878 r.out.resume_handle = &resume_handle;
8879 r.out.num_entries = &num_entries;
8880 r.out.sam = &sam;
8882 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
8883 "EnumDomains failed");
8884 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
8886 if (!*r.out.sam) {
8887 return false;
8890 for (i=0;i<sam->count;i++) {
8891 if (!test_LookupDomain(p, tctx, ctx,
8892 sam->entries[i].name.string)) {
8893 ret = false;
8897 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
8898 "EnumDomains failed");
8899 torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
8901 return ret;
8905 static bool test_Connect(struct dcerpc_binding_handle *b,
8906 struct torture_context *tctx,
8907 struct policy_handle *handle)
8909 struct samr_Connect r;
8910 struct samr_Connect2 r2;
8911 struct samr_Connect3 r3;
8912 struct samr_Connect4 r4;
8913 struct samr_Connect5 r5;
8914 union samr_ConnectInfo info;
8915 struct policy_handle h;
8916 uint32_t level_out = 0;
8917 bool ret = true, got_handle = false;
8919 torture_comment(tctx, "Testing samr_Connect\n");
8921 r.in.system_name = NULL;
8922 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8923 r.out.connect_handle = &h;
8925 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
8926 "Connect failed");
8927 if (!NT_STATUS_IS_OK(r.out.result)) {
8928 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
8929 ret = false;
8930 } else {
8931 got_handle = true;
8932 *handle = h;
8935 torture_comment(tctx, "Testing samr_Connect2\n");
8937 r2.in.system_name = NULL;
8938 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8939 r2.out.connect_handle = &h;
8941 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
8942 "Connect2 failed");
8943 if (!NT_STATUS_IS_OK(r2.out.result)) {
8944 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
8945 ret = false;
8946 } else {
8947 if (got_handle) {
8948 test_samr_handle_Close(b, tctx, handle);
8950 got_handle = true;
8951 *handle = h;
8954 torture_comment(tctx, "Testing samr_Connect3\n");
8956 r3.in.system_name = NULL;
8957 r3.in.unknown = 0;
8958 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8959 r3.out.connect_handle = &h;
8961 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
8962 "Connect3 failed");
8963 if (!NT_STATUS_IS_OK(r3.out.result)) {
8964 torture_result(tctx, TORTURE_FAIL, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
8965 ret = false;
8966 } else {
8967 if (got_handle) {
8968 test_samr_handle_Close(b, tctx, handle);
8970 got_handle = true;
8971 *handle = h;
8974 torture_comment(tctx, "Testing samr_Connect4\n");
8976 r4.in.system_name = "";
8977 r4.in.client_version = 0;
8978 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
8979 r4.out.connect_handle = &h;
8981 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
8982 "Connect4 failed");
8983 if (!NT_STATUS_IS_OK(r4.out.result)) {
8984 torture_result(tctx, TORTURE_FAIL, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
8985 ret = false;
8986 } else {
8987 if (got_handle) {
8988 test_samr_handle_Close(b, tctx, handle);
8990 got_handle = true;
8991 *handle = h;
8994 torture_comment(tctx, "Testing samr_Connect5\n");
8996 info.info1.client_version = 0;
8997 info.info1.supported_features = 0;
8999 r5.in.system_name = "";
9000 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
9001 r5.in.level_in = 1;
9002 r5.out.level_out = &level_out;
9003 r5.in.info_in = &info;
9004 r5.out.info_out = &info;
9005 r5.out.connect_handle = &h;
9007 torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
9008 "Connect5 failed");
9009 if (!NT_STATUS_IS_OK(r5.out.result)) {
9010 torture_result(tctx, TORTURE_FAIL, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
9011 ret = false;
9012 } else {
9013 if (got_handle) {
9014 test_samr_handle_Close(b, tctx, handle);
9016 got_handle = true;
9017 *handle = h;
9020 return ret;
9024 static bool test_samr_ValidatePassword(struct torture_context *tctx,
9025 struct dcerpc_pipe *p)
9027 struct samr_ValidatePassword r;
9028 union samr_ValidatePasswordReq req;
9029 union samr_ValidatePasswordRep *repp = NULL;
9030 NTSTATUS status;
9031 const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
9032 int i;
9033 struct dcerpc_binding_handle *b = p->binding_handle;
9035 torture_comment(tctx, "Testing samr_ValidatePassword\n");
9037 if (dcerpc_binding_handle_get_transport(b) != NCACN_IP_TCP) {
9038 torture_comment(tctx, "samr_ValidatePassword only should succeed over NCACN_IP_TCP!\n");
9041 ZERO_STRUCT(r);
9042 r.in.level = NetValidatePasswordReset;
9043 r.in.req = &req;
9044 r.out.rep = &repp;
9046 ZERO_STRUCT(req);
9047 req.req3.account.string = "non-existent-account-aklsdji";
9049 for (i=0; passwords[i]; i++) {
9050 req.req3.password.string = passwords[i];
9052 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
9053 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
9054 torture_skip(tctx, "ValidatePassword not supported by server\n");
9056 torture_assert_ntstatus_ok(tctx, status,
9057 "samr_ValidatePassword failed");
9058 torture_assert_ntstatus_ok(tctx, r.out.result,
9059 "samr_ValidatePassword failed");
9060 torture_comment(tctx, "Server %s password '%s' with code %i\n",
9061 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
9062 req.req3.password.string, repp->ctr3.status);
9065 return true;
9068 bool torture_rpc_samr(struct torture_context *torture)
9070 NTSTATUS status;
9071 struct dcerpc_pipe *p;
9072 bool ret = true;
9073 struct torture_samr_context *ctx;
9074 struct dcerpc_binding_handle *b;
9076 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9077 if (!NT_STATUS_IS_OK(status)) {
9078 return false;
9080 b = p->binding_handle;
9082 ctx = talloc_zero(torture, struct torture_samr_context);
9084 ctx->choice = TORTURE_SAMR_OTHER;
9086 ret &= test_Connect(b, torture, &ctx->handle);
9088 if (!torture_setting_bool(torture, "samba3", false)) {
9089 ret &= test_QuerySecurity(b, torture, &ctx->handle);
9092 ret &= test_EnumDomains(p, torture, ctx);
9094 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
9096 ret &= test_Shutdown(b, torture, &ctx->handle);
9098 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9100 return ret;
9104 bool torture_rpc_samr_users(struct torture_context *torture)
9106 NTSTATUS status;
9107 struct dcerpc_pipe *p;
9108 bool ret = true;
9109 struct torture_samr_context *ctx;
9110 struct dcerpc_binding_handle *b;
9112 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9113 if (!NT_STATUS_IS_OK(status)) {
9114 return false;
9116 b = p->binding_handle;
9118 ctx = talloc_zero(torture, struct torture_samr_context);
9120 ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
9122 ret &= test_Connect(b, torture, &ctx->handle);
9124 if (!torture_setting_bool(torture, "samba3", false)) {
9125 ret &= test_QuerySecurity(b, torture, &ctx->handle);
9128 ret &= test_EnumDomains(p, torture, ctx);
9130 ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
9132 ret &= test_Shutdown(b, torture, &ctx->handle);
9134 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9136 return ret;
9140 bool torture_rpc_samr_passwords(struct torture_context *torture)
9142 NTSTATUS status;
9143 struct dcerpc_pipe *p;
9144 bool ret = true;
9145 struct torture_samr_context *ctx;
9146 struct dcerpc_binding_handle *b;
9148 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9149 if (!NT_STATUS_IS_OK(status)) {
9150 return false;
9152 b = p->binding_handle;
9154 ctx = talloc_zero(torture, struct torture_samr_context);
9156 ctx->choice = TORTURE_SAMR_PASSWORDS;
9158 ret &= test_Connect(b, torture, &ctx->handle);
9160 ret &= test_EnumDomains(p, torture, ctx);
9162 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9164 return ret;
9167 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
9168 struct dcerpc_pipe *p2,
9169 struct cli_credentials *machine_credentials)
9171 NTSTATUS status;
9172 struct dcerpc_pipe *p;
9173 bool ret = true;
9174 struct torture_samr_context *ctx;
9175 struct dcerpc_binding_handle *b;
9177 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9178 if (!NT_STATUS_IS_OK(status)) {
9179 return false;
9181 b = p->binding_handle;
9183 ctx = talloc_zero(torture, struct torture_samr_context);
9185 ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
9186 ctx->machine_credentials = machine_credentials;
9188 ret &= test_Connect(b, torture, &ctx->handle);
9190 ret &= test_EnumDomains(p, torture, ctx);
9192 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9194 return ret;
9197 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
9199 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
9200 struct torture_rpc_tcase *tcase;
9202 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
9203 &ndr_table_samr,
9204 TEST_ACCOUNT_NAME_PWD);
9206 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
9207 torture_rpc_samr_pwdlastset);
9209 return suite;
9212 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
9213 struct dcerpc_pipe *p2,
9214 struct cli_credentials *machine_credentials)
9216 NTSTATUS status;
9217 struct dcerpc_pipe *p;
9218 bool ret = true;
9219 struct torture_samr_context *ctx;
9220 struct dcerpc_binding_handle *b;
9222 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9223 if (!NT_STATUS_IS_OK(status)) {
9224 return false;
9226 b = p->binding_handle;
9228 ctx = talloc_zero(torture, struct torture_samr_context);
9230 ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
9231 ctx->machine_credentials = machine_credentials;
9233 ret &= test_Connect(b, torture, &ctx->handle);
9235 ret &= test_EnumDomains(p, torture, ctx);
9237 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9239 return ret;
9242 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
9244 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
9245 struct torture_rpc_tcase *tcase;
9247 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
9248 &ndr_table_samr,
9249 TEST_ACCOUNT_NAME_PWD);
9251 torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
9252 torture_rpc_samr_users_privileges_delete_user);
9254 return suite;
9257 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
9258 struct dcerpc_pipe *p2,
9259 void *data)
9261 NTSTATUS status;
9262 struct dcerpc_pipe *p;
9263 bool ret = true;
9264 struct torture_samr_context *ctx =
9265 talloc_get_type_abort(data, struct torture_samr_context);
9266 struct dcerpc_binding_handle *b;
9268 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9269 if (!NT_STATUS_IS_OK(status)) {
9270 return false;
9272 b = p->binding_handle;
9274 ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
9275 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
9276 ctx->num_objects_large_dc);
9278 ret &= test_Connect(b, torture, &ctx->handle);
9280 ret &= test_EnumDomains(p, torture, ctx);
9282 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9284 return ret;
9287 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
9288 struct dcerpc_pipe *p2,
9289 void *data)
9291 NTSTATUS status;
9292 struct dcerpc_pipe *p;
9293 bool ret = true;
9294 struct torture_samr_context *ctx =
9295 talloc_get_type_abort(data, struct torture_samr_context);
9296 struct dcerpc_binding_handle *b;
9298 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9299 if (!NT_STATUS_IS_OK(status)) {
9300 return false;
9302 b = p->binding_handle;
9304 ctx->choice = TORTURE_SAMR_MANY_GROUPS;
9305 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
9306 ctx->num_objects_large_dc);
9308 ret &= test_Connect(b, torture, &ctx->handle);
9310 ret &= test_EnumDomains(p, torture, ctx);
9312 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9314 return ret;
9317 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
9318 struct dcerpc_pipe *p2,
9319 void *data)
9321 NTSTATUS status;
9322 struct dcerpc_pipe *p;
9323 bool ret = true;
9324 struct torture_samr_context *ctx =
9325 talloc_get_type_abort(data, struct torture_samr_context);
9326 struct dcerpc_binding_handle *b;
9328 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9329 if (!NT_STATUS_IS_OK(status)) {
9330 return false;
9332 b = p->binding_handle;
9334 ctx->choice = TORTURE_SAMR_MANY_ALIASES;
9335 ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
9336 ctx->num_objects_large_dc);
9338 ret &= test_Connect(b, torture, &ctx->handle);
9340 ret &= test_EnumDomains(p, torture, ctx);
9342 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9344 return ret;
9347 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
9349 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
9350 struct torture_rpc_tcase *tcase;
9351 struct torture_samr_context *ctx;
9353 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
9355 ctx = talloc_zero(suite, struct torture_samr_context);
9356 ctx->num_objects_large_dc = 150;
9358 torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
9359 torture_rpc_samr_many_aliases, ctx);
9360 torture_rpc_tcase_add_test_ex(tcase, "many_groups",
9361 torture_rpc_samr_many_groups, ctx);
9362 torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
9363 torture_rpc_samr_many_accounts, ctx);
9365 return suite;
9368 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
9369 struct dcerpc_pipe *p2,
9370 struct cli_credentials *machine_credentials)
9372 NTSTATUS status;
9373 struct dcerpc_pipe *p;
9374 bool ret = true;
9375 struct torture_samr_context *ctx;
9376 struct dcerpc_binding_handle *b;
9378 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9379 if (!NT_STATUS_IS_OK(status)) {
9380 return false;
9382 b = p->binding_handle;
9384 ctx = talloc_zero(torture, struct torture_samr_context);
9386 ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
9387 ctx->machine_credentials = machine_credentials;
9389 ret &= test_Connect(b, torture, &ctx->handle);
9391 ret &= test_EnumDomains(p, torture, ctx);
9393 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9395 return ret;
9398 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
9400 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
9401 struct torture_rpc_tcase *tcase;
9403 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
9404 &ndr_table_samr,
9405 TEST_ACCOUNT_NAME_PWD);
9407 torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
9408 torture_rpc_samr_badpwdcount);
9410 return suite;
9413 static bool torture_rpc_samr_lockout(struct torture_context *torture,
9414 struct dcerpc_pipe *p2,
9415 struct cli_credentials *machine_credentials)
9417 NTSTATUS status;
9418 struct dcerpc_pipe *p;
9419 bool ret = true;
9420 struct torture_samr_context *ctx;
9421 struct dcerpc_binding_handle *b;
9423 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
9424 if (!NT_STATUS_IS_OK(status)) {
9425 return false;
9427 b = p->binding_handle;
9429 ctx = talloc_zero(torture, struct torture_samr_context);
9431 ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
9432 ctx->machine_credentials = machine_credentials;
9434 ret &= test_Connect(b, torture, &ctx->handle);
9436 ret &= test_EnumDomains(p, torture, ctx);
9438 ret &= test_samr_handle_Close(b, torture, &ctx->handle);
9440 return ret;
9443 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
9445 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
9446 struct torture_rpc_tcase *tcase;
9448 tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
9449 &ndr_table_samr,
9450 TEST_ACCOUNT_NAME_PWD);
9452 torture_rpc_tcase_add_test_creds(tcase, "lockout",
9453 torture_rpc_samr_lockout);
9455 return suite;
9458 struct torture_suite *torture_rpc_samr_passwords_validate(TALLOC_CTX *mem_ctx)
9460 struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.validate");
9461 struct torture_rpc_tcase *tcase;
9463 tcase = torture_suite_add_rpc_iface_tcase(suite, "samr",
9464 &ndr_table_samr);
9465 torture_rpc_tcase_add_test(tcase, "validate",
9466 test_samr_ValidatePassword);
9468 return suite;