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