s4-samr: merge samr_QueryDisplayInfo from s3 idl. (fixme: python)
[Samba/gbeck.git] / source4 / torture / rpc / samr.c
blob17e81a93e014636e553b8e5dde11417cc3f81cf3
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_samr_c.h"
27 #include "../lib/crypto/crypto.h"
28 #include "libcli/auth/libcli_auth.h"
29 #include "libcli/security/security.h"
30 #include "torture/rpc/rpc.h"
32 #define TEST_ACCOUNT_NAME "samrtorturetest"
33 #define TEST_ALIASNAME "samrtorturetestalias"
34 #define TEST_GROUPNAME "samrtorturetestgroup"
35 #define TEST_MACHINENAME "samrtestmach$"
36 #define TEST_DOMAINNAME "samrtestdom$"
38 enum torture_samr_choice {
39 TORTURE_SAMR_PASSWORDS,
40 TORTURE_SAMR_USER_ATTRIBUTES,
41 TORTURE_SAMR_OTHER
44 static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
45 struct policy_handle *handle);
47 static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
48 struct policy_handle *handle);
50 static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
51 struct policy_handle *handle);
53 static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
54 const char *acct_name,
55 struct policy_handle *domain_handle, char **password);
57 static void init_lsa_String(struct lsa_String *string, const char *s)
59 string->string = s;
62 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
64 string->length = length;
65 string->size = length;
66 string->array = (uint16_t *)discard_const(s);
69 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
70 struct policy_handle *handle)
72 NTSTATUS status;
73 struct samr_Close r;
75 r.in.handle = handle;
76 r.out.handle = handle;
78 status = dcerpc_samr_Close(p, tctx, &r);
79 torture_assert_ntstatus_ok(tctx, status, "Close");
81 return true;
84 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
85 struct policy_handle *handle)
87 NTSTATUS status;
88 struct samr_Shutdown r;
90 if (!torture_setting_bool(tctx, "dangerous", false)) {
91 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
92 return true;
95 r.in.connect_handle = handle;
97 torture_comment(tctx, "testing samr_Shutdown\n");
99 status = dcerpc_samr_Shutdown(p, tctx, &r);
100 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
102 return true;
105 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
106 struct policy_handle *handle)
108 NTSTATUS status;
109 struct samr_SetDsrmPassword r;
110 struct lsa_String string;
111 struct samr_Password hash;
113 if (!torture_setting_bool(tctx, "dangerous", false)) {
114 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
117 E_md4hash("TeSTDSRM123", hash.hash);
119 init_lsa_String(&string, "Administrator");
121 r.in.name = &string;
122 r.in.unknown = 0;
123 r.in.hash = &hash;
125 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
127 status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
128 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
130 return true;
134 static bool test_QuerySecurity(struct dcerpc_pipe *p,
135 struct torture_context *tctx,
136 struct policy_handle *handle)
138 NTSTATUS status;
139 struct samr_QuerySecurity r;
140 struct samr_SetSecurity s;
141 struct sec_desc_buf *sdbuf = NULL;
143 r.in.handle = handle;
144 r.in.sec_info = 7;
145 r.out.sdbuf = &sdbuf;
147 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
148 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
150 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
152 s.in.handle = handle;
153 s.in.sec_info = 7;
154 s.in.sdbuf = sdbuf;
156 if (torture_setting_bool(tctx, "samba4", false)) {
157 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
160 status = dcerpc_samr_SetSecurity(p, tctx, &s);
161 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
163 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
164 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
166 return true;
170 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
171 struct policy_handle *handle, uint32_t base_acct_flags,
172 const char *base_account_name)
174 NTSTATUS status;
175 struct samr_SetUserInfo s;
176 struct samr_SetUserInfo2 s2;
177 struct samr_QueryUserInfo q;
178 struct samr_QueryUserInfo q0;
179 union samr_UserInfo u;
180 bool ret = true;
181 const char *test_account_name;
183 uint32_t user_extra_flags = 0;
184 if (base_acct_flags == ACB_NORMAL) {
185 /* When created, accounts are expired by default */
186 user_extra_flags = ACB_PW_EXPIRED;
189 s.in.user_handle = handle;
190 s.in.info = &u;
192 s2.in.user_handle = handle;
193 s2.in.info = &u;
195 q.in.user_handle = handle;
196 q.out.info = &u;
197 q0 = q;
199 #define TESTCALL(call, r) \
200 status = dcerpc_samr_ ##call(p, tctx, &r); \
201 if (!NT_STATUS_IS_OK(status)) { \
202 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
203 r.in.level, nt_errstr(status), __location__); \
204 ret = false; \
205 break; \
208 #define STRING_EQUAL(s1, s2, field) \
209 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
210 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
211 #field, s2, __location__); \
212 ret = false; \
213 break; \
216 #define MEM_EQUAL(s1, s2, length, field) \
217 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
218 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
219 #field, (const char *)s2, __location__); \
220 ret = false; \
221 break; \
224 #define INT_EQUAL(i1, i2, field) \
225 if (i1 != i2) { \
226 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
227 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
228 ret = false; \
229 break; \
232 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
233 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
234 q.in.level = lvl1; \
235 TESTCALL(QueryUserInfo, q) \
236 s.in.level = lvl1; \
237 s2.in.level = lvl1; \
238 u = *q.out.info; \
239 if (lvl1 == 21) { \
240 ZERO_STRUCT(u.info21); \
241 u.info21.fields_present = fpval; \
243 init_lsa_String(&u.info ## lvl1.field1, value); \
244 TESTCALL(SetUserInfo, s) \
245 TESTCALL(SetUserInfo2, s2) \
246 init_lsa_String(&u.info ## lvl1.field1, ""); \
247 TESTCALL(QueryUserInfo, q); \
248 u = *q.out.info; \
249 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
250 q.in.level = lvl2; \
251 TESTCALL(QueryUserInfo, q) \
252 u = *q.out.info; \
253 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
254 } while (0)
256 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
257 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
258 q.in.level = lvl1; \
259 TESTCALL(QueryUserInfo, q) \
260 s.in.level = lvl1; \
261 s2.in.level = lvl1; \
262 u = *q.out.info; \
263 if (lvl1 == 21) { \
264 ZERO_STRUCT(u.info21); \
265 u.info21.fields_present = fpval; \
267 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
268 TESTCALL(SetUserInfo, s) \
269 TESTCALL(SetUserInfo2, s2) \
270 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
271 TESTCALL(QueryUserInfo, q); \
272 u = *q.out.info; \
273 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
274 q.in.level = lvl2; \
275 TESTCALL(QueryUserInfo, q) \
276 u = *q.out.info; \
277 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
278 } while (0)
280 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
281 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
282 q.in.level = lvl1; \
283 TESTCALL(QueryUserInfo, q) \
284 s.in.level = lvl1; \
285 s2.in.level = lvl1; \
286 u = *q.out.info; \
287 if (lvl1 == 21) { \
288 uint8_t *bits = u.info21.logon_hours.bits; \
289 ZERO_STRUCT(u.info21); \
290 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
291 u.info21.logon_hours.units_per_week = 168; \
292 u.info21.logon_hours.bits = bits; \
294 u.info21.fields_present = fpval; \
296 u.info ## lvl1.field1 = value; \
297 TESTCALL(SetUserInfo, s) \
298 TESTCALL(SetUserInfo2, s2) \
299 u.info ## lvl1.field1 = 0; \
300 TESTCALL(QueryUserInfo, q); \
301 u = *q.out.info; \
302 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
303 q.in.level = lvl2; \
304 TESTCALL(QueryUserInfo, q) \
305 u = *q.out.info; \
306 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
307 } while (0)
309 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
310 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
311 } while (0)
313 q0.in.level = 12;
314 do { TESTCALL(QueryUserInfo, q0) } while (0);
316 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
317 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
318 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
319 SAMR_FIELD_COMMENT);
321 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
322 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
323 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
324 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
325 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
326 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
327 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
328 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
329 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
330 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
331 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
332 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
333 test_account_name = base_account_name;
334 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
335 SAMR_FIELD_ACCOUNT_NAME);
337 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
338 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
339 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
340 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
341 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
342 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
343 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
344 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
345 SAMR_FIELD_FULL_NAME);
347 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
348 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
349 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
350 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
351 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
352 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
353 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
354 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
355 SAMR_FIELD_FULL_NAME);
357 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
358 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
359 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
360 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
361 SAMR_FIELD_LOGON_SCRIPT);
363 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
364 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
365 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
366 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
367 SAMR_FIELD_PROFILE_PATH);
369 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
370 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
371 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
372 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
373 SAMR_FIELD_HOME_DIRECTORY);
374 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
375 SAMR_FIELD_HOME_DIRECTORY);
377 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
378 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
379 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
380 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
381 SAMR_FIELD_HOME_DRIVE);
382 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
383 SAMR_FIELD_HOME_DRIVE);
385 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
386 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
387 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
388 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
389 SAMR_FIELD_DESCRIPTION);
391 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
392 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
393 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
394 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
395 SAMR_FIELD_WORKSTATIONS);
396 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
397 SAMR_FIELD_WORKSTATIONS);
398 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
399 SAMR_FIELD_WORKSTATIONS);
400 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
401 SAMR_FIELD_WORKSTATIONS);
403 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
404 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
405 SAMR_FIELD_PARAMETERS);
406 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
407 SAMR_FIELD_PARAMETERS);
409 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
410 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
411 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
412 SAMR_FIELD_COUNTRY_CODE);
413 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
414 SAMR_FIELD_COUNTRY_CODE);
416 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
417 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
418 SAMR_FIELD_CODE_PAGE);
419 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
420 SAMR_FIELD_CODE_PAGE);
422 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
423 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
424 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
425 SAMR_FIELD_ACCT_EXPIRY);
426 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
427 SAMR_FIELD_ACCT_EXPIRY);
428 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
429 SAMR_FIELD_ACCT_EXPIRY);
431 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
432 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
433 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
434 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
435 SAMR_FIELD_LOGON_HOURS);
437 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
438 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
439 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
441 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
442 (base_acct_flags | ACB_DISABLED),
443 (base_acct_flags | ACB_DISABLED | user_extra_flags),
446 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
447 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
448 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
449 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
451 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
452 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
453 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
457 /* The 'autolock' flag doesn't stick - check this */
458 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
459 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
460 (base_acct_flags | ACB_DISABLED | user_extra_flags),
462 #if 0
463 /* Removing the 'disabled' flag doesn't stick - check this */
464 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
465 (base_acct_flags),
466 (base_acct_flags | ACB_DISABLED | user_extra_flags),
468 #endif
469 /* The 'store plaintext' flag does stick */
470 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
471 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
472 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
474 /* The 'use DES' flag does stick */
475 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
476 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
477 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
479 /* The 'don't require kerberos pre-authentication flag does stick */
480 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
481 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
482 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
484 /* The 'no kerberos PAC required' flag sticks */
485 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
486 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
487 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
490 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
491 (base_acct_flags | ACB_DISABLED),
492 (base_acct_flags | ACB_DISABLED | user_extra_flags),
493 SAMR_FIELD_ACCT_FLAGS);
495 #if 0
496 /* these fail with win2003 - it appears you can't set the primary gid?
497 the set succeeds, but the gid isn't changed. Very weird! */
498 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
499 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
500 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
501 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
502 #endif
504 return ret;
508 generate a random password for password change tests
510 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
512 size_t len = MAX(8, min_len) + (random() % 6);
513 char *s = generate_random_str(mem_ctx, len);
514 printf("Generated password '%s'\n", s);
515 return s;
519 generate a random password for password change tests
521 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
523 int i;
524 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
525 generate_random_buffer(password.data, password.length);
527 for (i=0; i < len; i++) {
528 if (((uint16_t *)password.data)[i] == 0) {
529 ((uint16_t *)password.data)[i] = 1;
533 return password;
537 generate a random password for password change tests (fixed length)
539 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
541 char *s = generate_random_str(mem_ctx, len);
542 printf("Generated password '%s'\n", s);
543 return s;
546 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
547 struct policy_handle *handle, char **password)
549 NTSTATUS status;
550 struct samr_SetUserInfo s;
551 union samr_UserInfo u;
552 bool ret = true;
553 DATA_BLOB session_key;
554 char *newpass;
555 struct samr_GetUserPwInfo pwp;
556 struct samr_PwInfo info;
557 int policy_min_pw_len = 0;
558 pwp.in.user_handle = handle;
559 pwp.out.info = &info;
561 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
562 if (NT_STATUS_IS_OK(status)) {
563 policy_min_pw_len = pwp.out.info->min_password_length;
565 newpass = samr_rand_pass(tctx, policy_min_pw_len);
567 s.in.user_handle = handle;
568 s.in.info = &u;
569 s.in.level = 24;
571 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
572 /* w2k3 ignores this length */
573 u.info24.pw_len = strlen_m(newpass) * 2;
575 status = dcerpc_fetch_session_key(p, &session_key);
576 if (!NT_STATUS_IS_OK(status)) {
577 printf("SetUserInfo level %u - no session key - %s\n",
578 s.in.level, nt_errstr(status));
579 return false;
582 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
584 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
586 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
587 if (!NT_STATUS_IS_OK(status)) {
588 printf("SetUserInfo level %u failed - %s\n",
589 s.in.level, nt_errstr(status));
590 ret = false;
591 } else {
592 *password = newpass;
595 return ret;
599 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
600 struct policy_handle *handle, uint32_t fields_present,
601 char **password)
603 NTSTATUS status;
604 struct samr_SetUserInfo s;
605 union samr_UserInfo u;
606 bool ret = true;
607 DATA_BLOB session_key;
608 char *newpass;
609 struct samr_GetUserPwInfo pwp;
610 struct samr_PwInfo info;
611 int policy_min_pw_len = 0;
612 pwp.in.user_handle = handle;
613 pwp.out.info = &info;
615 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
616 if (NT_STATUS_IS_OK(status)) {
617 policy_min_pw_len = pwp.out.info->min_password_length;
619 newpass = samr_rand_pass(tctx, policy_min_pw_len);
621 s.in.user_handle = handle;
622 s.in.info = &u;
623 s.in.level = 23;
625 ZERO_STRUCT(u);
627 u.info23.info.fields_present = fields_present;
629 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
631 status = dcerpc_fetch_session_key(p, &session_key);
632 if (!NT_STATUS_IS_OK(status)) {
633 printf("SetUserInfo level %u - no session key - %s\n",
634 s.in.level, nt_errstr(status));
635 return false;
638 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
640 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
642 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
643 if (!NT_STATUS_IS_OK(status)) {
644 printf("SetUserInfo level %u failed - %s\n",
645 s.in.level, nt_errstr(status));
646 ret = false;
647 } else {
648 *password = newpass;
651 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
653 status = dcerpc_fetch_session_key(p, &session_key);
654 if (!NT_STATUS_IS_OK(status)) {
655 printf("SetUserInfo level %u - no session key - %s\n",
656 s.in.level, nt_errstr(status));
657 return false;
660 /* This should break the key nicely */
661 session_key.length--;
662 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
664 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
666 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
667 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
668 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
669 s.in.level, nt_errstr(status));
670 ret = false;
673 return ret;
677 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
678 struct policy_handle *handle, bool makeshort,
679 char **password)
681 NTSTATUS status;
682 struct samr_SetUserInfo s;
683 union samr_UserInfo u;
684 bool ret = true;
685 DATA_BLOB session_key;
686 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
687 uint8_t confounder[16];
688 char *newpass;
689 struct MD5Context ctx;
690 struct samr_GetUserPwInfo pwp;
691 struct samr_PwInfo info;
692 int policy_min_pw_len = 0;
693 pwp.in.user_handle = handle;
694 pwp.out.info = &info;
696 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
697 if (NT_STATUS_IS_OK(status)) {
698 policy_min_pw_len = pwp.out.info->min_password_length;
700 if (makeshort && policy_min_pw_len) {
701 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
702 } else {
703 newpass = samr_rand_pass(tctx, policy_min_pw_len);
706 s.in.user_handle = handle;
707 s.in.info = &u;
708 s.in.level = 26;
710 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
711 u.info26.pw_len = strlen(newpass);
713 status = dcerpc_fetch_session_key(p, &session_key);
714 if (!NT_STATUS_IS_OK(status)) {
715 printf("SetUserInfo level %u - no session key - %s\n",
716 s.in.level, nt_errstr(status));
717 return false;
720 generate_random_buffer((uint8_t *)confounder, 16);
722 MD5Init(&ctx);
723 MD5Update(&ctx, confounder, 16);
724 MD5Update(&ctx, session_key.data, session_key.length);
725 MD5Final(confounded_session_key.data, &ctx);
727 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
728 memcpy(&u.info26.password.data[516], confounder, 16);
730 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
732 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
733 if (!NT_STATUS_IS_OK(status)) {
734 printf("SetUserInfo level %u failed - %s\n",
735 s.in.level, nt_errstr(status));
736 ret = false;
737 } else {
738 *password = newpass;
741 /* This should break the key nicely */
742 confounded_session_key.data[0]++;
744 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
745 memcpy(&u.info26.password.data[516], confounder, 16);
747 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
749 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
750 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
751 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
752 s.in.level, nt_errstr(status));
753 ret = false;
754 } else {
755 *password = newpass;
758 return ret;
761 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
762 struct policy_handle *handle, uint32_t fields_present,
763 char **password)
765 NTSTATUS status;
766 struct samr_SetUserInfo s;
767 union samr_UserInfo u;
768 bool ret = true;
769 DATA_BLOB session_key;
770 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
771 struct MD5Context ctx;
772 uint8_t confounder[16];
773 char *newpass;
774 struct samr_GetUserPwInfo pwp;
775 struct samr_PwInfo info;
776 int policy_min_pw_len = 0;
777 pwp.in.user_handle = handle;
778 pwp.out.info = &info;
780 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
781 if (NT_STATUS_IS_OK(status)) {
782 policy_min_pw_len = pwp.out.info->min_password_length;
784 newpass = samr_rand_pass(tctx, policy_min_pw_len);
786 s.in.user_handle = handle;
787 s.in.info = &u;
788 s.in.level = 25;
790 ZERO_STRUCT(u);
792 u.info25.info.fields_present = fields_present;
794 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
796 status = dcerpc_fetch_session_key(p, &session_key);
797 if (!NT_STATUS_IS_OK(status)) {
798 printf("SetUserInfo level %u - no session key - %s\n",
799 s.in.level, nt_errstr(status));
800 return false;
803 generate_random_buffer((uint8_t *)confounder, 16);
805 MD5Init(&ctx);
806 MD5Update(&ctx, confounder, 16);
807 MD5Update(&ctx, session_key.data, session_key.length);
808 MD5Final(confounded_session_key.data, &ctx);
810 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
811 memcpy(&u.info25.password.data[516], confounder, 16);
813 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
815 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
816 if (!NT_STATUS_IS_OK(status)) {
817 printf("SetUserInfo level %u failed - %s\n",
818 s.in.level, nt_errstr(status));
819 ret = false;
820 } else {
821 *password = newpass;
824 /* This should break the key nicely */
825 confounded_session_key.data[0]++;
827 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
828 memcpy(&u.info25.password.data[516], confounder, 16);
830 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
832 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
833 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
834 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
835 s.in.level, nt_errstr(status));
836 ret = false;
839 return ret;
842 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
843 struct policy_handle *handle)
845 NTSTATUS status;
846 struct samr_SetAliasInfo r;
847 struct samr_QueryAliasInfo q;
848 uint16_t levels[] = {2, 3};
849 int i;
850 bool ret = true;
852 /* Ignoring switch level 1, as that includes the number of members for the alias
853 * and setting this to a wrong value might have negative consequences
856 for (i=0;i<ARRAY_SIZE(levels);i++) {
857 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
859 r.in.alias_handle = handle;
860 r.in.level = levels[i];
861 r.in.info = talloc(tctx, union samr_AliasInfo);
862 switch (r.in.level) {
863 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
864 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
865 "Test Description, should test I18N as well"); break;
866 case ALIASINFOALL: printf("ALIASINFOALL ignored\n"); break;
869 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
870 if (!NT_STATUS_IS_OK(status)) {
871 printf("SetAliasInfo level %u failed - %s\n",
872 levels[i], nt_errstr(status));
873 ret = false;
876 q.in.alias_handle = handle;
877 q.in.level = levels[i];
879 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
880 if (!NT_STATUS_IS_OK(status)) {
881 printf("QueryAliasInfo level %u failed - %s\n",
882 levels[i], nt_errstr(status));
883 ret = false;
887 return ret;
890 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
891 struct policy_handle *user_handle)
893 struct samr_GetGroupsForUser r;
894 struct samr_RidWithAttributeArray *rids = NULL;
895 NTSTATUS status;
897 torture_comment(tctx, "testing GetGroupsForUser\n");
899 r.in.user_handle = user_handle;
900 r.out.rids = &rids;
902 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
903 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
905 return true;
909 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
910 struct lsa_String *domain_name)
912 NTSTATUS status;
913 struct samr_GetDomPwInfo r;
914 struct samr_PwInfo info;
916 r.in.domain_name = domain_name;
917 r.out.info = &info;
919 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
921 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
922 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
924 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
925 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
927 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
928 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
930 r.in.domain_name->string = "\\\\__NONAME__";
931 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
933 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
934 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
936 r.in.domain_name->string = "\\\\Builtin";
937 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
939 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
940 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
942 return true;
945 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
946 struct policy_handle *handle)
948 NTSTATUS status;
949 struct samr_GetUserPwInfo r;
950 struct samr_PwInfo info;
952 torture_comment(tctx, "Testing GetUserPwInfo\n");
954 r.in.user_handle = handle;
955 r.out.info = &info;
957 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
958 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
960 return true;
963 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
964 struct policy_handle *domain_handle, const char *name,
965 uint32_t *rid)
967 NTSTATUS status;
968 struct samr_LookupNames n;
969 struct lsa_String sname[2];
971 init_lsa_String(&sname[0], name);
973 n.in.domain_handle = domain_handle;
974 n.in.num_names = 1;
975 n.in.names = sname;
976 status = dcerpc_samr_LookupNames(p, tctx, &n);
977 if (NT_STATUS_IS_OK(status)) {
978 *rid = n.out.rids.ids[0];
979 } else {
980 return status;
983 init_lsa_String(&sname[1], "xxNONAMExx");
984 n.in.num_names = 2;
985 status = dcerpc_samr_LookupNames(p, tctx, &n);
986 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
987 printf("LookupNames[2] failed - %s\n", nt_errstr(status));
988 if (NT_STATUS_IS_OK(status)) {
989 return NT_STATUS_UNSUCCESSFUL;
991 return status;
994 n.in.num_names = 0;
995 status = dcerpc_samr_LookupNames(p, tctx, &n);
996 if (!NT_STATUS_IS_OK(status)) {
997 printf("LookupNames[0] failed - %s\n", nt_errstr(status));
998 return status;
1001 init_lsa_String(&sname[0], "xxNONAMExx");
1002 n.in.num_names = 1;
1003 status = dcerpc_samr_LookupNames(p, tctx, &n);
1004 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1005 printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1006 if (NT_STATUS_IS_OK(status)) {
1007 return NT_STATUS_UNSUCCESSFUL;
1009 return status;
1012 init_lsa_String(&sname[0], "xxNONAMExx");
1013 init_lsa_String(&sname[1], "xxNONAME2xx");
1014 n.in.num_names = 2;
1015 status = dcerpc_samr_LookupNames(p, tctx, &n);
1016 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1017 printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1018 if (NT_STATUS_IS_OK(status)) {
1019 return NT_STATUS_UNSUCCESSFUL;
1021 return status;
1024 return NT_STATUS_OK;
1027 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1028 struct policy_handle *domain_handle,
1029 const char *name, struct policy_handle *user_handle)
1031 NTSTATUS status;
1032 struct samr_OpenUser r;
1033 uint32_t rid;
1035 status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
1036 if (!NT_STATUS_IS_OK(status)) {
1037 return status;
1040 r.in.domain_handle = domain_handle;
1041 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1042 r.in.rid = rid;
1043 r.out.user_handle = user_handle;
1044 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
1045 if (!NT_STATUS_IS_OK(status)) {
1046 printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1049 return status;
1052 #if 0
1053 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1054 struct policy_handle *handle)
1056 NTSTATUS status;
1057 struct samr_ChangePasswordUser r;
1058 bool ret = true;
1059 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1060 struct policy_handle user_handle;
1061 char *oldpass = "test";
1062 char *newpass = "test2";
1063 uint8_t old_nt_hash[16], new_nt_hash[16];
1064 uint8_t old_lm_hash[16], new_lm_hash[16];
1066 status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
1067 if (!NT_STATUS_IS_OK(status)) {
1068 return false;
1071 printf("Testing ChangePasswordUser for user 'testuser'\n");
1073 printf("old password: %s\n", oldpass);
1074 printf("new password: %s\n", newpass);
1076 E_md4hash(oldpass, old_nt_hash);
1077 E_md4hash(newpass, new_nt_hash);
1078 E_deshash(oldpass, old_lm_hash);
1079 E_deshash(newpass, new_lm_hash);
1081 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1082 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1083 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1084 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1085 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1086 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1088 r.in.handle = &user_handle;
1089 r.in.lm_present = 1;
1090 r.in.old_lm_crypted = &hash1;
1091 r.in.new_lm_crypted = &hash2;
1092 r.in.nt_present = 1;
1093 r.in.old_nt_crypted = &hash3;
1094 r.in.new_nt_crypted = &hash4;
1095 r.in.cross1_present = 1;
1096 r.in.nt_cross = &hash5;
1097 r.in.cross2_present = 1;
1098 r.in.lm_cross = &hash6;
1100 status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1101 if (!NT_STATUS_IS_OK(status)) {
1102 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1103 ret = false;
1106 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
1107 ret = false;
1110 return ret;
1112 #endif
1114 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1115 const char *acct_name,
1116 struct policy_handle *handle, char **password)
1118 NTSTATUS status;
1119 struct samr_ChangePasswordUser r;
1120 bool ret = true;
1121 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1122 struct policy_handle user_handle;
1123 char *oldpass;
1124 uint8_t old_nt_hash[16], new_nt_hash[16];
1125 uint8_t old_lm_hash[16], new_lm_hash[16];
1126 bool changed = true;
1128 char *newpass;
1129 struct samr_GetUserPwInfo pwp;
1130 struct samr_PwInfo info;
1131 int policy_min_pw_len = 0;
1133 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1134 if (!NT_STATUS_IS_OK(status)) {
1135 return false;
1137 pwp.in.user_handle = &user_handle;
1138 pwp.out.info = &info;
1140 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1141 if (NT_STATUS_IS_OK(status)) {
1142 policy_min_pw_len = pwp.out.info->min_password_length;
1144 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1146 torture_comment(tctx, "Testing ChangePasswordUser\n");
1148 torture_assert(tctx, *password != NULL,
1149 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1151 oldpass = *password;
1153 E_md4hash(oldpass, old_nt_hash);
1154 E_md4hash(newpass, new_nt_hash);
1155 E_deshash(oldpass, old_lm_hash);
1156 E_deshash(newpass, new_lm_hash);
1158 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1159 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1160 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1161 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1162 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1163 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1165 r.in.user_handle = &user_handle;
1166 r.in.lm_present = 1;
1167 /* Break the LM hash */
1168 hash1.hash[0]++;
1169 r.in.old_lm_crypted = &hash1;
1170 r.in.new_lm_crypted = &hash2;
1171 r.in.nt_present = 1;
1172 r.in.old_nt_crypted = &hash3;
1173 r.in.new_nt_crypted = &hash4;
1174 r.in.cross1_present = 1;
1175 r.in.nt_cross = &hash5;
1176 r.in.cross2_present = 1;
1177 r.in.lm_cross = &hash6;
1179 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1180 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1181 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1183 /* Unbreak the LM hash */
1184 hash1.hash[0]--;
1186 r.in.user_handle = &user_handle;
1187 r.in.lm_present = 1;
1188 r.in.old_lm_crypted = &hash1;
1189 r.in.new_lm_crypted = &hash2;
1190 /* Break the NT hash */
1191 hash3.hash[0]--;
1192 r.in.nt_present = 1;
1193 r.in.old_nt_crypted = &hash3;
1194 r.in.new_nt_crypted = &hash4;
1195 r.in.cross1_present = 1;
1196 r.in.nt_cross = &hash5;
1197 r.in.cross2_present = 1;
1198 r.in.lm_cross = &hash6;
1200 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1201 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1202 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1204 /* Unbreak the NT hash */
1205 hash3.hash[0]--;
1207 r.in.user_handle = &user_handle;
1208 r.in.lm_present = 1;
1209 r.in.old_lm_crypted = &hash1;
1210 r.in.new_lm_crypted = &hash2;
1211 r.in.nt_present = 1;
1212 r.in.old_nt_crypted = &hash3;
1213 r.in.new_nt_crypted = &hash4;
1214 r.in.cross1_present = 1;
1215 r.in.nt_cross = &hash5;
1216 r.in.cross2_present = 1;
1217 /* Break the LM cross */
1218 hash6.hash[0]++;
1219 r.in.lm_cross = &hash6;
1221 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1222 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1223 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1224 ret = false;
1227 /* Unbreak the LM cross */
1228 hash6.hash[0]--;
1230 r.in.user_handle = &user_handle;
1231 r.in.lm_present = 1;
1232 r.in.old_lm_crypted = &hash1;
1233 r.in.new_lm_crypted = &hash2;
1234 r.in.nt_present = 1;
1235 r.in.old_nt_crypted = &hash3;
1236 r.in.new_nt_crypted = &hash4;
1237 r.in.cross1_present = 1;
1238 /* Break the NT cross */
1239 hash5.hash[0]++;
1240 r.in.nt_cross = &hash5;
1241 r.in.cross2_present = 1;
1242 r.in.lm_cross = &hash6;
1244 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1245 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1246 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1247 ret = false;
1250 /* Unbreak the NT cross */
1251 hash5.hash[0]--;
1254 /* Reset the hashes to not broken values */
1255 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1256 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1257 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1258 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1259 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1260 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1262 r.in.user_handle = &user_handle;
1263 r.in.lm_present = 1;
1264 r.in.old_lm_crypted = &hash1;
1265 r.in.new_lm_crypted = &hash2;
1266 r.in.nt_present = 1;
1267 r.in.old_nt_crypted = &hash3;
1268 r.in.new_nt_crypted = &hash4;
1269 r.in.cross1_present = 1;
1270 r.in.nt_cross = &hash5;
1271 r.in.cross2_present = 0;
1272 r.in.lm_cross = NULL;
1274 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1275 if (NT_STATUS_IS_OK(status)) {
1276 changed = true;
1277 *password = newpass;
1278 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1279 printf("ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1280 ret = false;
1283 oldpass = newpass;
1284 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1286 E_md4hash(oldpass, old_nt_hash);
1287 E_md4hash(newpass, new_nt_hash);
1288 E_deshash(oldpass, old_lm_hash);
1289 E_deshash(newpass, new_lm_hash);
1292 /* Reset the hashes to not broken values */
1293 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1294 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1295 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1296 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1297 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1298 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1300 r.in.user_handle = &user_handle;
1301 r.in.lm_present = 1;
1302 r.in.old_lm_crypted = &hash1;
1303 r.in.new_lm_crypted = &hash2;
1304 r.in.nt_present = 1;
1305 r.in.old_nt_crypted = &hash3;
1306 r.in.new_nt_crypted = &hash4;
1307 r.in.cross1_present = 0;
1308 r.in.nt_cross = NULL;
1309 r.in.cross2_present = 1;
1310 r.in.lm_cross = &hash6;
1312 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1313 if (NT_STATUS_IS_OK(status)) {
1314 changed = true;
1315 *password = newpass;
1316 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1317 printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1318 ret = false;
1321 oldpass = newpass;
1322 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1324 E_md4hash(oldpass, old_nt_hash);
1325 E_md4hash(newpass, new_nt_hash);
1326 E_deshash(oldpass, old_lm_hash);
1327 E_deshash(newpass, new_lm_hash);
1330 /* Reset the hashes to not broken values */
1331 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1332 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1333 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1334 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1335 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1336 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1338 r.in.user_handle = &user_handle;
1339 r.in.lm_present = 1;
1340 r.in.old_lm_crypted = &hash1;
1341 r.in.new_lm_crypted = &hash2;
1342 r.in.nt_present = 1;
1343 r.in.old_nt_crypted = &hash3;
1344 r.in.new_nt_crypted = &hash4;
1345 r.in.cross1_present = 1;
1346 r.in.nt_cross = &hash5;
1347 r.in.cross2_present = 1;
1348 r.in.lm_cross = &hash6;
1350 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1351 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1352 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1353 } else if (!NT_STATUS_IS_OK(status)) {
1354 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1355 ret = false;
1356 } else {
1357 changed = true;
1358 *password = newpass;
1361 r.in.user_handle = &user_handle;
1362 r.in.lm_present = 1;
1363 r.in.old_lm_crypted = &hash1;
1364 r.in.new_lm_crypted = &hash2;
1365 r.in.nt_present = 1;
1366 r.in.old_nt_crypted = &hash3;
1367 r.in.new_nt_crypted = &hash4;
1368 r.in.cross1_present = 1;
1369 r.in.nt_cross = &hash5;
1370 r.in.cross2_present = 1;
1371 r.in.lm_cross = &hash6;
1373 if (changed) {
1374 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1375 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1376 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1377 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1378 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1379 ret = false;
1384 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1385 ret = false;
1388 return ret;
1392 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1393 const char *acct_name,
1394 struct policy_handle *handle, char **password)
1396 NTSTATUS status;
1397 struct samr_OemChangePasswordUser2 r;
1398 bool ret = true;
1399 struct samr_Password lm_verifier;
1400 struct samr_CryptPassword lm_pass;
1401 struct lsa_AsciiString server, account, account_bad;
1402 char *oldpass;
1403 char *newpass;
1404 uint8_t old_lm_hash[16], new_lm_hash[16];
1406 struct samr_GetDomPwInfo dom_pw_info;
1407 struct samr_PwInfo info;
1408 int policy_min_pw_len = 0;
1410 struct lsa_String domain_name;
1412 domain_name.string = "";
1413 dom_pw_info.in.domain_name = &domain_name;
1414 dom_pw_info.out.info = &info;
1416 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1418 torture_assert(tctx, *password != NULL,
1419 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1421 oldpass = *password;
1423 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1424 if (NT_STATUS_IS_OK(status)) {
1425 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1428 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1430 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1431 account.string = acct_name;
1433 E_deshash(oldpass, old_lm_hash);
1434 E_deshash(newpass, new_lm_hash);
1436 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1437 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1438 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1440 r.in.server = &server;
1441 r.in.account = &account;
1442 r.in.password = &lm_pass;
1443 r.in.hash = &lm_verifier;
1445 /* Break the verification */
1446 lm_verifier.hash[0]++;
1448 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1450 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1451 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1452 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1453 nt_errstr(status));
1454 ret = false;
1457 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1458 /* Break the old password */
1459 old_lm_hash[0]++;
1460 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1461 /* unbreak it for the next operation */
1462 old_lm_hash[0]--;
1463 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1465 r.in.server = &server;
1466 r.in.account = &account;
1467 r.in.password = &lm_pass;
1468 r.in.hash = &lm_verifier;
1470 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1472 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1473 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1474 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1475 nt_errstr(status));
1476 ret = false;
1479 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1480 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1482 r.in.server = &server;
1483 r.in.account = &account;
1484 r.in.password = &lm_pass;
1485 r.in.hash = NULL;
1487 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1489 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1490 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1491 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1492 nt_errstr(status));
1493 ret = false;
1496 /* This shouldn't be a valid name */
1497 account_bad.string = TEST_ACCOUNT_NAME "XX";
1498 r.in.account = &account_bad;
1500 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1502 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1503 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1504 nt_errstr(status));
1505 ret = false;
1508 /* This shouldn't be a valid name */
1509 account_bad.string = TEST_ACCOUNT_NAME "XX";
1510 r.in.account = &account_bad;
1511 r.in.password = &lm_pass;
1512 r.in.hash = &lm_verifier;
1514 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1516 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1517 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1518 nt_errstr(status));
1519 ret = false;
1522 /* This shouldn't be a valid name */
1523 account_bad.string = TEST_ACCOUNT_NAME "XX";
1524 r.in.account = &account_bad;
1525 r.in.password = NULL;
1526 r.in.hash = &lm_verifier;
1528 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1530 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1531 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
1532 nt_errstr(status));
1533 ret = false;
1536 E_deshash(oldpass, old_lm_hash);
1537 E_deshash(newpass, new_lm_hash);
1539 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1540 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1541 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1543 r.in.server = &server;
1544 r.in.account = &account;
1545 r.in.password = &lm_pass;
1546 r.in.hash = &lm_verifier;
1548 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1549 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1550 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1551 } else if (!NT_STATUS_IS_OK(status)) {
1552 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
1553 ret = false;
1554 } else {
1555 *password = newpass;
1558 return ret;
1562 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1563 const char *acct_name,
1564 char **password,
1565 char *newpass, bool allow_password_restriction)
1567 NTSTATUS status;
1568 struct samr_ChangePasswordUser2 r;
1569 bool ret = true;
1570 struct lsa_String server, account;
1571 struct samr_CryptPassword nt_pass, lm_pass;
1572 struct samr_Password nt_verifier, lm_verifier;
1573 char *oldpass;
1574 uint8_t old_nt_hash[16], new_nt_hash[16];
1575 uint8_t old_lm_hash[16], new_lm_hash[16];
1577 struct samr_GetDomPwInfo dom_pw_info;
1578 struct samr_PwInfo info;
1580 struct lsa_String domain_name;
1582 domain_name.string = "";
1583 dom_pw_info.in.domain_name = &domain_name;
1584 dom_pw_info.out.info = &info;
1586 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
1588 torture_assert(tctx, *password != NULL,
1589 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
1590 oldpass = *password;
1592 if (!newpass) {
1593 int policy_min_pw_len = 0;
1594 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1595 if (NT_STATUS_IS_OK(status)) {
1596 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1599 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1602 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1603 init_lsa_String(&account, acct_name);
1605 E_md4hash(oldpass, old_nt_hash);
1606 E_md4hash(newpass, new_nt_hash);
1608 E_deshash(oldpass, old_lm_hash);
1609 E_deshash(newpass, new_lm_hash);
1611 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
1612 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1613 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1615 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1616 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1617 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1619 r.in.server = &server;
1620 r.in.account = &account;
1621 r.in.nt_password = &nt_pass;
1622 r.in.nt_verifier = &nt_verifier;
1623 r.in.lm_change = 1;
1624 r.in.lm_password = &lm_pass;
1625 r.in.lm_verifier = &lm_verifier;
1627 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
1628 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1629 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1630 } else if (!NT_STATUS_IS_OK(status)) {
1631 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
1632 ret = false;
1633 } else {
1634 *password = newpass;
1637 return ret;
1641 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
1642 const char *account_string,
1643 int policy_min_pw_len,
1644 char **password,
1645 const char *newpass,
1646 NTTIME last_password_change,
1647 bool handle_reject_reason)
1649 NTSTATUS status;
1650 struct samr_ChangePasswordUser3 r;
1651 bool ret = true;
1652 struct lsa_String server, account, account_bad;
1653 struct samr_CryptPassword nt_pass, lm_pass;
1654 struct samr_Password nt_verifier, lm_verifier;
1655 char *oldpass;
1656 uint8_t old_nt_hash[16], new_nt_hash[16];
1657 uint8_t old_lm_hash[16], new_lm_hash[16];
1658 NTTIME t;
1659 struct samr_DomInfo1 *dominfo = NULL;
1660 struct samr_ChangeReject *reject = NULL;
1662 torture_comment(tctx, "Testing ChangePasswordUser3\n");
1664 if (newpass == NULL) {
1665 do {
1666 if (policy_min_pw_len == 0) {
1667 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1668 } else {
1669 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
1671 } while (check_password_quality(newpass) == false);
1672 } else {
1673 torture_comment(tctx, "Using password '%s'\n", newpass);
1676 torture_assert(tctx, *password != NULL,
1677 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
1679 oldpass = *password;
1680 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1681 init_lsa_String(&account, account_string);
1683 E_md4hash(oldpass, old_nt_hash);
1684 E_md4hash(newpass, new_nt_hash);
1686 E_deshash(oldpass, old_lm_hash);
1687 E_deshash(newpass, new_lm_hash);
1689 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
1690 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
1691 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1693 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1694 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1695 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1697 /* Break the verification */
1698 nt_verifier.hash[0]++;
1700 r.in.server = &server;
1701 r.in.account = &account;
1702 r.in.nt_password = &nt_pass;
1703 r.in.nt_verifier = &nt_verifier;
1704 r.in.lm_change = 1;
1705 r.in.lm_password = &lm_pass;
1706 r.in.lm_verifier = &lm_verifier;
1707 r.in.password3 = NULL;
1708 r.out.dominfo = &dominfo;
1709 r.out.reject = &reject;
1711 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
1712 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
1713 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
1714 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1715 nt_errstr(status));
1716 ret = false;
1719 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
1720 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
1721 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1723 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1724 /* Break the NT hash */
1725 old_nt_hash[0]++;
1726 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1727 /* Unbreak it again */
1728 old_nt_hash[0]--;
1729 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1731 r.in.server = &server;
1732 r.in.account = &account;
1733 r.in.nt_password = &nt_pass;
1734 r.in.nt_verifier = &nt_verifier;
1735 r.in.lm_change = 1;
1736 r.in.lm_password = &lm_pass;
1737 r.in.lm_verifier = &lm_verifier;
1738 r.in.password3 = NULL;
1739 r.out.dominfo = &dominfo;
1740 r.out.reject = &reject;
1742 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
1743 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
1744 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
1745 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1746 nt_errstr(status));
1747 ret = false;
1750 /* This shouldn't be a valid name */
1751 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
1753 r.in.account = &account_bad;
1754 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
1755 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1756 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
1757 nt_errstr(status));
1758 ret = false;
1761 E_md4hash(oldpass, old_nt_hash);
1762 E_md4hash(newpass, new_nt_hash);
1764 E_deshash(oldpass, old_lm_hash);
1765 E_deshash(newpass, new_lm_hash);
1767 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
1768 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
1769 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1771 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1772 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1773 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1775 r.in.server = &server;
1776 r.in.account = &account;
1777 r.in.nt_password = &nt_pass;
1778 r.in.nt_verifier = &nt_verifier;
1779 r.in.lm_change = 1;
1780 r.in.lm_password = &lm_pass;
1781 r.in.lm_verifier = &lm_verifier;
1782 r.in.password3 = NULL;
1783 r.out.dominfo = &dominfo;
1784 r.out.reject = &reject;
1786 unix_to_nt_time(&t, time(NULL));
1788 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
1790 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1791 && dominfo
1792 && reject
1793 && handle_reject_reason
1794 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
1795 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
1797 if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
1798 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
1799 SAMR_REJECT_OTHER, reject->reason);
1800 return false;
1804 /* We tested the order of precendence which is as follows:
1806 * pwd min_age
1807 * pwd length
1808 * pwd complexity
1809 * pwd history
1811 Guenther */
1813 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
1814 (last_password_change + dominfo->min_password_age > t)) {
1816 if (reject->reason != SAMR_REJECT_OTHER) {
1817 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
1818 SAMR_REJECT_OTHER, reject->reason);
1819 return false;
1822 } else if ((dominfo->min_password_length > 0) &&
1823 (strlen(newpass) < dominfo->min_password_length)) {
1825 if (reject->reason != SAMR_REJECT_TOO_SHORT) {
1826 printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
1827 SAMR_REJECT_TOO_SHORT, reject->reason);
1828 return false;
1831 } else if ((dominfo->password_history_length > 0) &&
1832 strequal(oldpass, newpass)) {
1834 if (reject->reason != SAMR_REJECT_IN_HISTORY) {
1835 printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
1836 SAMR_REJECT_IN_HISTORY, reject->reason);
1837 return false;
1839 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
1841 if (reject->reason != SAMR_REJECT_COMPLEXITY) {
1842 printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
1843 SAMR_REJECT_COMPLEXITY, reject->reason);
1844 return false;
1849 if (reject->reason == SAMR_REJECT_TOO_SHORT) {
1850 /* retry with adjusted size */
1851 return test_ChangePasswordUser3(p, tctx, account_string,
1852 dominfo->min_password_length,
1853 password, NULL, 0, false);
1857 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1858 if (reject && reject->reason != SAMR_REJECT_OTHER) {
1859 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
1860 SAMR_REJECT_OTHER, reject->reason);
1861 return false;
1863 /* Perhaps the server has a 'min password age' set? */
1865 } else {
1866 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
1867 *password = talloc_strdup(tctx, newpass);
1870 return ret;
1873 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
1874 const char *account_string,
1875 struct policy_handle *handle,
1876 char **password)
1878 NTSTATUS status;
1879 struct samr_ChangePasswordUser3 r;
1880 struct samr_SetUserInfo s;
1881 union samr_UserInfo u;
1882 DATA_BLOB session_key;
1883 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1884 uint8_t confounder[16];
1885 struct MD5Context ctx;
1887 bool ret = true;
1888 struct lsa_String server, account;
1889 struct samr_CryptPassword nt_pass;
1890 struct samr_Password nt_verifier;
1891 DATA_BLOB new_random_pass;
1892 char *newpass;
1893 char *oldpass;
1894 uint8_t old_nt_hash[16], new_nt_hash[16];
1895 NTTIME t;
1896 struct samr_DomInfo1 *dominfo = NULL;
1897 struct samr_ChangeReject *reject = NULL;
1899 new_random_pass = samr_very_rand_pass(tctx, 128);
1901 torture_assert(tctx, *password != NULL,
1902 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
1904 oldpass = *password;
1905 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1906 init_lsa_String(&account, account_string);
1908 s.in.user_handle = handle;
1909 s.in.info = &u;
1910 s.in.level = 25;
1912 ZERO_STRUCT(u);
1914 u.info25.info.fields_present = SAMR_FIELD_PASSWORD;
1916 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
1918 status = dcerpc_fetch_session_key(p, &session_key);
1919 if (!NT_STATUS_IS_OK(status)) {
1920 printf("SetUserInfo level %u - no session key - %s\n",
1921 s.in.level, nt_errstr(status));
1922 return false;
1925 generate_random_buffer((uint8_t *)confounder, 16);
1927 MD5Init(&ctx);
1928 MD5Update(&ctx, confounder, 16);
1929 MD5Update(&ctx, session_key.data, session_key.length);
1930 MD5Final(confounded_session_key.data, &ctx);
1932 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1933 memcpy(&u.info25.password.data[516], confounder, 16);
1935 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
1937 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1938 if (!NT_STATUS_IS_OK(status)) {
1939 printf("SetUserInfo level %u failed - %s\n",
1940 s.in.level, nt_errstr(status));
1941 ret = false;
1944 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
1946 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
1948 new_random_pass = samr_very_rand_pass(tctx, 128);
1950 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
1952 set_pw_in_buffer(nt_pass.data, &new_random_pass);
1953 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1954 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1956 r.in.server = &server;
1957 r.in.account = &account;
1958 r.in.nt_password = &nt_pass;
1959 r.in.nt_verifier = &nt_verifier;
1960 r.in.lm_change = 0;
1961 r.in.lm_password = NULL;
1962 r.in.lm_verifier = NULL;
1963 r.in.password3 = NULL;
1964 r.out.dominfo = &dominfo;
1965 r.out.reject = &reject;
1967 unix_to_nt_time(&t, time(NULL));
1969 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
1971 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1972 if (reject && reject->reason != SAMR_REJECT_OTHER) {
1973 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
1974 SAMR_REJECT_OTHER, reject->reason);
1975 return false;
1977 /* Perhaps the server has a 'min password age' set? */
1979 } else if (!NT_STATUS_IS_OK(status)) {
1980 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
1981 ret = false;
1984 newpass = samr_rand_pass(tctx, 128);
1986 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
1988 E_md4hash(newpass, new_nt_hash);
1990 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1991 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1992 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1994 r.in.server = &server;
1995 r.in.account = &account;
1996 r.in.nt_password = &nt_pass;
1997 r.in.nt_verifier = &nt_verifier;
1998 r.in.lm_change = 0;
1999 r.in.lm_password = NULL;
2000 r.in.lm_verifier = NULL;
2001 r.in.password3 = NULL;
2002 r.out.dominfo = &dominfo;
2003 r.out.reject = &reject;
2005 unix_to_nt_time(&t, time(NULL));
2007 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2009 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2010 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2011 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2012 SAMR_REJECT_OTHER, reject->reason);
2013 return false;
2015 /* Perhaps the server has a 'min password age' set? */
2017 } else {
2018 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2019 *password = talloc_strdup(tctx, newpass);
2022 return ret;
2026 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2027 struct policy_handle *alias_handle)
2029 struct samr_GetMembersInAlias r;
2030 struct lsa_SidArray sids;
2031 NTSTATUS status;
2033 torture_comment(tctx, "Testing GetMembersInAlias\n");
2035 r.in.alias_handle = alias_handle;
2036 r.out.sids = &sids;
2038 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2039 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2041 return true;
2044 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2045 struct policy_handle *alias_handle,
2046 const struct dom_sid *domain_sid)
2048 struct samr_AddAliasMember r;
2049 struct samr_DeleteAliasMember d;
2050 NTSTATUS status;
2051 struct dom_sid *sid;
2053 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2055 torture_comment(tctx, "testing AddAliasMember\n");
2056 r.in.alias_handle = alias_handle;
2057 r.in.sid = sid;
2059 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2060 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2062 d.in.alias_handle = alias_handle;
2063 d.in.sid = sid;
2065 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2066 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2068 return true;
2071 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2072 struct policy_handle *alias_handle)
2074 struct samr_AddMultipleMembersToAlias a;
2075 struct samr_RemoveMultipleMembersFromAlias r;
2076 NTSTATUS status;
2077 struct lsa_SidArray sids;
2079 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2080 a.in.alias_handle = alias_handle;
2081 a.in.sids = &sids;
2083 sids.num_sids = 3;
2084 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2086 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2087 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2088 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2090 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2091 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2094 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2095 r.in.alias_handle = alias_handle;
2096 r.in.sids = &sids;
2098 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2099 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2101 /* strange! removing twice doesn't give any error */
2102 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2103 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2105 /* but removing an alias that isn't there does */
2106 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2108 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2109 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2111 return true;
2114 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2115 struct policy_handle *user_handle)
2117 struct samr_TestPrivateFunctionsUser r;
2118 NTSTATUS status;
2120 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2122 r.in.user_handle = user_handle;
2124 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2125 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2127 return true;
2131 static bool test_user_ops(struct dcerpc_pipe *p,
2132 struct torture_context *tctx,
2133 struct policy_handle *user_handle,
2134 struct policy_handle *domain_handle,
2135 uint32_t base_acct_flags,
2136 const char *base_acct_name, enum torture_samr_choice which_ops)
2138 char *password = NULL;
2139 struct samr_QueryUserInfo q;
2140 NTSTATUS status;
2142 bool ret = true;
2143 int i;
2144 uint32_t rid;
2145 const uint32_t password_fields[] = {
2146 SAMR_FIELD_PASSWORD,
2147 SAMR_FIELD_PASSWORD2,
2148 SAMR_FIELD_PASSWORD | SAMR_FIELD_PASSWORD2,
2152 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
2153 if (!NT_STATUS_IS_OK(status)) {
2154 ret = false;
2157 switch (which_ops) {
2158 case TORTURE_SAMR_USER_ATTRIBUTES:
2159 if (!test_QuerySecurity(p, tctx, user_handle)) {
2160 ret = false;
2163 if (!test_QueryUserInfo(p, tctx, user_handle)) {
2164 ret = false;
2167 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
2168 ret = false;
2171 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
2172 base_acct_name)) {
2173 ret = false;
2176 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
2177 ret = false;
2180 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
2181 ret = false;
2184 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
2185 ret = false;
2187 break;
2188 case TORTURE_SAMR_PASSWORDS:
2189 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
2190 char simple_pass[9];
2191 char *v = generate_random_str(tctx, 1);
2193 ZERO_STRUCT(simple_pass);
2194 memset(simple_pass, *v, sizeof(simple_pass) - 1);
2196 printf("Testing machine account password policy rules\n");
2198 /* Workstation trust accounts don't seem to need to honour password quality policy */
2199 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
2200 ret = false;
2203 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
2204 ret = false;
2207 /* reset again, to allow another 'user' password change */
2208 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
2209 ret = false;
2212 /* Try a 'short' password */
2213 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
2214 ret = false;
2217 /* Try a compleatly random password */
2218 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
2219 ret = false;
2223 for (i = 0; password_fields[i]; i++) {
2224 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
2225 ret = false;
2228 /* check it was set right */
2229 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
2230 ret = false;
2234 for (i = 0; password_fields[i]; i++) {
2235 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
2236 ret = false;
2239 /* check it was set right */
2240 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
2241 ret = false;
2245 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
2246 ret = false;
2249 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
2250 ret = false;
2253 q.in.user_handle = user_handle;
2254 q.in.level = 5;
2256 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
2257 if (!NT_STATUS_IS_OK(status)) {
2258 printf("QueryUserInfo level %u failed - %s\n",
2259 q.in.level, nt_errstr(status));
2260 ret = false;
2261 } else {
2262 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
2263 if ((q.out.info->info5.acct_flags) != expected_flags) {
2264 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
2265 q.out.info->info5.acct_flags,
2266 expected_flags);
2267 ret = false;
2269 if (q.out.info->info5.rid != rid) {
2270 printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
2271 q.out.info->info5.rid, rid);
2276 break;
2277 case TORTURE_SAMR_OTHER:
2278 /* We just need the account to exist */
2279 break;
2281 return ret;
2284 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
2285 struct policy_handle *alias_handle,
2286 const struct dom_sid *domain_sid)
2288 bool ret = true;
2290 if (!test_QuerySecurity(p, tctx, alias_handle)) {
2291 ret = false;
2294 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
2295 ret = false;
2298 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
2299 ret = false;
2302 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
2303 ret = false;
2306 if (torture_setting_bool(tctx, "samba4", false)) {
2307 printf("skipping MultipleMembers Alias tests against Samba4\n");
2308 return ret;
2311 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
2312 ret = false;
2315 return ret;
2319 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2320 struct policy_handle *user_handle)
2322 struct samr_DeleteUser d;
2323 NTSTATUS status;
2324 torture_comment(tctx, "Testing DeleteUser\n");
2326 d.in.user_handle = user_handle;
2327 d.out.user_handle = user_handle;
2329 status = dcerpc_samr_DeleteUser(p, tctx, &d);
2330 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
2332 return true;
2335 bool test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2336 struct policy_handle *handle, const char *name)
2338 NTSTATUS status;
2339 struct samr_DeleteUser d;
2340 struct policy_handle user_handle;
2341 uint32_t rid;
2343 status = test_LookupName(p, mem_ctx, handle, name, &rid);
2344 if (!NT_STATUS_IS_OK(status)) {
2345 goto failed;
2348 status = test_OpenUser_byname(p, mem_ctx, handle, name, &user_handle);
2349 if (!NT_STATUS_IS_OK(status)) {
2350 goto failed;
2353 d.in.user_handle = &user_handle;
2354 d.out.user_handle = &user_handle;
2355 status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
2356 if (!NT_STATUS_IS_OK(status)) {
2357 goto failed;
2360 return true;
2362 failed:
2363 printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
2364 return false;
2368 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2369 struct policy_handle *handle, const char *name)
2371 NTSTATUS status;
2372 struct samr_OpenGroup r;
2373 struct samr_DeleteDomainGroup d;
2374 struct policy_handle group_handle;
2375 uint32_t rid;
2377 status = test_LookupName(p, mem_ctx, handle, name, &rid);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 goto failed;
2382 r.in.domain_handle = handle;
2383 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2384 r.in.rid = rid;
2385 r.out.group_handle = &group_handle;
2386 status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 goto failed;
2391 d.in.group_handle = &group_handle;
2392 d.out.group_handle = &group_handle;
2393 status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
2394 if (!NT_STATUS_IS_OK(status)) {
2395 goto failed;
2398 return true;
2400 failed:
2401 printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
2402 return false;
2406 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2407 struct policy_handle *domain_handle, const char *name)
2409 NTSTATUS status;
2410 struct samr_OpenAlias r;
2411 struct samr_DeleteDomAlias d;
2412 struct policy_handle alias_handle;
2413 uint32_t rid;
2415 printf("testing DeleteAlias_byname\n");
2417 status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
2418 if (!NT_STATUS_IS_OK(status)) {
2419 goto failed;
2422 r.in.domain_handle = domain_handle;
2423 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2424 r.in.rid = rid;
2425 r.out.alias_handle = &alias_handle;
2426 status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
2427 if (!NT_STATUS_IS_OK(status)) {
2428 goto failed;
2431 d.in.alias_handle = &alias_handle;
2432 d.out.alias_handle = &alias_handle;
2433 status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
2434 if (!NT_STATUS_IS_OK(status)) {
2435 goto failed;
2438 return true;
2440 failed:
2441 printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
2442 return false;
2445 static bool test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2446 struct policy_handle *alias_handle)
2448 struct samr_DeleteDomAlias d;
2449 NTSTATUS status;
2450 bool ret = true;
2451 printf("Testing DeleteAlias\n");
2453 d.in.alias_handle = alias_handle;
2454 d.out.alias_handle = alias_handle;
2456 status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
2457 if (!NT_STATUS_IS_OK(status)) {
2458 printf("DeleteAlias failed - %s\n", nt_errstr(status));
2459 ret = false;
2462 return ret;
2465 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2466 struct policy_handle *domain_handle,
2467 struct policy_handle *alias_handle,
2468 const struct dom_sid *domain_sid)
2470 NTSTATUS status;
2471 struct samr_CreateDomAlias r;
2472 struct lsa_String name;
2473 uint32_t rid;
2474 bool ret = true;
2476 init_lsa_String(&name, TEST_ALIASNAME);
2477 r.in.domain_handle = domain_handle;
2478 r.in.alias_name = &name;
2479 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2480 r.out.alias_handle = alias_handle;
2481 r.out.rid = &rid;
2483 printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
2485 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
2487 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
2488 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2489 printf("Server correctly refused create of '%s'\n", r.in.alias_name->string);
2490 return true;
2491 } else {
2492 printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
2493 nt_errstr(status));
2494 return false;
2498 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
2499 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
2500 return false;
2502 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
2505 if (!NT_STATUS_IS_OK(status)) {
2506 printf("CreateAlias failed - %s\n", nt_errstr(status));
2507 return false;
2510 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
2511 ret = false;
2514 return ret;
2517 static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2518 const char *acct_name,
2519 struct policy_handle *domain_handle, char **password)
2521 bool ret = true;
2523 if (!*password) {
2524 return false;
2527 if (!test_ChangePasswordUser(p, mem_ctx, acct_name, domain_handle, password)) {
2528 ret = false;
2531 if (!test_ChangePasswordUser2(p, mem_ctx, acct_name, password, 0, true)) {
2532 ret = false;
2535 if (!test_OemChangePasswordUser2(p, mem_ctx, acct_name, domain_handle, password)) {
2536 ret = false;
2539 /* test what happens when setting the old password again */
2540 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, *password, 0, true)) {
2541 ret = false;
2545 char simple_pass[9];
2546 char *v = generate_random_str(mem_ctx, 1);
2548 ZERO_STRUCT(simple_pass);
2549 memset(simple_pass, *v, sizeof(simple_pass) - 1);
2551 /* test what happens when picking a simple password */
2552 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, simple_pass, 0, true)) {
2553 ret = false;
2557 /* set samr_SetDomainInfo level 1 with min_length 5 */
2559 struct samr_QueryDomainInfo r;
2560 union samr_DomainInfo *info = NULL;
2561 struct samr_SetDomainInfo s;
2562 uint16_t len_old, len;
2563 uint32_t pwd_prop_old;
2564 int64_t min_pwd_age_old;
2565 NTSTATUS status;
2567 len = 5;
2569 r.in.domain_handle = domain_handle;
2570 r.in.level = 1;
2571 r.out.info = &info;
2573 printf("testing samr_QueryDomainInfo level 1\n");
2574 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
2575 if (!NT_STATUS_IS_OK(status)) {
2576 return false;
2579 s.in.domain_handle = domain_handle;
2580 s.in.level = 1;
2581 s.in.info = info;
2583 /* remember the old min length, so we can reset it */
2584 len_old = s.in.info->info1.min_password_length;
2585 s.in.info->info1.min_password_length = len;
2586 pwd_prop_old = s.in.info->info1.password_properties;
2587 /* turn off password complexity checks for this test */
2588 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
2590 min_pwd_age_old = s.in.info->info1.min_password_age;
2591 s.in.info->info1.min_password_age = 0;
2593 printf("testing samr_SetDomainInfo level 1\n");
2594 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
2595 if (!NT_STATUS_IS_OK(status)) {
2596 return false;
2599 printf("calling test_ChangePasswordUser3 with too short password\n");
2601 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, len - 1, password, NULL, 0, true)) {
2602 ret = false;
2605 s.in.info->info1.min_password_length = len_old;
2606 s.in.info->info1.password_properties = pwd_prop_old;
2607 s.in.info->info1.min_password_age = min_pwd_age_old;
2609 printf("testing samr_SetDomainInfo level 1\n");
2610 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
2611 if (!NT_STATUS_IS_OK(status)) {
2612 return false;
2618 NTSTATUS status;
2619 struct samr_OpenUser r;
2620 struct samr_QueryUserInfo q;
2621 struct samr_LookupNames n;
2622 struct policy_handle user_handle;
2624 n.in.domain_handle = domain_handle;
2625 n.in.num_names = 1;
2626 n.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
2627 n.in.names[0].string = acct_name;
2629 status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
2630 if (!NT_STATUS_IS_OK(status)) {
2631 printf("LookupNames failed - %s\n", nt_errstr(status));
2632 return false;
2635 r.in.domain_handle = domain_handle;
2636 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2637 r.in.rid = n.out.rids.ids[0];
2638 r.out.user_handle = &user_handle;
2640 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
2641 if (!NT_STATUS_IS_OK(status)) {
2642 printf("OpenUser(%u) failed - %s\n", n.out.rids.ids[0], nt_errstr(status));
2643 return false;
2646 q.in.user_handle = &user_handle;
2647 q.in.level = 5;
2649 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
2650 if (!NT_STATUS_IS_OK(status)) {
2651 printf("QueryUserInfo failed - %s\n", nt_errstr(status));
2652 return false;
2655 printf("calling test_ChangePasswordUser3 with too early password change\n");
2657 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL,
2658 q.out.info->info5.last_password_change, true)) {
2659 ret = false;
2663 /* we change passwords twice - this has the effect of verifying
2664 they were changed correctly for the final call */
2665 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
2666 ret = false;
2669 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
2670 ret = false;
2673 return ret;
2676 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2677 struct policy_handle *domain_handle,
2678 struct policy_handle *user_handle_out,
2679 struct dom_sid *domain_sid,
2680 enum torture_samr_choice which_ops)
2683 TALLOC_CTX *user_ctx;
2685 NTSTATUS status;
2686 struct samr_CreateUser r;
2687 struct samr_QueryUserInfo q;
2688 struct samr_DeleteUser d;
2689 uint32_t rid;
2691 /* This call creates a 'normal' account - check that it really does */
2692 const uint32_t acct_flags = ACB_NORMAL;
2693 struct lsa_String name;
2694 bool ret = true;
2696 struct policy_handle user_handle;
2697 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
2698 init_lsa_String(&name, TEST_ACCOUNT_NAME);
2700 r.in.domain_handle = domain_handle;
2701 r.in.account_name = &name;
2702 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2703 r.out.user_handle = &user_handle;
2704 r.out.rid = &rid;
2706 printf("Testing CreateUser(%s)\n", r.in.account_name->string);
2708 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
2710 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
2711 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
2712 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
2713 return true;
2714 } else {
2715 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
2716 nt_errstr(status));
2717 return false;
2721 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
2722 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
2723 talloc_free(user_ctx);
2724 return false;
2726 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
2728 if (!NT_STATUS_IS_OK(status)) {
2729 talloc_free(user_ctx);
2730 printf("CreateUser failed - %s\n", nt_errstr(status));
2731 return false;
2732 } else {
2733 q.in.user_handle = &user_handle;
2734 q.in.level = 16;
2736 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
2737 if (!NT_STATUS_IS_OK(status)) {
2738 printf("QueryUserInfo level %u failed - %s\n",
2739 q.in.level, nt_errstr(status));
2740 ret = false;
2741 } else {
2742 if ((q.out.info->info16.acct_flags & acct_flags) != acct_flags) {
2743 printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
2744 q.out.info->info16.acct_flags,
2745 acct_flags);
2746 ret = false;
2750 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
2751 acct_flags, name.string, which_ops)) {
2752 ret = false;
2755 if (user_handle_out) {
2756 *user_handle_out = user_handle;
2757 } else {
2758 printf("Testing DeleteUser (createuser test)\n");
2760 d.in.user_handle = &user_handle;
2761 d.out.user_handle = &user_handle;
2763 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
2764 if (!NT_STATUS_IS_OK(status)) {
2765 printf("DeleteUser failed - %s\n", nt_errstr(status));
2766 ret = false;
2772 talloc_free(user_ctx);
2774 return ret;
2778 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2779 struct policy_handle *domain_handle,
2780 struct dom_sid *domain_sid,
2781 enum torture_samr_choice which_ops)
2783 NTSTATUS status;
2784 struct samr_CreateUser2 r;
2785 struct samr_QueryUserInfo q;
2786 struct samr_DeleteUser d;
2787 struct policy_handle user_handle;
2788 uint32_t rid;
2789 struct lsa_String name;
2790 bool ret = true;
2791 int i;
2793 struct {
2794 uint32_t acct_flags;
2795 const char *account_name;
2796 NTSTATUS nt_status;
2797 } account_types[] = {
2798 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
2799 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
2800 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
2801 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
2802 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
2803 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
2804 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
2805 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
2806 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
2807 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
2808 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
2809 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
2810 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
2811 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
2812 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
2815 for (i = 0; account_types[i].account_name; i++) {
2816 TALLOC_CTX *user_ctx;
2817 uint32_t acct_flags = account_types[i].acct_flags;
2818 uint32_t access_granted;
2819 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
2820 init_lsa_String(&name, account_types[i].account_name);
2822 r.in.domain_handle = domain_handle;
2823 r.in.account_name = &name;
2824 r.in.acct_flags = acct_flags;
2825 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2826 r.out.user_handle = &user_handle;
2827 r.out.access_granted = &access_granted;
2828 r.out.rid = &rid;
2830 printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
2832 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
2834 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
2835 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
2836 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
2837 continue;
2838 } else {
2839 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
2840 nt_errstr(status));
2841 ret = false;
2842 continue;
2846 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
2847 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
2848 talloc_free(user_ctx);
2849 ret = false;
2850 continue;
2852 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
2855 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
2856 printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
2857 nt_errstr(status), nt_errstr(account_types[i].nt_status));
2858 ret = false;
2861 if (NT_STATUS_IS_OK(status)) {
2862 q.in.user_handle = &user_handle;
2863 q.in.level = 5;
2865 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
2866 if (!NT_STATUS_IS_OK(status)) {
2867 printf("QueryUserInfo level %u failed - %s\n",
2868 q.in.level, nt_errstr(status));
2869 ret = false;
2870 } else {
2871 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
2872 if (acct_flags == ACB_NORMAL) {
2873 expected_flags |= ACB_PW_EXPIRED;
2875 if ((q.out.info->info5.acct_flags) != expected_flags) {
2876 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
2877 q.out.info->info5.acct_flags,
2878 expected_flags);
2879 ret = false;
2881 switch (acct_flags) {
2882 case ACB_SVRTRUST:
2883 if (q.out.info->info5.primary_gid != DOMAIN_RID_DCS) {
2884 printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
2885 DOMAIN_RID_DCS, q.out.info->info5.primary_gid);
2886 ret = false;
2888 break;
2889 case ACB_WSTRUST:
2890 if (q.out.info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
2891 printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
2892 DOMAIN_RID_DOMAIN_MEMBERS, q.out.info->info5.primary_gid);
2893 ret = false;
2895 break;
2896 case ACB_NORMAL:
2897 if (q.out.info->info5.primary_gid != DOMAIN_RID_USERS) {
2898 printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
2899 DOMAIN_RID_USERS, q.out.info->info5.primary_gid);
2900 ret = false;
2902 break;
2906 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
2907 acct_flags, name.string, which_ops)) {
2908 ret = false;
2911 printf("Testing DeleteUser (createuser2 test)\n");
2913 d.in.user_handle = &user_handle;
2914 d.out.user_handle = &user_handle;
2916 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
2917 if (!NT_STATUS_IS_OK(status)) {
2918 printf("DeleteUser failed - %s\n", nt_errstr(status));
2919 ret = false;
2922 talloc_free(user_ctx);
2925 return ret;
2928 static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2929 struct policy_handle *handle)
2931 NTSTATUS status;
2932 struct samr_QueryAliasInfo r;
2933 uint16_t levels[] = {1, 2, 3};
2934 int i;
2935 bool ret = true;
2937 for (i=0;i<ARRAY_SIZE(levels);i++) {
2938 printf("Testing QueryAliasInfo level %u\n", levels[i]);
2940 r.in.alias_handle = handle;
2941 r.in.level = levels[i];
2943 status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
2944 if (!NT_STATUS_IS_OK(status)) {
2945 printf("QueryAliasInfo level %u failed - %s\n",
2946 levels[i], nt_errstr(status));
2947 ret = false;
2951 return ret;
2954 static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2955 struct policy_handle *handle)
2957 NTSTATUS status;
2958 struct samr_QueryGroupInfo r;
2959 uint16_t levels[] = {1, 2, 3, 4, 5};
2960 int i;
2961 bool ret = true;
2963 for (i=0;i<ARRAY_SIZE(levels);i++) {
2964 printf("Testing QueryGroupInfo level %u\n", levels[i]);
2966 r.in.group_handle = handle;
2967 r.in.level = levels[i];
2969 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
2970 if (!NT_STATUS_IS_OK(status)) {
2971 printf("QueryGroupInfo level %u failed - %s\n",
2972 levels[i], nt_errstr(status));
2973 ret = false;
2977 return ret;
2980 static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2981 struct policy_handle *handle)
2983 NTSTATUS status;
2984 struct samr_QueryGroupMember r;
2985 struct samr_RidTypeArray *rids = NULL;
2986 bool ret = true;
2988 printf("Testing QueryGroupMember\n");
2990 r.in.group_handle = handle;
2991 r.out.rids = &rids;
2993 status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r);
2994 if (!NT_STATUS_IS_OK(status)) {
2995 printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
2996 ret = false;
2999 return ret;
3003 static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3004 struct policy_handle *handle)
3006 NTSTATUS status;
3007 struct samr_QueryGroupInfo r;
3008 struct samr_SetGroupInfo s;
3009 uint16_t levels[] = {1, 2, 3, 4};
3010 uint16_t set_ok[] = {0, 1, 1, 1};
3011 int i;
3012 bool ret = true;
3014 for (i=0;i<ARRAY_SIZE(levels);i++) {
3015 printf("Testing QueryGroupInfo level %u\n", levels[i]);
3017 r.in.group_handle = handle;
3018 r.in.level = levels[i];
3020 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
3021 if (!NT_STATUS_IS_OK(status)) {
3022 printf("QueryGroupInfo level %u failed - %s\n",
3023 levels[i], nt_errstr(status));
3024 ret = false;
3027 printf("Testing SetGroupInfo level %u\n", levels[i]);
3029 s.in.group_handle = handle;
3030 s.in.level = levels[i];
3031 s.in.info = r.out.info;
3033 #if 0
3034 /* disabled this, as it changes the name only from the point of view of samr,
3035 but leaves the name from the point of view of w2k3 internals (and ldap). This means
3036 the name is still reserved, so creating the old name fails, but deleting by the old name
3037 also fails */
3038 if (s.in.level == 2) {
3039 init_lsa_String(&s.in.info->string, "NewName");
3041 #endif
3043 if (s.in.level == 4) {
3044 init_lsa_String(&s.in.info->description, "test description");
3047 status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
3048 if (set_ok[i]) {
3049 if (!NT_STATUS_IS_OK(status)) {
3050 printf("SetGroupInfo level %u failed - %s\n",
3051 r.in.level, nt_errstr(status));
3052 ret = false;
3053 continue;
3055 } else {
3056 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
3057 printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
3058 r.in.level, nt_errstr(status));
3059 ret = false;
3060 continue;
3065 return ret;
3068 static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3069 struct policy_handle *handle)
3071 NTSTATUS status;
3072 struct samr_QueryUserInfo r;
3073 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
3074 11, 12, 13, 14, 16, 17, 20, 21};
3075 int i;
3076 bool ret = true;
3078 for (i=0;i<ARRAY_SIZE(levels);i++) {
3079 printf("Testing QueryUserInfo level %u\n", levels[i]);
3081 r.in.user_handle = handle;
3082 r.in.level = levels[i];
3084 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r);
3085 if (!NT_STATUS_IS_OK(status)) {
3086 printf("QueryUserInfo level %u failed - %s\n",
3087 levels[i], nt_errstr(status));
3088 ret = false;
3092 return ret;
3095 static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3096 struct policy_handle *handle)
3098 NTSTATUS status;
3099 struct samr_QueryUserInfo2 r;
3100 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
3101 11, 12, 13, 14, 16, 17, 20, 21};
3102 int i;
3103 bool ret = true;
3105 for (i=0;i<ARRAY_SIZE(levels);i++) {
3106 printf("Testing QueryUserInfo2 level %u\n", levels[i]);
3108 r.in.user_handle = handle;
3109 r.in.level = levels[i];
3111 status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r);
3112 if (!NT_STATUS_IS_OK(status)) {
3113 printf("QueryUserInfo2 level %u failed - %s\n",
3114 levels[i], nt_errstr(status));
3115 ret = false;
3119 return ret;
3122 static bool test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3123 struct policy_handle *handle, uint32_t rid)
3125 NTSTATUS status;
3126 struct samr_OpenUser r;
3127 struct policy_handle user_handle;
3128 bool ret = true;
3130 printf("Testing OpenUser(%u)\n", rid);
3132 r.in.domain_handle = handle;
3133 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3134 r.in.rid = rid;
3135 r.out.user_handle = &user_handle;
3137 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
3138 if (!NT_STATUS_IS_OK(status)) {
3139 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
3140 return false;
3143 if (!test_QuerySecurity(p, mem_ctx, &user_handle)) {
3144 ret = false;
3147 if (!test_QueryUserInfo(p, mem_ctx, &user_handle)) {
3148 ret = false;
3151 if (!test_QueryUserInfo2(p, mem_ctx, &user_handle)) {
3152 ret = false;
3155 if (!test_GetUserPwInfo(p, mem_ctx, &user_handle)) {
3156 ret = false;
3159 if (!test_GetGroupsForUser(p,mem_ctx, &user_handle)) {
3160 ret = false;
3163 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
3164 ret = false;
3167 return ret;
3170 static bool test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3171 struct policy_handle *handle, uint32_t rid)
3173 NTSTATUS status;
3174 struct samr_OpenGroup r;
3175 struct policy_handle group_handle;
3176 bool ret = true;
3178 printf("Testing OpenGroup(%u)\n", rid);
3180 r.in.domain_handle = handle;
3181 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3182 r.in.rid = rid;
3183 r.out.group_handle = &group_handle;
3185 status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
3186 if (!NT_STATUS_IS_OK(status)) {
3187 printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
3188 return false;
3191 if (!test_QuerySecurity(p, mem_ctx, &group_handle)) {
3192 ret = false;
3195 if (!test_QueryGroupInfo(p, mem_ctx, &group_handle)) {
3196 ret = false;
3199 if (!test_QueryGroupMember(p, mem_ctx, &group_handle)) {
3200 ret = false;
3203 if (!test_samr_handle_Close(p, mem_ctx, &group_handle)) {
3204 ret = false;
3207 return ret;
3210 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
3211 struct policy_handle *handle, uint32_t rid)
3213 NTSTATUS status;
3214 struct samr_OpenAlias r;
3215 struct policy_handle alias_handle;
3216 bool ret = true;
3218 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
3220 r.in.domain_handle = handle;
3221 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3222 r.in.rid = rid;
3223 r.out.alias_handle = &alias_handle;
3225 status = dcerpc_samr_OpenAlias(p, tctx, &r);
3226 if (!NT_STATUS_IS_OK(status)) {
3227 printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
3228 return false;
3231 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
3232 ret = false;
3235 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
3236 ret = false;
3239 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
3240 ret = false;
3243 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
3244 ret = false;
3247 return ret;
3250 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
3251 struct policy_handle *handle, uint32_t rid,
3252 uint32_t acct_flag_mask)
3254 NTSTATUS status;
3255 struct samr_OpenUser r;
3256 struct samr_QueryUserInfo q;
3257 struct policy_handle user_handle;
3258 bool ret = true;
3260 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
3262 r.in.domain_handle = handle;
3263 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3264 r.in.rid = rid;
3265 r.out.user_handle = &user_handle;
3267 status = dcerpc_samr_OpenUser(p, tctx, &r);
3268 if (!NT_STATUS_IS_OK(status)) {
3269 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
3270 return false;
3273 q.in.user_handle = &user_handle;
3274 q.in.level = 16;
3276 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3277 if (!NT_STATUS_IS_OK(status)) {
3278 printf("QueryUserInfo level 16 failed - %s\n",
3279 nt_errstr(status));
3280 ret = false;
3281 } else {
3282 if ((acct_flag_mask & q.out.info->info16.acct_flags) == 0) {
3283 printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
3284 acct_flag_mask, q.out.info->info16.acct_flags, rid);
3285 ret = false;
3289 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
3290 ret = false;
3293 return ret;
3296 static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *tctx,
3297 struct policy_handle *handle)
3299 NTSTATUS status = STATUS_MORE_ENTRIES;
3300 struct samr_EnumDomainUsers r;
3301 uint32_t mask, resume_handle=0;
3302 int i, mask_idx;
3303 bool ret = true;
3304 struct samr_LookupNames n;
3305 struct samr_LookupRids lr ;
3306 struct lsa_Strings names;
3307 struct samr_Ids types;
3309 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
3310 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
3311 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
3312 ACB_PWNOEXP, 0};
3314 printf("Testing EnumDomainUsers\n");
3316 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
3317 r.in.domain_handle = handle;
3318 r.in.resume_handle = &resume_handle;
3319 r.in.acct_flags = mask = masks[mask_idx];
3320 r.in.max_size = (uint32_t)-1;
3321 r.out.resume_handle = &resume_handle;
3323 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
3324 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
3325 !NT_STATUS_IS_OK(status)) {
3326 printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
3327 return false;
3330 torture_assert(tctx, r.out.sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
3332 if (r.out.sam->count == 0) {
3333 continue;
3336 for (i=0;i<r.out.sam->count;i++) {
3337 if (mask) {
3338 if (!check_mask(p, tctx, handle, r.out.sam->entries[i].idx, mask)) {
3339 ret = false;
3341 } else if (!test_OpenUser(p, tctx, handle, r.out.sam->entries[i].idx)) {
3342 ret = false;
3347 printf("Testing LookupNames\n");
3348 n.in.domain_handle = handle;
3349 n.in.num_names = r.out.sam->count;
3350 n.in.names = talloc_array(tctx, struct lsa_String, r.out.sam->count);
3351 for (i=0;i<r.out.sam->count;i++) {
3352 n.in.names[i].string = r.out.sam->entries[i].name.string;
3354 status = dcerpc_samr_LookupNames(p, tctx, &n);
3355 if (!NT_STATUS_IS_OK(status)) {
3356 printf("LookupNames failed - %s\n", nt_errstr(status));
3357 ret = false;
3361 printf("Testing LookupRids\n");
3362 lr.in.domain_handle = handle;
3363 lr.in.num_rids = r.out.sam->count;
3364 lr.in.rids = talloc_array(tctx, uint32_t, r.out.sam->count);
3365 lr.out.names = &names;
3366 lr.out.types = &types;
3367 for (i=0;i<r.out.sam->count;i++) {
3368 lr.in.rids[i] = r.out.sam->entries[i].idx;
3370 status = dcerpc_samr_LookupRids(p, tctx, &lr);
3371 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
3373 return ret;
3377 try blasting the server with a bunch of sync requests
3379 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
3380 struct policy_handle *handle)
3382 NTSTATUS status;
3383 struct samr_EnumDomainUsers r;
3384 uint32_t resume_handle=0;
3385 int i;
3386 #define ASYNC_COUNT 100
3387 struct rpc_request *req[ASYNC_COUNT];
3389 if (!torture_setting_bool(tctx, "dangerous", false)) {
3390 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
3393 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
3395 r.in.domain_handle = handle;
3396 r.in.resume_handle = &resume_handle;
3397 r.in.acct_flags = 0;
3398 r.in.max_size = (uint32_t)-1;
3399 r.out.resume_handle = &resume_handle;
3401 for (i=0;i<ASYNC_COUNT;i++) {
3402 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
3405 for (i=0;i<ASYNC_COUNT;i++) {
3406 status = dcerpc_ndr_request_recv(req[i]);
3407 if (!NT_STATUS_IS_OK(status)) {
3408 printf("EnumDomainUsers[%d] failed - %s\n",
3409 i, nt_errstr(status));
3410 return false;
3414 torture_comment(tctx, "%d async requests OK\n", i);
3416 return true;
3419 static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3420 struct policy_handle *handle)
3422 NTSTATUS status;
3423 struct samr_EnumDomainGroups r;
3424 uint32_t resume_handle=0;
3425 int i;
3426 bool ret = true;
3428 printf("Testing EnumDomainGroups\n");
3430 r.in.domain_handle = handle;
3431 r.in.resume_handle = &resume_handle;
3432 r.in.max_size = (uint32_t)-1;
3433 r.out.resume_handle = &resume_handle;
3435 status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
3436 if (!NT_STATUS_IS_OK(status)) {
3437 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
3438 return false;
3441 if (!r.out.sam) {
3442 return false;
3445 for (i=0;i<r.out.sam->count;i++) {
3446 if (!test_OpenGroup(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
3447 ret = false;
3451 return ret;
3454 static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3455 struct policy_handle *handle)
3457 NTSTATUS status;
3458 struct samr_EnumDomainAliases r;
3459 uint32_t resume_handle=0;
3460 int i;
3461 bool ret = true;
3463 printf("Testing EnumDomainAliases\n");
3465 r.in.domain_handle = handle;
3466 r.in.resume_handle = &resume_handle;
3467 r.in.acct_flags = (uint32_t)-1;
3468 r.out.resume_handle = &resume_handle;
3470 status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
3471 if (!NT_STATUS_IS_OK(status)) {
3472 printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
3473 return false;
3476 if (!r.out.sam) {
3477 return false;
3480 for (i=0;i<r.out.sam->count;i++) {
3481 if (!test_OpenAlias(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
3482 ret = false;
3486 return ret;
3489 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3490 struct policy_handle *handle)
3492 NTSTATUS status;
3493 struct samr_GetDisplayEnumerationIndex r;
3494 bool ret = true;
3495 uint16_t levels[] = {1, 2, 3, 4, 5};
3496 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
3497 struct lsa_String name;
3498 uint32_t idx = 0;
3499 int i;
3501 for (i=0;i<ARRAY_SIZE(levels);i++) {
3502 printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
3504 init_lsa_String(&name, TEST_ACCOUNT_NAME);
3506 r.in.domain_handle = handle;
3507 r.in.level = levels[i];
3508 r.in.name = &name;
3509 r.out.idx = &idx;
3511 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
3513 if (ok_lvl[i] &&
3514 !NT_STATUS_IS_OK(status) &&
3515 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
3516 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
3517 levels[i], nt_errstr(status));
3518 ret = false;
3521 init_lsa_String(&name, "zzzzzzzz");
3523 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
3525 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
3526 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
3527 levels[i], nt_errstr(status));
3528 ret = false;
3532 return ret;
3535 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3536 struct policy_handle *handle)
3538 NTSTATUS status;
3539 struct samr_GetDisplayEnumerationIndex2 r;
3540 bool ret = true;
3541 uint16_t levels[] = {1, 2, 3, 4, 5};
3542 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
3543 struct lsa_String name;
3544 uint32_t idx = 0;
3545 int i;
3547 for (i=0;i<ARRAY_SIZE(levels);i++) {
3548 printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
3550 init_lsa_String(&name, TEST_ACCOUNT_NAME);
3552 r.in.domain_handle = handle;
3553 r.in.level = levels[i];
3554 r.in.name = &name;
3555 r.out.idx = &idx;
3557 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
3558 if (ok_lvl[i] &&
3559 !NT_STATUS_IS_OK(status) &&
3560 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
3561 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
3562 levels[i], nt_errstr(status));
3563 ret = false;
3566 init_lsa_String(&name, "zzzzzzzz");
3568 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
3569 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
3570 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
3571 levels[i], nt_errstr(status));
3572 ret = false;
3576 return ret;
3579 #define STRING_EQUAL_QUERY(s1, s2, user) \
3580 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
3581 /* odd, but valid */ \
3582 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
3583 printf("%s mismatch for %s: %s != %s (%s)\n", \
3584 #s1, user.string, s1.string, s2.string, __location__); \
3585 ret = false; \
3587 #define INT_EQUAL_QUERY(s1, s2, user) \
3588 if (s1 != s2) { \
3589 printf("%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
3590 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
3591 ret = false; \
3594 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3595 struct samr_QueryDisplayInfo *querydisplayinfo,
3596 bool *seen_testuser)
3598 struct samr_OpenUser r;
3599 struct samr_QueryUserInfo q;
3600 struct policy_handle user_handle;
3601 int i, ret = true;
3602 NTSTATUS status;
3603 r.in.domain_handle = querydisplayinfo->in.domain_handle;
3604 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3605 for (i = 0; ; i++) {
3606 switch (querydisplayinfo->in.level) {
3607 case 1:
3608 if (i >= querydisplayinfo->out.info->info1.count) {
3609 return ret;
3611 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
3612 break;
3613 case 2:
3614 if (i >= querydisplayinfo->out.info->info2.count) {
3615 return ret;
3617 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
3618 break;
3619 case 3:
3620 /* Groups */
3621 case 4:
3622 case 5:
3623 /* Not interested in validating just the account name */
3624 return true;
3627 r.out.user_handle = &user_handle;
3629 switch (querydisplayinfo->in.level) {
3630 case 1:
3631 case 2:
3632 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
3633 if (!NT_STATUS_IS_OK(status)) {
3634 printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
3635 return false;
3639 q.in.user_handle = &user_handle;
3640 q.in.level = 21;
3641 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
3642 if (!NT_STATUS_IS_OK(status)) {
3643 printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
3644 return false;
3647 switch (querydisplayinfo->in.level) {
3648 case 1:
3649 if (seen_testuser && strcmp(q.out.info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
3650 *seen_testuser = true;
3652 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
3653 q.out.info->info21.full_name, q.out.info->info21.account_name);
3654 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
3655 q.out.info->info21.account_name, q.out.info->info21.account_name);
3656 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
3657 q.out.info->info21.description, q.out.info->info21.account_name);
3658 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
3659 q.out.info->info21.rid, q.out.info->info21.account_name);
3660 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
3661 q.out.info->info21.acct_flags, q.out.info->info21.account_name);
3663 break;
3664 case 2:
3665 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
3666 q.out.info->info21.account_name, q.out.info->info21.account_name);
3667 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
3668 q.out.info->info21.description, q.out.info->info21.account_name);
3669 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
3670 q.out.info->info21.rid, q.out.info->info21.account_name);
3671 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
3672 q.out.info->info21.acct_flags, q.out.info->info21.account_name);
3674 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
3675 printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
3676 q.out.info->info21.account_name.string);
3679 if (!(q.out.info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
3680 printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
3681 q.out.info->info21.account_name.string,
3682 querydisplayinfo->out.info->info2.entries[i].acct_flags,
3683 q.out.info->info21.acct_flags);
3684 return false;
3687 break;
3690 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
3691 return false;
3694 return ret;
3697 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3698 struct policy_handle *handle)
3700 NTSTATUS status;
3701 struct samr_QueryDisplayInfo r;
3702 struct samr_QueryDomainInfo dom_info;
3703 union samr_DomainInfo *info = NULL;
3704 bool ret = true;
3705 uint16_t levels[] = {1, 2, 3, 4, 5};
3706 int i;
3707 bool seen_testuser = false;
3708 uint32_t total_size;
3709 uint32_t returned_size;
3710 union samr_DispInfo disp_info;
3713 for (i=0;i<ARRAY_SIZE(levels);i++) {
3714 printf("Testing QueryDisplayInfo level %u\n", levels[i]);
3716 r.in.start_idx = 0;
3717 status = STATUS_MORE_ENTRIES;
3718 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
3719 r.in.domain_handle = handle;
3720 r.in.level = levels[i];
3721 r.in.max_entries = 2;
3722 r.in.buf_size = (uint32_t)-1;
3723 r.out.total_size = &total_size;
3724 r.out.returned_size = &returned_size;
3725 r.out.info = &disp_info;
3727 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
3728 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
3729 printf("QueryDisplayInfo level %u failed - %s\n",
3730 levels[i], nt_errstr(status));
3731 ret = false;
3733 switch (r.in.level) {
3734 case 1:
3735 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) {
3736 ret = false;
3738 r.in.start_idx += r.out.info->info1.count;
3739 break;
3740 case 2:
3741 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) {
3742 ret = false;
3744 r.in.start_idx += r.out.info->info2.count;
3745 break;
3746 case 3:
3747 r.in.start_idx += r.out.info->info3.count;
3748 break;
3749 case 4:
3750 r.in.start_idx += r.out.info->info4.count;
3751 break;
3752 case 5:
3753 r.in.start_idx += r.out.info->info5.count;
3754 break;
3757 dom_info.in.domain_handle = handle;
3758 dom_info.in.level = 2;
3759 dom_info.out.info = &info;
3761 /* Check number of users returned is correct */
3762 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info);
3763 if (!NT_STATUS_IS_OK(status)) {
3764 printf("QueryDomainInfo level %u failed - %s\n",
3765 r.in.level, nt_errstr(status));
3766 ret = false;
3767 break;
3769 switch (r.in.level) {
3770 case 1:
3771 case 4:
3772 if (info->general.num_users < r.in.start_idx) {
3773 printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
3774 r.in.start_idx, info->general.num_groups,
3775 info->general.domain_name.string);
3776 ret = false;
3778 if (!seen_testuser) {
3779 struct policy_handle user_handle;
3780 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
3781 printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
3782 info->general.domain_name.string);
3783 ret = false;
3784 test_samr_handle_Close(p, mem_ctx, &user_handle);
3787 break;
3788 case 3:
3789 case 5:
3790 if (info->general.num_groups != r.in.start_idx) {
3791 printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
3792 r.in.start_idx, info->general.num_groups,
3793 info->general.domain_name.string);
3794 ret = false;
3797 break;
3802 return ret;
3805 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3806 struct policy_handle *handle)
3808 NTSTATUS status;
3809 struct samr_QueryDisplayInfo2 r;
3810 bool ret = true;
3811 uint16_t levels[] = {1, 2, 3, 4, 5};
3812 int i;
3813 uint32_t total_size;
3814 uint32_t returned_size;
3815 union samr_DispInfo info;
3817 for (i=0;i<ARRAY_SIZE(levels);i++) {
3818 printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
3820 r.in.domain_handle = handle;
3821 r.in.level = levels[i];
3822 r.in.start_idx = 0;
3823 r.in.max_entries = 1000;
3824 r.in.buf_size = (uint32_t)-1;
3825 r.out.total_size = &total_size;
3826 r.out.returned_size = &returned_size;
3827 r.out.info = &info;
3829 status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
3830 if (!NT_STATUS_IS_OK(status)) {
3831 printf("QueryDisplayInfo2 level %u failed - %s\n",
3832 levels[i], nt_errstr(status));
3833 ret = false;
3837 return ret;
3840 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
3841 struct policy_handle *handle)
3843 NTSTATUS status;
3844 struct samr_QueryDisplayInfo3 r;
3845 bool ret = true;
3846 uint16_t levels[] = {1, 2, 3, 4, 5};
3847 int i;
3848 uint32_t total_size;
3849 uint32_t returned_size;
3850 union samr_DispInfo info;
3852 for (i=0;i<ARRAY_SIZE(levels);i++) {
3853 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
3855 r.in.domain_handle = handle;
3856 r.in.level = levels[i];
3857 r.in.start_idx = 0;
3858 r.in.max_entries = 1000;
3859 r.in.buf_size = (uint32_t)-1;
3860 r.out.total_size = &total_size;
3861 r.out.returned_size = &returned_size;
3862 r.out.info = &info;
3864 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
3865 if (!NT_STATUS_IS_OK(status)) {
3866 printf("QueryDisplayInfo3 level %u failed - %s\n",
3867 levels[i], nt_errstr(status));
3868 ret = false;
3872 return ret;
3876 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3877 struct policy_handle *handle)
3879 NTSTATUS status;
3880 struct samr_QueryDisplayInfo r;
3881 bool ret = true;
3882 uint32_t total_size;
3883 uint32_t returned_size;
3884 union samr_DispInfo info;
3886 printf("Testing QueryDisplayInfo continuation\n");
3888 r.in.domain_handle = handle;
3889 r.in.level = 1;
3890 r.in.start_idx = 0;
3891 r.in.max_entries = 1;
3892 r.in.buf_size = (uint32_t)-1;
3893 r.out.total_size = &total_size;
3894 r.out.returned_size = &returned_size;
3895 r.out.info = &info;
3897 do {
3898 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
3899 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
3900 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
3901 printf("expected idx %d but got %d\n",
3902 r.in.start_idx + 1,
3903 r.out.info->info1.entries[0].idx);
3904 break;
3907 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
3908 !NT_STATUS_IS_OK(status)) {
3909 printf("QueryDisplayInfo level %u failed - %s\n",
3910 r.in.level, nt_errstr(status));
3911 ret = false;
3912 break;
3914 r.in.start_idx++;
3915 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
3916 NT_STATUS_IS_OK(status)) &&
3917 *r.out.returned_size != 0);
3919 return ret;
3922 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
3923 struct policy_handle *handle)
3925 NTSTATUS status;
3926 struct samr_QueryDomainInfo r;
3927 union samr_DomainInfo *info = NULL;
3928 struct samr_SetDomainInfo s;
3929 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
3930 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
3931 int i;
3932 bool ret = true;
3933 const char *domain_comment = talloc_asprintf(tctx,
3934 "Tortured by Samba4 RPC-SAMR: %s",
3935 timestring(tctx, time(NULL)));
3937 s.in.domain_handle = handle;
3938 s.in.level = 4;
3939 s.in.info = talloc(tctx, union samr_DomainInfo);
3941 s.in.info->oem.oem_information.string = domain_comment;
3942 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
3943 if (!NT_STATUS_IS_OK(status)) {
3944 printf("SetDomainInfo level %u (set comment) failed - %s\n",
3945 r.in.level, nt_errstr(status));
3946 return false;
3949 for (i=0;i<ARRAY_SIZE(levels);i++) {
3950 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
3952 r.in.domain_handle = handle;
3953 r.in.level = levels[i];
3954 r.out.info = &info;
3956 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
3957 if (!NT_STATUS_IS_OK(status)) {
3958 printf("QueryDomainInfo level %u failed - %s\n",
3959 r.in.level, nt_errstr(status));
3960 ret = false;
3961 continue;
3964 switch (levels[i]) {
3965 case 2:
3966 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
3967 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
3968 levels[i], info->general.oem_information.string, domain_comment);
3969 ret = false;
3971 if (!info->general.primary.string) {
3972 printf("QueryDomainInfo level %u returned no PDC name\n",
3973 levels[i]);
3974 ret = false;
3975 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
3976 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
3977 printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
3978 levels[i], info->general.primary.string, dcerpc_server_name(p));
3981 break;
3982 case 4:
3983 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
3984 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
3985 levels[i], info->oem.oem_information.string, domain_comment);
3986 ret = false;
3988 break;
3989 case 6:
3990 if (!info->info6.primary.string) {
3991 printf("QueryDomainInfo level %u returned no PDC name\n",
3992 levels[i]);
3993 ret = false;
3995 break;
3996 case 11:
3997 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
3998 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
3999 levels[i], info->general2.general.oem_information.string, domain_comment);
4000 ret = false;
4002 break;
4005 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
4007 s.in.domain_handle = handle;
4008 s.in.level = levels[i];
4009 s.in.info = info;
4011 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
4012 if (set_ok[i]) {
4013 if (!NT_STATUS_IS_OK(status)) {
4014 printf("SetDomainInfo level %u failed - %s\n",
4015 r.in.level, nt_errstr(status));
4016 ret = false;
4017 continue;
4019 } else {
4020 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4021 printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4022 r.in.level, nt_errstr(status));
4023 ret = false;
4024 continue;
4028 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
4029 if (!NT_STATUS_IS_OK(status)) {
4030 printf("QueryDomainInfo level %u failed - %s\n",
4031 r.in.level, nt_errstr(status));
4032 ret = false;
4033 continue;
4037 return ret;
4041 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
4042 struct policy_handle *handle)
4044 NTSTATUS status;
4045 struct samr_QueryDomainInfo2 r;
4046 union samr_DomainInfo *info = NULL;
4047 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
4048 int i;
4049 bool ret = true;
4051 for (i=0;i<ARRAY_SIZE(levels);i++) {
4052 printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
4054 r.in.domain_handle = handle;
4055 r.in.level = levels[i];
4056 r.out.info = &info;
4058 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
4059 if (!NT_STATUS_IS_OK(status)) {
4060 printf("QueryDomainInfo2 level %u failed - %s\n",
4061 r.in.level, nt_errstr(status));
4062 ret = false;
4063 continue;
4067 return true;
4070 /* Test whether querydispinfo level 5 and enumdomgroups return the same
4071 set of group names. */
4072 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
4073 struct policy_handle *handle)
4075 struct samr_EnumDomainGroups q1;
4076 struct samr_QueryDisplayInfo q2;
4077 NTSTATUS status;
4078 uint32_t resume_handle=0;
4079 int i;
4080 bool ret = true;
4081 uint32_t total_size;
4082 uint32_t returned_size;
4083 union samr_DispInfo info;
4085 int num_names = 0;
4086 const char **names = NULL;
4088 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
4090 q1.in.domain_handle = handle;
4091 q1.in.resume_handle = &resume_handle;
4092 q1.in.max_size = 5;
4093 q1.out.resume_handle = &resume_handle;
4095 status = STATUS_MORE_ENTRIES;
4096 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
4097 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
4099 if (!NT_STATUS_IS_OK(status) &&
4100 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
4101 break;
4103 for (i=0; i<q1.out.num_entries; i++) {
4104 add_string_to_array(tctx,
4105 q1.out.sam->entries[i].name.string,
4106 &names, &num_names);
4110 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
4112 torture_assert(tctx, q1.out.sam, "EnumDomainGroups failed to return q1.out.sam");
4114 q2.in.domain_handle = handle;
4115 q2.in.level = 5;
4116 q2.in.start_idx = 0;
4117 q2.in.max_entries = 5;
4118 q2.in.buf_size = (uint32_t)-1;
4119 q2.out.total_size = &total_size;
4120 q2.out.returned_size = &returned_size;
4121 q2.out.info = &info;
4123 status = STATUS_MORE_ENTRIES;
4124 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
4125 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
4127 if (!NT_STATUS_IS_OK(status) &&
4128 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
4129 break;
4131 for (i=0; i<q2.out.info->info5.count; i++) {
4132 int j;
4133 const char *name = q2.out.info->info5.entries[i].account_name.string;
4134 bool found = false;
4135 for (j=0; j<num_names; j++) {
4136 if (names[j] == NULL)
4137 continue;
4138 if (strequal(names[j], name)) {
4139 names[j] = NULL;
4140 found = true;
4141 break;
4145 if (!found) {
4146 printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
4147 name);
4148 ret = false;
4151 q2.in.start_idx += q2.out.info->info5.count;
4154 if (!NT_STATUS_IS_OK(status)) {
4155 printf("QueryDisplayInfo level 5 failed - %s\n",
4156 nt_errstr(status));
4157 ret = false;
4160 for (i=0; i<num_names; i++) {
4161 if (names[i] != NULL) {
4162 printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
4163 names[i]);
4164 ret = false;
4168 return ret;
4171 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
4172 struct policy_handle *group_handle)
4174 struct samr_DeleteDomainGroup d;
4175 NTSTATUS status;
4177 torture_comment(tctx, "Testing DeleteDomainGroup\n");
4179 d.in.group_handle = group_handle;
4180 d.out.group_handle = group_handle;
4182 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
4183 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
4185 return true;
4188 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
4189 struct policy_handle *domain_handle)
4191 struct samr_TestPrivateFunctionsDomain r;
4192 NTSTATUS status;
4193 bool ret = true;
4195 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
4197 r.in.domain_handle = domain_handle;
4199 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
4200 torture_assert_ntstatus_equal(tctx, NT_STATUS_NOT_IMPLEMENTED, status, "TestPrivateFunctionsDomain");
4202 return ret;
4205 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
4206 struct dom_sid *domain_sid,
4207 struct policy_handle *domain_handle)
4209 struct samr_RidToSid r;
4210 NTSTATUS status;
4211 bool ret = true;
4212 struct dom_sid *calc_sid, *out_sid;
4213 int rids[] = { 0, 42, 512, 10200 };
4214 int i;
4216 for (i=0;i<ARRAY_SIZE(rids);i++) {
4217 torture_comment(tctx, "Testing RidToSid\n");
4219 calc_sid = dom_sid_dup(tctx, domain_sid);
4220 r.in.domain_handle = domain_handle;
4221 r.in.rid = rids[i];
4222 r.out.sid = &out_sid;
4224 status = dcerpc_samr_RidToSid(p, tctx, &r);
4225 if (!NT_STATUS_IS_OK(status)) {
4226 printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
4227 ret = false;
4228 } else {
4229 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
4231 if (!dom_sid_equal(calc_sid, out_sid)) {
4232 printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
4233 dom_sid_string(tctx, out_sid),
4234 dom_sid_string(tctx, calc_sid));
4235 ret = false;
4240 return ret;
4243 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
4244 struct policy_handle *domain_handle)
4246 struct samr_GetBootKeyInformation r;
4247 NTSTATUS status;
4248 bool ret = true;
4249 uint32_t unknown = 0;
4251 torture_comment(tctx, "Testing GetBootKeyInformation\n");
4253 r.in.domain_handle = domain_handle;
4254 r.out.unknown = &unknown;
4256 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
4257 if (!NT_STATUS_IS_OK(status)) {
4258 /* w2k3 seems to fail this sometimes and pass it sometimes */
4259 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
4262 return ret;
4265 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
4266 struct policy_handle *domain_handle,
4267 struct policy_handle *group_handle)
4269 NTSTATUS status;
4270 struct samr_AddGroupMember r;
4271 struct samr_DeleteGroupMember d;
4272 struct samr_QueryGroupMember q;
4273 struct samr_RidTypeArray *rids = NULL;
4274 struct samr_SetMemberAttributesOfGroup s;
4275 uint32_t rid;
4277 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
4278 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
4280 r.in.group_handle = group_handle;
4281 r.in.rid = rid;
4282 r.in.flags = 0; /* ??? */
4284 torture_comment(tctx, "Testing AddGroupMember and DeleteGroupMember\n");
4286 d.in.group_handle = group_handle;
4287 d.in.rid = rid;
4289 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
4290 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
4292 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
4293 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
4295 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
4296 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
4298 if (torture_setting_bool(tctx, "samba4", false)) {
4299 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba4\n");
4300 } else {
4301 /* this one is quite strange. I am using random inputs in the
4302 hope of triggering an error that might give us a clue */
4304 s.in.group_handle = group_handle;
4305 s.in.unknown1 = random();
4306 s.in.unknown2 = random();
4308 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
4309 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
4312 q.in.group_handle = group_handle;
4313 q.out.rids = &rids;
4315 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
4316 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
4318 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
4319 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
4321 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
4322 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
4324 return true;
4328 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
4329 struct torture_context *tctx,
4330 struct policy_handle *domain_handle,
4331 struct policy_handle *group_handle,
4332 struct dom_sid *domain_sid)
4334 NTSTATUS status;
4335 struct samr_CreateDomainGroup r;
4336 uint32_t rid;
4337 struct lsa_String name;
4338 bool ret = true;
4340 init_lsa_String(&name, TEST_GROUPNAME);
4342 r.in.domain_handle = domain_handle;
4343 r.in.name = &name;
4344 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4345 r.out.group_handle = group_handle;
4346 r.out.rid = &rid;
4348 printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
4350 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
4352 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4353 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4354 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
4355 return true;
4356 } else {
4357 printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
4358 nt_errstr(status));
4359 return false;
4363 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
4364 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
4365 printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
4366 nt_errstr(status));
4367 return false;
4369 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
4371 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4372 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
4374 printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
4375 nt_errstr(status));
4376 return false;
4378 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
4380 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
4382 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
4383 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
4384 ret = false;
4387 if (!test_SetGroupInfo(p, tctx, group_handle)) {
4388 ret = false;
4391 return ret;
4396 its not totally clear what this does. It seems to accept any sid you like.
4398 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
4399 struct torture_context *tctx,
4400 struct policy_handle *domain_handle)
4402 NTSTATUS status;
4403 struct samr_RemoveMemberFromForeignDomain r;
4405 r.in.domain_handle = domain_handle;
4406 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
4408 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
4409 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
4411 return true;
4416 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
4417 struct policy_handle *handle);
4419 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
4420 struct policy_handle *handle, struct dom_sid *sid,
4421 enum torture_samr_choice which_ops)
4423 NTSTATUS status;
4424 struct samr_OpenDomain r;
4425 struct policy_handle domain_handle;
4426 struct policy_handle alias_handle;
4427 struct policy_handle user_handle;
4428 struct policy_handle group_handle;
4429 bool ret = true;
4431 ZERO_STRUCT(alias_handle);
4432 ZERO_STRUCT(user_handle);
4433 ZERO_STRUCT(group_handle);
4434 ZERO_STRUCT(domain_handle);
4436 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
4438 r.in.connect_handle = handle;
4439 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4440 r.in.sid = sid;
4441 r.out.domain_handle = &domain_handle;
4443 status = dcerpc_samr_OpenDomain(p, tctx, &r);
4444 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
4446 /* run the domain tests with the main handle closed - this tests
4447 the servers reference counting */
4448 ret &= test_samr_handle_Close(p, tctx, handle);
4450 switch (which_ops) {
4451 case TORTURE_SAMR_USER_ATTRIBUTES:
4452 case TORTURE_SAMR_PASSWORDS:
4453 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops);
4454 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops);
4455 /* This test needs 'complex' users to validate */
4456 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
4457 if (!ret) {
4458 printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
4460 break;
4461 case TORTURE_SAMR_OTHER:
4462 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops);
4463 if (!ret) {
4464 printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
4466 ret &= test_QuerySecurity(p, tctx, &domain_handle);
4467 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
4468 ret &= test_CreateAlias(p, tctx, &domain_handle, &alias_handle, sid);
4469 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle, sid);
4470 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
4471 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
4472 ret &= test_EnumDomainUsers(p, tctx, &domain_handle);
4473 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
4474 ret &= test_EnumDomainGroups(p, tctx, &domain_handle);
4475 ret &= test_EnumDomainAliases(p, tctx, &domain_handle);
4476 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
4477 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
4478 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
4480 if (torture_setting_bool(tctx, "samba4", false)) {
4481 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
4482 } else {
4483 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
4484 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
4486 ret &= test_GroupList(p, tctx, &domain_handle);
4487 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
4488 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
4489 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
4490 if (!ret) {
4491 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
4493 break;
4496 if (!policy_handle_empty(&user_handle) &&
4497 !test_DeleteUser(p, tctx, &user_handle)) {
4498 ret = false;
4501 if (!policy_handle_empty(&alias_handle) &&
4502 !test_DeleteAlias(p, tctx, &alias_handle)) {
4503 ret = false;
4506 if (!policy_handle_empty(&group_handle) &&
4507 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
4508 ret = false;
4511 ret &= test_samr_handle_Close(p, tctx, &domain_handle);
4513 /* reconnect the main handle */
4514 ret &= test_Connect(p, tctx, handle);
4516 if (!ret) {
4517 printf("Testing domain %s failed!\n", dom_sid_string(tctx, sid));
4520 return ret;
4523 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
4524 struct policy_handle *handle, const char *domain,
4525 enum torture_samr_choice which_ops)
4527 NTSTATUS status;
4528 struct samr_LookupDomain r;
4529 struct lsa_String n1;
4530 struct lsa_String n2;
4531 bool ret = true;
4533 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
4535 /* check for correct error codes */
4536 r.in.connect_handle = handle;
4537 r.in.domain_name = &n2;
4538 n2.string = NULL;
4540 status = dcerpc_samr_LookupDomain(p, tctx, &r);
4541 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
4543 init_lsa_String(&n2, "xxNODOMAINxx");
4545 status = dcerpc_samr_LookupDomain(p, tctx, &r);
4546 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
4548 r.in.connect_handle = handle;
4550 init_lsa_String(&n1, domain);
4551 r.in.domain_name = &n1;
4553 status = dcerpc_samr_LookupDomain(p, tctx, &r);
4554 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
4556 if (!test_GetDomPwInfo(p, tctx, &n1)) {
4557 ret = false;
4560 if (!test_OpenDomain(p, tctx, handle, r.out.sid, which_ops)) {
4561 ret = false;
4564 return ret;
4568 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
4569 struct policy_handle *handle, enum torture_samr_choice which_ops)
4571 NTSTATUS status;
4572 struct samr_EnumDomains r;
4573 uint32_t resume_handle = 0;
4574 int i;
4575 bool ret = true;
4577 r.in.connect_handle = handle;
4578 r.in.resume_handle = &resume_handle;
4579 r.in.buf_size = (uint32_t)-1;
4580 r.out.resume_handle = &resume_handle;
4582 status = dcerpc_samr_EnumDomains(p, tctx, &r);
4583 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
4585 if (!r.out.sam) {
4586 return false;
4589 for (i=0;i<r.out.sam->count;i++) {
4590 if (!test_LookupDomain(p, tctx, handle,
4591 r.out.sam->entries[i].name.string, which_ops)) {
4592 ret = false;
4596 status = dcerpc_samr_EnumDomains(p, tctx, &r);
4597 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
4599 return ret;
4603 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
4604 struct policy_handle *handle)
4606 NTSTATUS status;
4607 struct samr_Connect r;
4608 struct samr_Connect2 r2;
4609 struct samr_Connect3 r3;
4610 struct samr_Connect4 r4;
4611 struct samr_Connect5 r5;
4612 union samr_ConnectInfo info;
4613 struct policy_handle h;
4614 uint32_t level_out = 0;
4615 bool ret = true, got_handle = false;
4617 torture_comment(tctx, "testing samr_Connect\n");
4619 r.in.system_name = 0;
4620 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4621 r.out.connect_handle = &h;
4623 status = dcerpc_samr_Connect(p, tctx, &r);
4624 if (!NT_STATUS_IS_OK(status)) {
4625 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
4626 ret = false;
4627 } else {
4628 got_handle = true;
4629 *handle = h;
4632 torture_comment(tctx, "testing samr_Connect2\n");
4634 r2.in.system_name = NULL;
4635 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4636 r2.out.connect_handle = &h;
4638 status = dcerpc_samr_Connect2(p, tctx, &r2);
4639 if (!NT_STATUS_IS_OK(status)) {
4640 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
4641 ret = false;
4642 } else {
4643 if (got_handle) {
4644 test_samr_handle_Close(p, tctx, handle);
4646 got_handle = true;
4647 *handle = h;
4650 torture_comment(tctx, "testing samr_Connect3\n");
4652 r3.in.system_name = NULL;
4653 r3.in.unknown = 0;
4654 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4655 r3.out.connect_handle = &h;
4657 status = dcerpc_samr_Connect3(p, tctx, &r3);
4658 if (!NT_STATUS_IS_OK(status)) {
4659 printf("Connect3 failed - %s\n", nt_errstr(status));
4660 ret = false;
4661 } else {
4662 if (got_handle) {
4663 test_samr_handle_Close(p, tctx, handle);
4665 got_handle = true;
4666 *handle = h;
4669 torture_comment(tctx, "testing samr_Connect4\n");
4671 r4.in.system_name = "";
4672 r4.in.client_version = 0;
4673 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4674 r4.out.connect_handle = &h;
4676 status = dcerpc_samr_Connect4(p, tctx, &r4);
4677 if (!NT_STATUS_IS_OK(status)) {
4678 printf("Connect4 failed - %s\n", nt_errstr(status));
4679 ret = false;
4680 } else {
4681 if (got_handle) {
4682 test_samr_handle_Close(p, tctx, handle);
4684 got_handle = true;
4685 *handle = h;
4688 torture_comment(tctx, "testing samr_Connect5\n");
4690 info.info1.client_version = 0;
4691 info.info1.unknown2 = 0;
4693 r5.in.system_name = "";
4694 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4695 r5.in.level_in = 1;
4696 r5.out.level_out = &level_out;
4697 r5.in.info_in = &info;
4698 r5.out.info_out = &info;
4699 r5.out.connect_handle = &h;
4701 status = dcerpc_samr_Connect5(p, tctx, &r5);
4702 if (!NT_STATUS_IS_OK(status)) {
4703 printf("Connect5 failed - %s\n", nt_errstr(status));
4704 ret = false;
4705 } else {
4706 if (got_handle) {
4707 test_samr_handle_Close(p, tctx, handle);
4709 got_handle = true;
4710 *handle = h;
4713 return ret;
4717 bool torture_rpc_samr(struct torture_context *torture)
4719 NTSTATUS status;
4720 struct dcerpc_pipe *p;
4721 bool ret = true;
4722 struct policy_handle handle;
4724 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
4725 if (!NT_STATUS_IS_OK(status)) {
4726 return false;
4729 ret &= test_Connect(p, torture, &handle);
4731 ret &= test_QuerySecurity(p, torture, &handle);
4733 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER);
4735 ret &= test_SetDsrmPassword(p, torture, &handle);
4737 ret &= test_Shutdown(p, torture, &handle);
4739 ret &= test_samr_handle_Close(p, torture, &handle);
4741 return ret;
4745 bool torture_rpc_samr_users(struct torture_context *torture)
4747 NTSTATUS status;
4748 struct dcerpc_pipe *p;
4749 bool ret = true;
4750 struct policy_handle handle;
4752 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
4753 if (!NT_STATUS_IS_OK(status)) {
4754 return false;
4757 ret &= test_Connect(p, torture, &handle);
4759 ret &= test_QuerySecurity(p, torture, &handle);
4761 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES);
4763 ret &= test_SetDsrmPassword(p, torture, &handle);
4765 ret &= test_Shutdown(p, torture, &handle);
4767 ret &= test_samr_handle_Close(p, torture, &handle);
4769 return ret;
4773 bool torture_rpc_samr_passwords(struct torture_context *torture)
4775 NTSTATUS status;
4776 struct dcerpc_pipe *p;
4777 bool ret = true;
4778 struct policy_handle handle;
4780 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
4781 if (!NT_STATUS_IS_OK(status)) {
4782 return false;
4785 ret &= test_Connect(p, torture, &handle);
4787 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS);
4789 ret &= test_samr_handle_Close(p, torture, &handle);
4791 return ret;