s3/docs: Raise version number up to 3.5.
[Samba/gebeck_regimport.git] / source4 / torture / rpc / samr.c
blob8af986752882f856b77df89c33a2fbb87ee18380
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for samr rpc operations
5 Copyright (C) Andrew Tridgell 2003
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "system/time.h"
25 #include "librpc/gen_ndr/lsa.h"
26 #include "librpc/gen_ndr/ndr_netlogon.h"
27 #include "librpc/gen_ndr/ndr_netlogon_c.h"
28 #include "librpc/gen_ndr/ndr_samr_c.h"
29 #include "../lib/crypto/crypto.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/rpc.h"
33 #include "param/param.h"
35 #include <unistd.h>
37 #define TEST_ACCOUNT_NAME "samrtorturetest"
38 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
39 #define TEST_ALIASNAME "samrtorturetestalias"
40 #define TEST_GROUPNAME "samrtorturetestgroup"
41 #define TEST_MACHINENAME "samrtestmach$"
42 #define TEST_DOMAINNAME "samrtestdom$"
44 enum torture_samr_choice {
45 TORTURE_SAMR_PASSWORDS,
46 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
47 TORTURE_SAMR_USER_ATTRIBUTES,
48 TORTURE_SAMR_OTHER
51 static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
52 struct policy_handle *handle);
54 static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
55 struct policy_handle *handle);
57 static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
58 struct policy_handle *handle);
60 static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
61 const char *acct_name,
62 struct policy_handle *domain_handle, char **password);
64 static void init_lsa_String(struct lsa_String *string, const char *s)
66 string->string = s;
69 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
71 string->length = length;
72 string->size = length;
73 string->array = (uint16_t *)discard_const(s);
76 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
77 struct policy_handle *handle)
79 NTSTATUS status;
80 struct samr_Close r;
82 r.in.handle = handle;
83 r.out.handle = handle;
85 status = dcerpc_samr_Close(p, tctx, &r);
86 torture_assert_ntstatus_ok(tctx, status, "Close");
88 return true;
91 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
92 struct policy_handle *handle)
94 NTSTATUS status;
95 struct samr_Shutdown r;
97 if (!torture_setting_bool(tctx, "dangerous", false)) {
98 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
99 return true;
102 r.in.connect_handle = handle;
104 torture_comment(tctx, "testing samr_Shutdown\n");
106 status = dcerpc_samr_Shutdown(p, tctx, &r);
107 torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
109 return true;
112 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
113 struct policy_handle *handle)
115 NTSTATUS status;
116 struct samr_SetDsrmPassword r;
117 struct lsa_String string;
118 struct samr_Password hash;
120 if (!torture_setting_bool(tctx, "dangerous", false)) {
121 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
124 E_md4hash("TeSTDSRM123", hash.hash);
126 init_lsa_String(&string, "Administrator");
128 r.in.name = &string;
129 r.in.unknown = 0;
130 r.in.hash = &hash;
132 torture_comment(tctx, "testing samr_SetDsrmPassword\n");
134 status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
135 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
137 return true;
141 static bool test_QuerySecurity(struct dcerpc_pipe *p,
142 struct torture_context *tctx,
143 struct policy_handle *handle)
145 NTSTATUS status;
146 struct samr_QuerySecurity r;
147 struct samr_SetSecurity s;
148 struct sec_desc_buf *sdbuf = NULL;
150 r.in.handle = handle;
151 r.in.sec_info = 7;
152 r.out.sdbuf = &sdbuf;
154 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
155 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
157 torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
159 s.in.handle = handle;
160 s.in.sec_info = 7;
161 s.in.sdbuf = sdbuf;
163 if (torture_setting_bool(tctx, "samba4", false)) {
164 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
167 status = dcerpc_samr_SetSecurity(p, tctx, &s);
168 torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
170 status = dcerpc_samr_QuerySecurity(p, tctx, &r);
171 torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
173 return true;
177 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
178 struct policy_handle *handle, uint32_t base_acct_flags,
179 const char *base_account_name)
181 NTSTATUS status;
182 struct samr_SetUserInfo s;
183 struct samr_SetUserInfo2 s2;
184 struct samr_QueryUserInfo q;
185 struct samr_QueryUserInfo q0;
186 union samr_UserInfo u;
187 union samr_UserInfo *info;
188 bool ret = true;
189 const char *test_account_name;
191 uint32_t user_extra_flags = 0;
192 if (base_acct_flags == ACB_NORMAL) {
193 /* When created, accounts are expired by default */
194 user_extra_flags = ACB_PW_EXPIRED;
197 s.in.user_handle = handle;
198 s.in.info = &u;
200 s2.in.user_handle = handle;
201 s2.in.info = &u;
203 q.in.user_handle = handle;
204 q.out.info = &info;
205 q0 = q;
207 #define TESTCALL(call, r) \
208 status = dcerpc_samr_ ##call(p, tctx, &r); \
209 if (!NT_STATUS_IS_OK(status)) { \
210 torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
211 r.in.level, nt_errstr(status), __location__); \
212 ret = false; \
213 break; \
216 #define STRING_EQUAL(s1, s2, field) \
217 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
218 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
219 #field, s2, __location__); \
220 ret = false; \
221 break; \
224 #define MEM_EQUAL(s1, s2, length, field) \
225 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
226 torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
227 #field, (const char *)s2, __location__); \
228 ret = false; \
229 break; \
232 #define INT_EQUAL(i1, i2, field) \
233 if (i1 != i2) { \
234 torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
235 #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
236 ret = false; \
237 break; \
240 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
241 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
242 q.in.level = lvl1; \
243 TESTCALL(QueryUserInfo, q) \
244 s.in.level = lvl1; \
245 s2.in.level = lvl1; \
246 u = *info; \
247 if (lvl1 == 21) { \
248 ZERO_STRUCT(u.info21); \
249 u.info21.fields_present = fpval; \
251 init_lsa_String(&u.info ## lvl1.field1, value); \
252 TESTCALL(SetUserInfo, s) \
253 TESTCALL(SetUserInfo2, s2) \
254 init_lsa_String(&u.info ## lvl1.field1, ""); \
255 TESTCALL(QueryUserInfo, q); \
256 u = *info; \
257 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
258 q.in.level = lvl2; \
259 TESTCALL(QueryUserInfo, q) \
260 u = *info; \
261 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
262 } while (0)
264 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
265 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
266 q.in.level = lvl1; \
267 TESTCALL(QueryUserInfo, q) \
268 s.in.level = lvl1; \
269 s2.in.level = lvl1; \
270 u = *info; \
271 if (lvl1 == 21) { \
272 ZERO_STRUCT(u.info21); \
273 u.info21.fields_present = fpval; \
275 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
276 TESTCALL(SetUserInfo, s) \
277 TESTCALL(SetUserInfo2, s2) \
278 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
279 TESTCALL(QueryUserInfo, q); \
280 u = *info; \
281 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
282 q.in.level = lvl2; \
283 TESTCALL(QueryUserInfo, q) \
284 u = *info; \
285 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
286 } while (0)
288 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
289 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
290 q.in.level = lvl1; \
291 TESTCALL(QueryUserInfo, q) \
292 s.in.level = lvl1; \
293 s2.in.level = lvl1; \
294 u = *info; \
295 if (lvl1 == 21) { \
296 uint8_t *bits = u.info21.logon_hours.bits; \
297 ZERO_STRUCT(u.info21); \
298 if (fpval == SAMR_FIELD_LOGON_HOURS) { \
299 u.info21.logon_hours.units_per_week = 168; \
300 u.info21.logon_hours.bits = bits; \
302 u.info21.fields_present = fpval; \
304 u.info ## lvl1.field1 = value; \
305 TESTCALL(SetUserInfo, s) \
306 TESTCALL(SetUserInfo2, s2) \
307 u.info ## lvl1.field1 = 0; \
308 TESTCALL(QueryUserInfo, q); \
309 u = *info; \
310 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
311 q.in.level = lvl2; \
312 TESTCALL(QueryUserInfo, q) \
313 u = *info; \
314 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
315 } while (0)
317 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
318 TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
319 } while (0)
321 q0.in.level = 12;
322 do { TESTCALL(QueryUserInfo, q0) } while (0);
324 TEST_USERINFO_STRING(2, comment, 1, comment, "xx2-1 comment", 0);
325 TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
326 TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
327 SAMR_FIELD_COMMENT);
329 test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
330 TEST_USERINFO_STRING(7, account_name, 1, account_name, base_account_name, 0);
331 test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
332 TEST_USERINFO_STRING(7, account_name, 3, account_name, base_account_name, 0);
333 test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
334 TEST_USERINFO_STRING(7, account_name, 5, account_name, base_account_name, 0);
335 test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
336 TEST_USERINFO_STRING(7, account_name, 6, account_name, base_account_name, 0);
337 test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
338 TEST_USERINFO_STRING(7, account_name, 7, account_name, base_account_name, 0);
339 test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
340 TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
341 test_account_name = base_account_name;
342 TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
343 SAMR_FIELD_ACCOUNT_NAME);
345 TEST_USERINFO_STRING(6, full_name, 1, full_name, "xx6-1 full_name", 0);
346 TEST_USERINFO_STRING(6, full_name, 3, full_name, "xx6-3 full_name", 0);
347 TEST_USERINFO_STRING(6, full_name, 5, full_name, "xx6-5 full_name", 0);
348 TEST_USERINFO_STRING(6, full_name, 6, full_name, "xx6-6 full_name", 0);
349 TEST_USERINFO_STRING(6, full_name, 8, full_name, "xx6-8 full_name", 0);
350 TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
351 TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
352 TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
353 SAMR_FIELD_FULL_NAME);
355 TEST_USERINFO_STRING(6, full_name, 1, full_name, "", 0);
356 TEST_USERINFO_STRING(6, full_name, 3, full_name, "", 0);
357 TEST_USERINFO_STRING(6, full_name, 5, full_name, "", 0);
358 TEST_USERINFO_STRING(6, full_name, 6, full_name, "", 0);
359 TEST_USERINFO_STRING(6, full_name, 8, full_name, "", 0);
360 TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
361 TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
362 TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
363 SAMR_FIELD_FULL_NAME);
365 TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
366 TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
367 TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
368 TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
369 SAMR_FIELD_LOGON_SCRIPT);
371 TEST_USERINFO_STRING(12, profile_path, 3, profile_path, "xx12-3 profile_path", 0);
372 TEST_USERINFO_STRING(12, profile_path, 5, profile_path, "xx12-5 profile_path", 0);
373 TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
374 TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
375 SAMR_FIELD_PROFILE_PATH);
377 TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
378 TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
379 TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
380 TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
381 SAMR_FIELD_HOME_DIRECTORY);
382 TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
383 SAMR_FIELD_HOME_DIRECTORY);
385 TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
386 TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
387 TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
388 TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
389 SAMR_FIELD_HOME_DRIVE);
390 TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
391 SAMR_FIELD_HOME_DRIVE);
393 TEST_USERINFO_STRING(13, description, 1, description, "xx13-1 description", 0);
394 TEST_USERINFO_STRING(13, description, 5, description, "xx13-5 description", 0);
395 TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
396 TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
397 SAMR_FIELD_DESCRIPTION);
399 TEST_USERINFO_STRING(14, workstations, 3, workstations, "14workstation3", 0);
400 TEST_USERINFO_STRING(14, workstations, 5, workstations, "14workstation4", 0);
401 TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
402 TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
403 SAMR_FIELD_WORKSTATIONS);
404 TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
405 SAMR_FIELD_WORKSTATIONS);
406 TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
407 SAMR_FIELD_WORKSTATIONS);
408 TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
409 SAMR_FIELD_WORKSTATIONS);
411 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
412 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
413 SAMR_FIELD_PARAMETERS);
414 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
415 SAMR_FIELD_PARAMETERS);
416 /* also empty user parameters are allowed */
417 TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
418 TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
419 SAMR_FIELD_PARAMETERS);
420 TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
421 SAMR_FIELD_PARAMETERS);
423 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
424 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
425 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
426 SAMR_FIELD_COUNTRY_CODE);
427 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
428 SAMR_FIELD_COUNTRY_CODE);
430 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
431 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
432 SAMR_FIELD_CODE_PAGE);
433 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
434 SAMR_FIELD_CODE_PAGE);
436 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
437 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
438 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
439 SAMR_FIELD_ACCT_EXPIRY);
440 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
441 SAMR_FIELD_ACCT_EXPIRY);
442 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
443 SAMR_FIELD_ACCT_EXPIRY);
445 TEST_USERINFO_INT(4, logon_hours.bits[3], 3, logon_hours.bits[3], 1, 0);
446 TEST_USERINFO_INT(4, logon_hours.bits[3], 5, logon_hours.bits[3], 2, 0);
447 TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
448 TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
449 SAMR_FIELD_LOGON_HOURS);
451 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
452 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
453 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
455 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
456 (base_acct_flags | ACB_DISABLED),
457 (base_acct_flags | ACB_DISABLED | user_extra_flags),
460 /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
461 TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
462 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
463 (base_acct_flags | ACB_DISABLED | ACB_PWNOEXP),
465 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
466 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
467 (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
471 /* The 'autolock' flag doesn't stick - check this */
472 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
473 (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
474 (base_acct_flags | ACB_DISABLED | user_extra_flags),
476 #if 0
477 /* Removing the 'disabled' flag doesn't stick - check this */
478 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
479 (base_acct_flags),
480 (base_acct_flags | ACB_DISABLED | user_extra_flags),
482 #endif
483 /* The 'store plaintext' flag does stick */
484 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
485 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
486 (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
488 /* The 'use DES' flag does stick */
489 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
490 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
491 (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
493 /* The 'don't require kerberos pre-authentication flag does stick */
494 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
495 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
496 (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
498 /* The 'no kerberos PAC required' flag sticks */
499 TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
500 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
501 (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
504 TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
505 (base_acct_flags | ACB_DISABLED),
506 (base_acct_flags | ACB_DISABLED | user_extra_flags),
507 SAMR_FIELD_ACCT_FLAGS);
509 #if 0
510 /* these fail with win2003 - it appears you can't set the primary gid?
511 the set succeeds, but the gid isn't changed. Very weird! */
512 TEST_USERINFO_INT(9, primary_gid, 1, primary_gid, 513);
513 TEST_USERINFO_INT(9, primary_gid, 3, primary_gid, 513);
514 TEST_USERINFO_INT(9, primary_gid, 5, primary_gid, 513);
515 TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
516 #endif
518 return ret;
522 generate a random password for password change tests
524 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
526 size_t len = MAX(8, min_len) + (random() % 6);
527 char *s = generate_random_str(mem_ctx, len);
528 return s;
531 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
533 char *s = samr_rand_pass_silent(mem_ctx, min_len);
534 printf("Generated password '%s'\n", s);
535 return s;
540 generate a random password for password change tests
542 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
544 int i;
545 DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
546 generate_random_buffer(password.data, password.length);
548 for (i=0; i < len; i++) {
549 if (((uint16_t *)password.data)[i] == 0) {
550 ((uint16_t *)password.data)[i] = 1;
554 return password;
558 generate a random password for password change tests (fixed length)
560 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
562 char *s = generate_random_str(mem_ctx, len);
563 printf("Generated password '%s'\n", s);
564 return s;
567 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
568 struct policy_handle *handle, char **password)
570 NTSTATUS status;
571 struct samr_SetUserInfo s;
572 union samr_UserInfo u;
573 bool ret = true;
574 DATA_BLOB session_key;
575 char *newpass;
576 struct samr_GetUserPwInfo pwp;
577 struct samr_PwInfo info;
578 int policy_min_pw_len = 0;
579 pwp.in.user_handle = handle;
580 pwp.out.info = &info;
582 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
583 if (NT_STATUS_IS_OK(status)) {
584 policy_min_pw_len = pwp.out.info->min_password_length;
586 newpass = samr_rand_pass(tctx, policy_min_pw_len);
588 s.in.user_handle = handle;
589 s.in.info = &u;
590 s.in.level = 24;
592 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
593 u.info24.password_expired = 0;
595 status = dcerpc_fetch_session_key(p, &session_key);
596 if (!NT_STATUS_IS_OK(status)) {
597 printf("SetUserInfo level %u - no session key - %s\n",
598 s.in.level, nt_errstr(status));
599 return false;
602 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
604 torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
606 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
607 if (!NT_STATUS_IS_OK(status)) {
608 printf("SetUserInfo level %u failed - %s\n",
609 s.in.level, nt_errstr(status));
610 ret = false;
611 } else {
612 *password = newpass;
615 return ret;
619 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
620 struct policy_handle *handle, uint32_t fields_present,
621 char **password)
623 NTSTATUS status;
624 struct samr_SetUserInfo s;
625 union samr_UserInfo u;
626 bool ret = true;
627 DATA_BLOB session_key;
628 char *newpass;
629 struct samr_GetUserPwInfo pwp;
630 struct samr_PwInfo info;
631 int policy_min_pw_len = 0;
632 pwp.in.user_handle = handle;
633 pwp.out.info = &info;
635 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
636 if (NT_STATUS_IS_OK(status)) {
637 policy_min_pw_len = pwp.out.info->min_password_length;
639 newpass = samr_rand_pass(tctx, policy_min_pw_len);
641 s.in.user_handle = handle;
642 s.in.info = &u;
643 s.in.level = 23;
645 ZERO_STRUCT(u);
647 u.info23.info.fields_present = fields_present;
649 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
651 status = dcerpc_fetch_session_key(p, &session_key);
652 if (!NT_STATUS_IS_OK(status)) {
653 printf("SetUserInfo level %u - no session key - %s\n",
654 s.in.level, nt_errstr(status));
655 return false;
658 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
660 torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
662 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
663 if (!NT_STATUS_IS_OK(status)) {
664 printf("SetUserInfo level %u failed - %s\n",
665 s.in.level, nt_errstr(status));
666 ret = false;
667 } else {
668 *password = newpass;
671 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
673 status = dcerpc_fetch_session_key(p, &session_key);
674 if (!NT_STATUS_IS_OK(status)) {
675 printf("SetUserInfo level %u - no session key - %s\n",
676 s.in.level, nt_errstr(status));
677 return false;
680 /* This should break the key nicely */
681 session_key.length--;
682 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
684 torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
686 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
687 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
688 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
689 s.in.level, nt_errstr(status));
690 ret = false;
693 return ret;
697 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
698 struct policy_handle *handle, bool makeshort,
699 char **password)
701 NTSTATUS status;
702 struct samr_SetUserInfo s;
703 union samr_UserInfo u;
704 bool ret = true;
705 DATA_BLOB session_key;
706 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
707 uint8_t confounder[16];
708 char *newpass;
709 struct MD5Context ctx;
710 struct samr_GetUserPwInfo pwp;
711 struct samr_PwInfo info;
712 int policy_min_pw_len = 0;
713 pwp.in.user_handle = handle;
714 pwp.out.info = &info;
716 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
717 if (NT_STATUS_IS_OK(status)) {
718 policy_min_pw_len = pwp.out.info->min_password_length;
720 if (makeshort && policy_min_pw_len) {
721 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
722 } else {
723 newpass = samr_rand_pass(tctx, policy_min_pw_len);
726 s.in.user_handle = handle;
727 s.in.info = &u;
728 s.in.level = 26;
730 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
731 u.info26.password_expired = 0;
733 status = dcerpc_fetch_session_key(p, &session_key);
734 if (!NT_STATUS_IS_OK(status)) {
735 printf("SetUserInfo level %u - no session key - %s\n",
736 s.in.level, nt_errstr(status));
737 return false;
740 generate_random_buffer((uint8_t *)confounder, 16);
742 MD5Init(&ctx);
743 MD5Update(&ctx, confounder, 16);
744 MD5Update(&ctx, session_key.data, session_key.length);
745 MD5Final(confounded_session_key.data, &ctx);
747 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
748 memcpy(&u.info26.password.data[516], confounder, 16);
750 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
752 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
753 if (!NT_STATUS_IS_OK(status)) {
754 printf("SetUserInfo level %u failed - %s\n",
755 s.in.level, nt_errstr(status));
756 ret = false;
757 } else {
758 *password = newpass;
761 /* This should break the key nicely */
762 confounded_session_key.data[0]++;
764 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
765 memcpy(&u.info26.password.data[516], confounder, 16);
767 torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
769 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
770 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
771 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
772 s.in.level, nt_errstr(status));
773 ret = false;
774 } else {
775 *password = newpass;
778 return ret;
781 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
782 struct policy_handle *handle, uint32_t fields_present,
783 char **password)
785 NTSTATUS status;
786 struct samr_SetUserInfo s;
787 union samr_UserInfo u;
788 bool ret = true;
789 DATA_BLOB session_key;
790 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
791 struct MD5Context ctx;
792 uint8_t confounder[16];
793 char *newpass;
794 struct samr_GetUserPwInfo pwp;
795 struct samr_PwInfo info;
796 int policy_min_pw_len = 0;
797 pwp.in.user_handle = handle;
798 pwp.out.info = &info;
800 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
801 if (NT_STATUS_IS_OK(status)) {
802 policy_min_pw_len = pwp.out.info->min_password_length;
804 newpass = samr_rand_pass(tctx, policy_min_pw_len);
806 s.in.user_handle = handle;
807 s.in.info = &u;
808 s.in.level = 25;
810 ZERO_STRUCT(u);
812 u.info25.info.fields_present = fields_present;
814 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
816 status = dcerpc_fetch_session_key(p, &session_key);
817 if (!NT_STATUS_IS_OK(status)) {
818 printf("SetUserInfo level %u - no session key - %s\n",
819 s.in.level, nt_errstr(status));
820 return false;
823 generate_random_buffer((uint8_t *)confounder, 16);
825 MD5Init(&ctx);
826 MD5Update(&ctx, confounder, 16);
827 MD5Update(&ctx, session_key.data, session_key.length);
828 MD5Final(confounded_session_key.data, &ctx);
830 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
831 memcpy(&u.info25.password.data[516], confounder, 16);
833 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
835 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
836 if (!NT_STATUS_IS_OK(status)) {
837 printf("SetUserInfo level %u failed - %s\n",
838 s.in.level, nt_errstr(status));
839 ret = false;
840 } else {
841 *password = newpass;
844 /* This should break the key nicely */
845 confounded_session_key.data[0]++;
847 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
848 memcpy(&u.info25.password.data[516], confounder, 16);
850 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
852 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
853 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
854 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
855 s.in.level, nt_errstr(status));
856 ret = false;
859 return ret;
862 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
863 struct policy_handle *handle, char **password)
865 NTSTATUS status;
866 struct samr_SetUserInfo s;
867 union samr_UserInfo u;
868 bool ret = true;
869 DATA_BLOB session_key;
870 char *newpass;
871 struct samr_GetUserPwInfo pwp;
872 struct samr_PwInfo info;
873 int policy_min_pw_len = 0;
874 uint8_t lm_hash[16], nt_hash[16];
876 pwp.in.user_handle = handle;
877 pwp.out.info = &info;
879 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
880 if (NT_STATUS_IS_OK(status)) {
881 policy_min_pw_len = pwp.out.info->min_password_length;
883 newpass = samr_rand_pass(tctx, policy_min_pw_len);
885 s.in.user_handle = handle;
886 s.in.info = &u;
887 s.in.level = 18;
889 ZERO_STRUCT(u);
891 u.info18.nt_pwd_active = true;
892 u.info18.lm_pwd_active = true;
894 E_md4hash(newpass, nt_hash);
895 E_deshash(newpass, lm_hash);
897 status = dcerpc_fetch_session_key(p, &session_key);
898 if (!NT_STATUS_IS_OK(status)) {
899 printf("SetUserInfo level %u - no session key - %s\n",
900 s.in.level, nt_errstr(status));
901 return false;
905 DATA_BLOB in,out;
906 in = data_blob_const(nt_hash, 16);
907 out = data_blob_talloc_zero(tctx, 16);
908 sess_crypt_blob(&out, &in, &session_key, true);
909 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
912 DATA_BLOB in,out;
913 in = data_blob_const(lm_hash, 16);
914 out = data_blob_talloc_zero(tctx, 16);
915 sess_crypt_blob(&out, &in, &session_key, true);
916 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
919 torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
921 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
922 if (!NT_STATUS_IS_OK(status)) {
923 printf("SetUserInfo level %u failed - %s\n",
924 s.in.level, nt_errstr(status));
925 ret = false;
926 } else {
927 *password = newpass;
930 return ret;
933 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
934 struct policy_handle *handle, uint32_t fields_present,
935 char **password)
937 NTSTATUS status;
938 struct samr_SetUserInfo s;
939 union samr_UserInfo u;
940 bool ret = true;
941 DATA_BLOB session_key;
942 char *newpass;
943 struct samr_GetUserPwInfo pwp;
944 struct samr_PwInfo info;
945 int policy_min_pw_len = 0;
946 uint8_t lm_hash[16], nt_hash[16];
948 pwp.in.user_handle = handle;
949 pwp.out.info = &info;
951 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
952 if (NT_STATUS_IS_OK(status)) {
953 policy_min_pw_len = pwp.out.info->min_password_length;
955 newpass = samr_rand_pass(tctx, policy_min_pw_len);
957 s.in.user_handle = handle;
958 s.in.info = &u;
959 s.in.level = 21;
961 E_md4hash(newpass, nt_hash);
962 E_deshash(newpass, lm_hash);
964 ZERO_STRUCT(u);
966 u.info21.fields_present = fields_present;
968 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
969 u.info21.lm_owf_password.length = 16;
970 u.info21.lm_owf_password.size = 16;
971 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
972 u.info21.lm_password_set = true;
975 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
976 u.info21.nt_owf_password.length = 16;
977 u.info21.nt_owf_password.size = 16;
978 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
979 u.info21.nt_password_set = true;
982 status = dcerpc_fetch_session_key(p, &session_key);
983 if (!NT_STATUS_IS_OK(status)) {
984 printf("SetUserInfo level %u - no session key - %s\n",
985 s.in.level, nt_errstr(status));
986 return false;
989 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
990 DATA_BLOB in,out;
991 in = data_blob_const(u.info21.lm_owf_password.array,
992 u.info21.lm_owf_password.length);
993 out = data_blob_talloc_zero(tctx, 16);
994 sess_crypt_blob(&out, &in, &session_key, true);
995 u.info21.lm_owf_password.array = (uint16_t *)out.data;
998 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
999 DATA_BLOB in,out;
1000 in = data_blob_const(u.info21.nt_owf_password.array,
1001 u.info21.nt_owf_password.length);
1002 out = data_blob_talloc_zero(tctx, 16);
1003 sess_crypt_blob(&out, &in, &session_key, true);
1004 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1007 torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1009 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1010 if (!NT_STATUS_IS_OK(status)) {
1011 printf("SetUserInfo level %u failed - %s\n",
1012 s.in.level, nt_errstr(status));
1013 ret = false;
1014 } else {
1015 *password = newpass;
1018 /* try invalid length */
1019 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1021 u.info21.nt_owf_password.length++;
1023 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1025 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1026 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1027 s.in.level, nt_errstr(status));
1028 ret = false;
1032 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1034 u.info21.lm_owf_password.length++;
1036 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1038 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1039 printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1040 s.in.level, nt_errstr(status));
1041 ret = false;
1045 return ret;
1048 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1049 struct torture_context *tctx,
1050 struct policy_handle *handle,
1051 uint16_t level,
1052 uint32_t fields_present,
1053 char **password, uint8_t password_expired,
1054 bool use_setinfo2,
1055 bool *matched_expected_error)
1057 NTSTATUS status;
1058 NTSTATUS expected_error = NT_STATUS_OK;
1059 struct samr_SetUserInfo s;
1060 struct samr_SetUserInfo2 s2;
1061 union samr_UserInfo u;
1062 bool ret = true;
1063 DATA_BLOB session_key;
1064 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1065 struct MD5Context ctx;
1066 uint8_t confounder[16];
1067 char *newpass;
1068 struct samr_GetUserPwInfo pwp;
1069 struct samr_PwInfo info;
1070 int policy_min_pw_len = 0;
1071 const char *comment = NULL;
1072 uint8_t lm_hash[16], nt_hash[16];
1074 pwp.in.user_handle = handle;
1075 pwp.out.info = &info;
1077 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1078 if (NT_STATUS_IS_OK(status)) {
1079 policy_min_pw_len = pwp.out.info->min_password_length;
1081 newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1083 if (use_setinfo2) {
1084 s2.in.user_handle = handle;
1085 s2.in.info = &u;
1086 s2.in.level = level;
1087 } else {
1088 s.in.user_handle = handle;
1089 s.in.info = &u;
1090 s.in.level = level;
1093 if (fields_present & SAMR_FIELD_COMMENT) {
1094 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1097 ZERO_STRUCT(u);
1099 switch (level) {
1100 case 18:
1101 E_md4hash(newpass, nt_hash);
1102 E_deshash(newpass, lm_hash);
1104 u.info18.nt_pwd_active = true;
1105 u.info18.lm_pwd_active = true;
1106 u.info18.password_expired = password_expired;
1108 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1109 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1111 break;
1112 case 21:
1113 E_md4hash(newpass, nt_hash);
1114 E_deshash(newpass, lm_hash);
1116 u.info21.fields_present = fields_present;
1117 u.info21.password_expired = password_expired;
1118 u.info21.comment.string = comment;
1120 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1121 u.info21.lm_owf_password.length = 16;
1122 u.info21.lm_owf_password.size = 16;
1123 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1124 u.info21.lm_password_set = true;
1127 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1128 u.info21.nt_owf_password.length = 16;
1129 u.info21.nt_owf_password.size = 16;
1130 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1131 u.info21.nt_password_set = true;
1134 break;
1135 case 23:
1136 u.info23.info.fields_present = fields_present;
1137 u.info23.info.password_expired = password_expired;
1138 u.info23.info.comment.string = comment;
1140 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1142 break;
1143 case 24:
1144 u.info24.password_expired = password_expired;
1146 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1148 break;
1149 case 25:
1150 u.info25.info.fields_present = fields_present;
1151 u.info25.info.password_expired = password_expired;
1152 u.info25.info.comment.string = comment;
1154 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1156 break;
1157 case 26:
1158 u.info26.password_expired = password_expired;
1160 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1162 break;
1165 status = dcerpc_fetch_session_key(p, &session_key);
1166 if (!NT_STATUS_IS_OK(status)) {
1167 printf("SetUserInfo level %u - no session key - %s\n",
1168 s.in.level, nt_errstr(status));
1169 return false;
1172 generate_random_buffer((uint8_t *)confounder, 16);
1174 MD5Init(&ctx);
1175 MD5Update(&ctx, confounder, 16);
1176 MD5Update(&ctx, session_key.data, session_key.length);
1177 MD5Final(confounded_session_key.data, &ctx);
1179 switch (level) {
1180 case 18:
1182 DATA_BLOB in,out;
1183 in = data_blob_const(u.info18.nt_pwd.hash, 16);
1184 out = data_blob_talloc_zero(tctx, 16);
1185 sess_crypt_blob(&out, &in, &session_key, true);
1186 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1189 DATA_BLOB in,out;
1190 in = data_blob_const(u.info18.lm_pwd.hash, 16);
1191 out = data_blob_talloc_zero(tctx, 16);
1192 sess_crypt_blob(&out, &in, &session_key, true);
1193 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1196 break;
1197 case 21:
1198 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1199 DATA_BLOB in,out;
1200 in = data_blob_const(u.info21.lm_owf_password.array,
1201 u.info21.lm_owf_password.length);
1202 out = data_blob_talloc_zero(tctx, 16);
1203 sess_crypt_blob(&out, &in, &session_key, true);
1204 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1206 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1207 DATA_BLOB in,out;
1208 in = data_blob_const(u.info21.nt_owf_password.array,
1209 u.info21.nt_owf_password.length);
1210 out = data_blob_talloc_zero(tctx, 16);
1211 sess_crypt_blob(&out, &in, &session_key, true);
1212 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1214 break;
1215 case 23:
1216 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1217 break;
1218 case 24:
1219 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1220 break;
1221 case 25:
1222 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1223 memcpy(&u.info25.password.data[516], confounder, 16);
1224 break;
1225 case 26:
1226 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1227 memcpy(&u.info26.password.data[516], confounder, 16);
1228 break;
1231 if (use_setinfo2) {
1232 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1233 } else {
1234 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1237 if (!NT_STATUS_IS_OK(status)) {
1238 if (fields_present == 0) {
1239 expected_error = NT_STATUS_INVALID_PARAMETER;
1241 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1242 expected_error = NT_STATUS_ACCESS_DENIED;
1246 if (!NT_STATUS_IS_OK(expected_error)) {
1247 if (use_setinfo2) {
1248 torture_assert_ntstatus_equal(tctx,
1249 s2.out.result,
1250 expected_error, "SetUserInfo2 failed");
1251 } else {
1252 torture_assert_ntstatus_equal(tctx,
1253 s.out.result,
1254 expected_error, "SetUserInfo failed");
1256 *matched_expected_error = true;
1257 return true;
1260 if (!NT_STATUS_IS_OK(status)) {
1261 printf("SetUserInfo%s level %u failed - %s\n",
1262 use_setinfo2 ? "2":"", level, nt_errstr(status));
1263 ret = false;
1264 } else {
1265 *password = newpass;
1268 return ret;
1271 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1272 struct policy_handle *handle)
1274 NTSTATUS status;
1275 struct samr_SetAliasInfo r;
1276 struct samr_QueryAliasInfo q;
1277 union samr_AliasInfo *info;
1278 uint16_t levels[] = {2, 3};
1279 int i;
1280 bool ret = true;
1282 /* Ignoring switch level 1, as that includes the number of members for the alias
1283 * and setting this to a wrong value might have negative consequences
1286 for (i=0;i<ARRAY_SIZE(levels);i++) {
1287 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1289 r.in.alias_handle = handle;
1290 r.in.level = levels[i];
1291 r.in.info = talloc(tctx, union samr_AliasInfo);
1292 switch (r.in.level) {
1293 case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1294 case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1295 "Test Description, should test I18N as well"); break;
1296 case ALIASINFOALL: printf("ALIASINFOALL ignored\n"); break;
1299 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 printf("SetAliasInfo level %u failed - %s\n",
1302 levels[i], nt_errstr(status));
1303 ret = false;
1306 q.in.alias_handle = handle;
1307 q.in.level = levels[i];
1308 q.out.info = &info;
1310 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1311 if (!NT_STATUS_IS_OK(status)) {
1312 printf("QueryAliasInfo level %u failed - %s\n",
1313 levels[i], nt_errstr(status));
1314 ret = false;
1318 return ret;
1321 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1322 struct policy_handle *user_handle)
1324 struct samr_GetGroupsForUser r;
1325 struct samr_RidWithAttributeArray *rids = NULL;
1326 NTSTATUS status;
1328 torture_comment(tctx, "testing GetGroupsForUser\n");
1330 r.in.user_handle = user_handle;
1331 r.out.rids = &rids;
1333 status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1334 torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1336 return true;
1340 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1341 struct lsa_String *domain_name)
1343 NTSTATUS status;
1344 struct samr_GetDomPwInfo r;
1345 struct samr_PwInfo info;
1347 r.in.domain_name = domain_name;
1348 r.out.info = &info;
1350 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1352 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1353 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1355 r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1356 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1358 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1359 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1361 r.in.domain_name->string = "\\\\__NONAME__";
1362 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1364 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1365 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1367 r.in.domain_name->string = "\\\\Builtin";
1368 torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1370 status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1371 torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1373 return true;
1376 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1377 struct policy_handle *handle)
1379 NTSTATUS status;
1380 struct samr_GetUserPwInfo r;
1381 struct samr_PwInfo info;
1383 torture_comment(tctx, "Testing GetUserPwInfo\n");
1385 r.in.user_handle = handle;
1386 r.out.info = &info;
1388 status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1389 torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1391 return true;
1394 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1395 struct policy_handle *domain_handle, const char *name,
1396 uint32_t *rid)
1398 NTSTATUS status;
1399 struct samr_LookupNames n;
1400 struct lsa_String sname[2];
1401 struct samr_Ids rids, types;
1403 init_lsa_String(&sname[0], name);
1405 n.in.domain_handle = domain_handle;
1406 n.in.num_names = 1;
1407 n.in.names = sname;
1408 n.out.rids = &rids;
1409 n.out.types = &types;
1410 status = dcerpc_samr_LookupNames(p, tctx, &n);
1411 if (NT_STATUS_IS_OK(status)) {
1412 *rid = n.out.rids->ids[0];
1413 } else {
1414 return status;
1417 init_lsa_String(&sname[1], "xxNONAMExx");
1418 n.in.num_names = 2;
1419 status = dcerpc_samr_LookupNames(p, tctx, &n);
1420 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1421 printf("LookupNames[2] failed - %s\n", nt_errstr(status));
1422 if (NT_STATUS_IS_OK(status)) {
1423 return NT_STATUS_UNSUCCESSFUL;
1425 return status;
1428 n.in.num_names = 0;
1429 status = dcerpc_samr_LookupNames(p, tctx, &n);
1430 if (!NT_STATUS_IS_OK(status)) {
1431 printf("LookupNames[0] failed - %s\n", nt_errstr(status));
1432 return status;
1435 init_lsa_String(&sname[0], "xxNONAMExx");
1436 n.in.num_names = 1;
1437 status = dcerpc_samr_LookupNames(p, tctx, &n);
1438 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1439 printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));
1440 if (NT_STATUS_IS_OK(status)) {
1441 return NT_STATUS_UNSUCCESSFUL;
1443 return status;
1446 init_lsa_String(&sname[0], "xxNONAMExx");
1447 init_lsa_String(&sname[1], "xxNONAME2xx");
1448 n.in.num_names = 2;
1449 status = dcerpc_samr_LookupNames(p, tctx, &n);
1450 if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1451 printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));
1452 if (NT_STATUS_IS_OK(status)) {
1453 return NT_STATUS_UNSUCCESSFUL;
1455 return status;
1458 return NT_STATUS_OK;
1461 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1462 struct policy_handle *domain_handle,
1463 const char *name, struct policy_handle *user_handle)
1465 NTSTATUS status;
1466 struct samr_OpenUser r;
1467 uint32_t rid;
1469 status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
1470 if (!NT_STATUS_IS_OK(status)) {
1471 return status;
1474 r.in.domain_handle = domain_handle;
1475 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1476 r.in.rid = rid;
1477 r.out.user_handle = user_handle;
1478 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
1479 if (!NT_STATUS_IS_OK(status)) {
1480 printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1483 return status;
1486 #if 0
1487 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1488 struct policy_handle *handle)
1490 NTSTATUS status;
1491 struct samr_ChangePasswordUser r;
1492 bool ret = true;
1493 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1494 struct policy_handle user_handle;
1495 char *oldpass = "test";
1496 char *newpass = "test2";
1497 uint8_t old_nt_hash[16], new_nt_hash[16];
1498 uint8_t old_lm_hash[16], new_lm_hash[16];
1500 status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 return false;
1505 printf("Testing ChangePasswordUser for user 'testuser'\n");
1507 printf("old password: %s\n", oldpass);
1508 printf("new password: %s\n", newpass);
1510 E_md4hash(oldpass, old_nt_hash);
1511 E_md4hash(newpass, new_nt_hash);
1512 E_deshash(oldpass, old_lm_hash);
1513 E_deshash(newpass, new_lm_hash);
1515 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1516 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1517 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1518 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1519 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1520 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1522 r.in.handle = &user_handle;
1523 r.in.lm_present = 1;
1524 r.in.old_lm_crypted = &hash1;
1525 r.in.new_lm_crypted = &hash2;
1526 r.in.nt_present = 1;
1527 r.in.old_nt_crypted = &hash3;
1528 r.in.new_nt_crypted = &hash4;
1529 r.in.cross1_present = 1;
1530 r.in.nt_cross = &hash5;
1531 r.in.cross2_present = 1;
1532 r.in.lm_cross = &hash6;
1534 status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1535 if (!NT_STATUS_IS_OK(status)) {
1536 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1537 ret = false;
1540 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
1541 ret = false;
1544 return ret;
1546 #endif
1548 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1549 const char *acct_name,
1550 struct policy_handle *handle, char **password)
1552 NTSTATUS status;
1553 struct samr_ChangePasswordUser r;
1554 bool ret = true;
1555 struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1556 struct policy_handle user_handle;
1557 char *oldpass;
1558 uint8_t old_nt_hash[16], new_nt_hash[16];
1559 uint8_t old_lm_hash[16], new_lm_hash[16];
1560 bool changed = true;
1562 char *newpass;
1563 struct samr_GetUserPwInfo pwp;
1564 struct samr_PwInfo info;
1565 int policy_min_pw_len = 0;
1567 status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1568 if (!NT_STATUS_IS_OK(status)) {
1569 return false;
1571 pwp.in.user_handle = &user_handle;
1572 pwp.out.info = &info;
1574 status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1575 if (NT_STATUS_IS_OK(status)) {
1576 policy_min_pw_len = pwp.out.info->min_password_length;
1578 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1580 torture_comment(tctx, "Testing ChangePasswordUser\n");
1582 torture_assert(tctx, *password != NULL,
1583 "Failing ChangePasswordUser as old password was NULL. Previous test failed?");
1585 oldpass = *password;
1587 E_md4hash(oldpass, old_nt_hash);
1588 E_md4hash(newpass, new_nt_hash);
1589 E_deshash(oldpass, old_lm_hash);
1590 E_deshash(newpass, new_lm_hash);
1592 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1593 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1594 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1595 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1596 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1597 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1599 r.in.user_handle = &user_handle;
1600 r.in.lm_present = 1;
1601 /* Break the LM hash */
1602 hash1.hash[0]++;
1603 r.in.old_lm_crypted = &hash1;
1604 r.in.new_lm_crypted = &hash2;
1605 r.in.nt_present = 1;
1606 r.in.old_nt_crypted = &hash3;
1607 r.in.new_nt_crypted = &hash4;
1608 r.in.cross1_present = 1;
1609 r.in.nt_cross = &hash5;
1610 r.in.cross2_present = 1;
1611 r.in.lm_cross = &hash6;
1613 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1614 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1615 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1617 /* Unbreak the LM hash */
1618 hash1.hash[0]--;
1620 r.in.user_handle = &user_handle;
1621 r.in.lm_present = 1;
1622 r.in.old_lm_crypted = &hash1;
1623 r.in.new_lm_crypted = &hash2;
1624 /* Break the NT hash */
1625 hash3.hash[0]--;
1626 r.in.nt_present = 1;
1627 r.in.old_nt_crypted = &hash3;
1628 r.in.new_nt_crypted = &hash4;
1629 r.in.cross1_present = 1;
1630 r.in.nt_cross = &hash5;
1631 r.in.cross2_present = 1;
1632 r.in.lm_cross = &hash6;
1634 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1635 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1636 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1638 /* Unbreak the NT hash */
1639 hash3.hash[0]--;
1641 r.in.user_handle = &user_handle;
1642 r.in.lm_present = 1;
1643 r.in.old_lm_crypted = &hash1;
1644 r.in.new_lm_crypted = &hash2;
1645 r.in.nt_present = 1;
1646 r.in.old_nt_crypted = &hash3;
1647 r.in.new_nt_crypted = &hash4;
1648 r.in.cross1_present = 1;
1649 r.in.nt_cross = &hash5;
1650 r.in.cross2_present = 1;
1651 /* Break the LM cross */
1652 hash6.hash[0]++;
1653 r.in.lm_cross = &hash6;
1655 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1656 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1657 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1658 ret = false;
1661 /* Unbreak the LM cross */
1662 hash6.hash[0]--;
1664 r.in.user_handle = &user_handle;
1665 r.in.lm_present = 1;
1666 r.in.old_lm_crypted = &hash1;
1667 r.in.new_lm_crypted = &hash2;
1668 r.in.nt_present = 1;
1669 r.in.old_nt_crypted = &hash3;
1670 r.in.new_nt_crypted = &hash4;
1671 r.in.cross1_present = 1;
1672 /* Break the NT cross */
1673 hash5.hash[0]++;
1674 r.in.nt_cross = &hash5;
1675 r.in.cross2_present = 1;
1676 r.in.lm_cross = &hash6;
1678 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1679 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1680 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1681 ret = false;
1684 /* Unbreak the NT cross */
1685 hash5.hash[0]--;
1688 /* Reset the hashes to not broken values */
1689 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1690 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1691 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1692 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1693 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1694 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1696 r.in.user_handle = &user_handle;
1697 r.in.lm_present = 1;
1698 r.in.old_lm_crypted = &hash1;
1699 r.in.new_lm_crypted = &hash2;
1700 r.in.nt_present = 1;
1701 r.in.old_nt_crypted = &hash3;
1702 r.in.new_nt_crypted = &hash4;
1703 r.in.cross1_present = 1;
1704 r.in.nt_cross = &hash5;
1705 r.in.cross2_present = 0;
1706 r.in.lm_cross = NULL;
1708 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1709 if (NT_STATUS_IS_OK(status)) {
1710 changed = true;
1711 *password = newpass;
1712 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1713 printf("ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1714 ret = false;
1717 oldpass = newpass;
1718 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1720 E_md4hash(oldpass, old_nt_hash);
1721 E_md4hash(newpass, new_nt_hash);
1722 E_deshash(oldpass, old_lm_hash);
1723 E_deshash(newpass, new_lm_hash);
1726 /* Reset the hashes to not broken values */
1727 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1728 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1729 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1730 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1731 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1732 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1734 r.in.user_handle = &user_handle;
1735 r.in.lm_present = 1;
1736 r.in.old_lm_crypted = &hash1;
1737 r.in.new_lm_crypted = &hash2;
1738 r.in.nt_present = 1;
1739 r.in.old_nt_crypted = &hash3;
1740 r.in.new_nt_crypted = &hash4;
1741 r.in.cross1_present = 0;
1742 r.in.nt_cross = NULL;
1743 r.in.cross2_present = 1;
1744 r.in.lm_cross = &hash6;
1746 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1747 if (NT_STATUS_IS_OK(status)) {
1748 changed = true;
1749 *password = newpass;
1750 } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1751 printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1752 ret = false;
1755 oldpass = newpass;
1756 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1758 E_md4hash(oldpass, old_nt_hash);
1759 E_md4hash(newpass, new_nt_hash);
1760 E_deshash(oldpass, old_lm_hash);
1761 E_deshash(newpass, new_lm_hash);
1764 /* Reset the hashes to not broken values */
1765 E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1766 E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1767 E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1768 E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1769 E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1770 E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1772 r.in.user_handle = &user_handle;
1773 r.in.lm_present = 1;
1774 r.in.old_lm_crypted = &hash1;
1775 r.in.new_lm_crypted = &hash2;
1776 r.in.nt_present = 1;
1777 r.in.old_nt_crypted = &hash3;
1778 r.in.new_nt_crypted = &hash4;
1779 r.in.cross1_present = 1;
1780 r.in.nt_cross = &hash5;
1781 r.in.cross2_present = 1;
1782 r.in.lm_cross = &hash6;
1784 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1785 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1786 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1787 } else if (!NT_STATUS_IS_OK(status)) {
1788 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1789 ret = false;
1790 } else {
1791 changed = true;
1792 *password = newpass;
1795 r.in.user_handle = &user_handle;
1796 r.in.lm_present = 1;
1797 r.in.old_lm_crypted = &hash1;
1798 r.in.new_lm_crypted = &hash2;
1799 r.in.nt_present = 1;
1800 r.in.old_nt_crypted = &hash3;
1801 r.in.new_nt_crypted = &hash4;
1802 r.in.cross1_present = 1;
1803 r.in.nt_cross = &hash5;
1804 r.in.cross2_present = 1;
1805 r.in.lm_cross = &hash6;
1807 if (changed) {
1808 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1809 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1810 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1811 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1812 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1813 ret = false;
1818 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1819 ret = false;
1822 return ret;
1826 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1827 const char *acct_name,
1828 struct policy_handle *handle, char **password)
1830 NTSTATUS status;
1831 struct samr_OemChangePasswordUser2 r;
1832 bool ret = true;
1833 struct samr_Password lm_verifier;
1834 struct samr_CryptPassword lm_pass;
1835 struct lsa_AsciiString server, account, account_bad;
1836 char *oldpass;
1837 char *newpass;
1838 uint8_t old_lm_hash[16], new_lm_hash[16];
1840 struct samr_GetDomPwInfo dom_pw_info;
1841 struct samr_PwInfo info;
1842 int policy_min_pw_len = 0;
1844 struct lsa_String domain_name;
1846 domain_name.string = "";
1847 dom_pw_info.in.domain_name = &domain_name;
1848 dom_pw_info.out.info = &info;
1850 torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1852 torture_assert(tctx, *password != NULL,
1853 "Failing OemChangePasswordUser2 as old password was NULL. Previous test failed?");
1855 oldpass = *password;
1857 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1858 if (NT_STATUS_IS_OK(status)) {
1859 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1862 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1864 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1865 account.string = acct_name;
1867 E_deshash(oldpass, old_lm_hash);
1868 E_deshash(newpass, new_lm_hash);
1870 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1871 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1872 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1874 r.in.server = &server;
1875 r.in.account = &account;
1876 r.in.password = &lm_pass;
1877 r.in.hash = &lm_verifier;
1879 /* Break the verification */
1880 lm_verifier.hash[0]++;
1882 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1884 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1885 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1886 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1887 nt_errstr(status));
1888 ret = false;
1891 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1892 /* Break the old password */
1893 old_lm_hash[0]++;
1894 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1895 /* unbreak it for the next operation */
1896 old_lm_hash[0]--;
1897 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1899 r.in.server = &server;
1900 r.in.account = &account;
1901 r.in.password = &lm_pass;
1902 r.in.hash = &lm_verifier;
1904 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1906 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1907 && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1908 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1909 nt_errstr(status));
1910 ret = false;
1913 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1914 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1916 r.in.server = &server;
1917 r.in.account = &account;
1918 r.in.password = &lm_pass;
1919 r.in.hash = NULL;
1921 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1923 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1924 && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1925 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1926 nt_errstr(status));
1927 ret = false;
1930 /* This shouldn't be a valid name */
1931 account_bad.string = TEST_ACCOUNT_NAME "XX";
1932 r.in.account = &account_bad;
1934 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1936 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1937 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1938 nt_errstr(status));
1939 ret = false;
1942 /* This shouldn't be a valid name */
1943 account_bad.string = TEST_ACCOUNT_NAME "XX";
1944 r.in.account = &account_bad;
1945 r.in.password = &lm_pass;
1946 r.in.hash = &lm_verifier;
1948 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1950 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1951 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1952 nt_errstr(status));
1953 ret = false;
1956 /* This shouldn't be a valid name */
1957 account_bad.string = TEST_ACCOUNT_NAME "XX";
1958 r.in.account = &account_bad;
1959 r.in.password = NULL;
1960 r.in.hash = &lm_verifier;
1962 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1964 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1965 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
1966 nt_errstr(status));
1967 ret = false;
1970 E_deshash(oldpass, old_lm_hash);
1971 E_deshash(newpass, new_lm_hash);
1973 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1974 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1975 E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1977 r.in.server = &server;
1978 r.in.account = &account;
1979 r.in.password = &lm_pass;
1980 r.in.hash = &lm_verifier;
1982 status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1983 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1984 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1985 } else if (!NT_STATUS_IS_OK(status)) {
1986 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
1987 ret = false;
1988 } else {
1989 *password = newpass;
1992 return ret;
1996 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1997 const char *acct_name,
1998 char **password,
1999 char *newpass, bool allow_password_restriction)
2001 NTSTATUS status;
2002 struct samr_ChangePasswordUser2 r;
2003 bool ret = true;
2004 struct lsa_String server, account;
2005 struct samr_CryptPassword nt_pass, lm_pass;
2006 struct samr_Password nt_verifier, lm_verifier;
2007 char *oldpass;
2008 uint8_t old_nt_hash[16], new_nt_hash[16];
2009 uint8_t old_lm_hash[16], new_lm_hash[16];
2011 struct samr_GetDomPwInfo dom_pw_info;
2012 struct samr_PwInfo info;
2014 struct lsa_String domain_name;
2016 domain_name.string = "";
2017 dom_pw_info.in.domain_name = &domain_name;
2018 dom_pw_info.out.info = &info;
2020 torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2022 torture_assert(tctx, *password != NULL,
2023 "Failing ChangePasswordUser2 as old password was NULL. Previous test failed?");
2024 oldpass = *password;
2026 if (!newpass) {
2027 int policy_min_pw_len = 0;
2028 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
2029 if (NT_STATUS_IS_OK(status)) {
2030 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2033 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2036 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2037 init_lsa_String(&account, acct_name);
2039 E_md4hash(oldpass, old_nt_hash);
2040 E_md4hash(newpass, new_nt_hash);
2042 E_deshash(oldpass, old_lm_hash);
2043 E_deshash(newpass, new_lm_hash);
2045 encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2046 arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2047 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2049 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2050 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2051 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2053 r.in.server = &server;
2054 r.in.account = &account;
2055 r.in.nt_password = &nt_pass;
2056 r.in.nt_verifier = &nt_verifier;
2057 r.in.lm_change = 1;
2058 r.in.lm_password = &lm_pass;
2059 r.in.lm_verifier = &lm_verifier;
2061 status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
2062 if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2063 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
2064 } else if (!NT_STATUS_IS_OK(status)) {
2065 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
2066 ret = false;
2067 } else {
2068 *password = newpass;
2071 return ret;
2075 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2076 const char *account_string,
2077 int policy_min_pw_len,
2078 char **password,
2079 const char *newpass,
2080 NTTIME last_password_change,
2081 bool handle_reject_reason)
2083 NTSTATUS status;
2084 struct samr_ChangePasswordUser3 r;
2085 bool ret = true;
2086 struct lsa_String server, account, account_bad;
2087 struct samr_CryptPassword nt_pass, lm_pass;
2088 struct samr_Password nt_verifier, lm_verifier;
2089 char *oldpass;
2090 uint8_t old_nt_hash[16], new_nt_hash[16];
2091 uint8_t old_lm_hash[16], new_lm_hash[16];
2092 NTTIME t;
2093 struct samr_DomInfo1 *dominfo = NULL;
2094 struct samr_ChangeReject *reject = NULL;
2096 torture_comment(tctx, "Testing ChangePasswordUser3\n");
2098 if (newpass == NULL) {
2099 do {
2100 if (policy_min_pw_len == 0) {
2101 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2102 } else {
2103 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2105 } while (check_password_quality(newpass) == false);
2106 } else {
2107 torture_comment(tctx, "Using password '%s'\n", newpass);
2110 torture_assert(tctx, *password != NULL,
2111 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2113 oldpass = *password;
2114 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2115 init_lsa_String(&account, account_string);
2117 E_md4hash(oldpass, old_nt_hash);
2118 E_md4hash(newpass, new_nt_hash);
2120 E_deshash(oldpass, old_lm_hash);
2121 E_deshash(newpass, new_lm_hash);
2123 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2124 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2125 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2127 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2128 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2129 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2131 /* Break the verification */
2132 nt_verifier.hash[0]++;
2134 r.in.server = &server;
2135 r.in.account = &account;
2136 r.in.nt_password = &nt_pass;
2137 r.in.nt_verifier = &nt_verifier;
2138 r.in.lm_change = 1;
2139 r.in.lm_password = &lm_pass;
2140 r.in.lm_verifier = &lm_verifier;
2141 r.in.password3 = NULL;
2142 r.out.dominfo = &dominfo;
2143 r.out.reject = &reject;
2145 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2146 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2147 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2148 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2149 nt_errstr(status));
2150 ret = false;
2153 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2154 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2155 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2157 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2158 /* Break the NT hash */
2159 old_nt_hash[0]++;
2160 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2161 /* Unbreak it again */
2162 old_nt_hash[0]--;
2163 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2165 r.in.server = &server;
2166 r.in.account = &account;
2167 r.in.nt_password = &nt_pass;
2168 r.in.nt_verifier = &nt_verifier;
2169 r.in.lm_change = 1;
2170 r.in.lm_password = &lm_pass;
2171 r.in.lm_verifier = &lm_verifier;
2172 r.in.password3 = NULL;
2173 r.out.dominfo = &dominfo;
2174 r.out.reject = &reject;
2176 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2177 if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2178 (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2179 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2180 nt_errstr(status));
2181 ret = false;
2184 /* This shouldn't be a valid name */
2185 init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2187 r.in.account = &account_bad;
2188 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2189 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2190 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2191 nt_errstr(status));
2192 ret = false;
2195 E_md4hash(oldpass, old_nt_hash);
2196 E_md4hash(newpass, new_nt_hash);
2198 E_deshash(oldpass, old_lm_hash);
2199 E_deshash(newpass, new_lm_hash);
2201 encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2202 arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2203 E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2205 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2206 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2207 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2209 r.in.server = &server;
2210 r.in.account = &account;
2211 r.in.nt_password = &nt_pass;
2212 r.in.nt_verifier = &nt_verifier;
2213 r.in.lm_change = 1;
2214 r.in.lm_password = &lm_pass;
2215 r.in.lm_verifier = &lm_verifier;
2216 r.in.password3 = NULL;
2217 r.out.dominfo = &dominfo;
2218 r.out.reject = &reject;
2220 unix_to_nt_time(&t, time(NULL));
2222 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2224 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2225 && dominfo
2226 && reject
2227 && handle_reject_reason
2228 && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2229 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2231 if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
2232 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2233 SAMR_REJECT_OTHER, reject->reason);
2234 return false;
2238 /* We tested the order of precendence which is as follows:
2240 * pwd min_age
2241 * pwd length
2242 * pwd complexity
2243 * pwd history
2245 Guenther */
2247 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2248 (last_password_change + dominfo->min_password_age > t)) {
2250 if (reject->reason != SAMR_REJECT_OTHER) {
2251 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2252 SAMR_REJECT_OTHER, reject->reason);
2253 return false;
2256 } else if ((dominfo->min_password_length > 0) &&
2257 (strlen(newpass) < dominfo->min_password_length)) {
2259 if (reject->reason != SAMR_REJECT_TOO_SHORT) {
2260 printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n",
2261 SAMR_REJECT_TOO_SHORT, reject->reason);
2262 return false;
2265 } else if ((dominfo->password_history_length > 0) &&
2266 strequal(oldpass, newpass)) {
2268 if (reject->reason != SAMR_REJECT_IN_HISTORY) {
2269 printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n",
2270 SAMR_REJECT_IN_HISTORY, reject->reason);
2271 return false;
2273 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2275 if (reject->reason != SAMR_REJECT_COMPLEXITY) {
2276 printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n",
2277 SAMR_REJECT_COMPLEXITY, reject->reason);
2278 return false;
2283 if (reject->reason == SAMR_REJECT_TOO_SHORT) {
2284 /* retry with adjusted size */
2285 return test_ChangePasswordUser3(p, tctx, account_string,
2286 dominfo->min_password_length,
2287 password, NULL, 0, false);
2291 } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2292 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2293 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2294 SAMR_REJECT_OTHER, reject->reason);
2295 return false;
2297 /* Perhaps the server has a 'min password age' set? */
2299 } else {
2300 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2301 *password = talloc_strdup(tctx, newpass);
2304 return ret;
2307 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2308 const char *account_string,
2309 struct policy_handle *handle,
2310 char **password)
2312 NTSTATUS status;
2313 struct samr_ChangePasswordUser3 r;
2314 struct samr_SetUserInfo s;
2315 union samr_UserInfo u;
2316 DATA_BLOB session_key;
2317 DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2318 uint8_t confounder[16];
2319 struct MD5Context ctx;
2321 bool ret = true;
2322 struct lsa_String server, account;
2323 struct samr_CryptPassword nt_pass;
2324 struct samr_Password nt_verifier;
2325 DATA_BLOB new_random_pass;
2326 char *newpass;
2327 char *oldpass;
2328 uint8_t old_nt_hash[16], new_nt_hash[16];
2329 NTTIME t;
2330 struct samr_DomInfo1 *dominfo = NULL;
2331 struct samr_ChangeReject *reject = NULL;
2333 new_random_pass = samr_very_rand_pass(tctx, 128);
2335 torture_assert(tctx, *password != NULL,
2336 "Failing ChangePasswordUser3 as old password was NULL. Previous test failed?");
2338 oldpass = *password;
2339 server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2340 init_lsa_String(&account, account_string);
2342 s.in.user_handle = handle;
2343 s.in.info = &u;
2344 s.in.level = 25;
2346 ZERO_STRUCT(u);
2348 u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2350 set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2352 status = dcerpc_fetch_session_key(p, &session_key);
2353 if (!NT_STATUS_IS_OK(status)) {
2354 printf("SetUserInfo level %u - no session key - %s\n",
2355 s.in.level, nt_errstr(status));
2356 return false;
2359 generate_random_buffer((uint8_t *)confounder, 16);
2361 MD5Init(&ctx);
2362 MD5Update(&ctx, confounder, 16);
2363 MD5Update(&ctx, session_key.data, session_key.length);
2364 MD5Final(confounded_session_key.data, &ctx);
2366 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2367 memcpy(&u.info25.password.data[516], confounder, 16);
2369 torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2371 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2372 if (!NT_STATUS_IS_OK(status)) {
2373 printf("SetUserInfo level %u failed - %s\n",
2374 s.in.level, nt_errstr(status));
2375 ret = false;
2378 torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2380 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2382 new_random_pass = samr_very_rand_pass(tctx, 128);
2384 mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2386 set_pw_in_buffer(nt_pass.data, &new_random_pass);
2387 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2388 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2390 r.in.server = &server;
2391 r.in.account = &account;
2392 r.in.nt_password = &nt_pass;
2393 r.in.nt_verifier = &nt_verifier;
2394 r.in.lm_change = 0;
2395 r.in.lm_password = NULL;
2396 r.in.lm_verifier = NULL;
2397 r.in.password3 = NULL;
2398 r.out.dominfo = &dominfo;
2399 r.out.reject = &reject;
2401 unix_to_nt_time(&t, time(NULL));
2403 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2405 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2406 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2407 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2408 SAMR_REJECT_OTHER, reject->reason);
2409 return false;
2411 /* Perhaps the server has a 'min password age' set? */
2413 } else if (!NT_STATUS_IS_OK(status)) {
2414 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2415 ret = false;
2418 newpass = samr_rand_pass(tctx, 128);
2420 mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2422 E_md4hash(newpass, new_nt_hash);
2424 encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2425 arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2426 E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2428 r.in.server = &server;
2429 r.in.account = &account;
2430 r.in.nt_password = &nt_pass;
2431 r.in.nt_verifier = &nt_verifier;
2432 r.in.lm_change = 0;
2433 r.in.lm_password = NULL;
2434 r.in.lm_verifier = NULL;
2435 r.in.password3 = NULL;
2436 r.out.dominfo = &dominfo;
2437 r.out.reject = &reject;
2439 unix_to_nt_time(&t, time(NULL));
2441 status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2443 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2444 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2445 printf("expected SAMR_REJECT_OTHER (%d), got %d\n",
2446 SAMR_REJECT_OTHER, reject->reason);
2447 return false;
2449 /* Perhaps the server has a 'min password age' set? */
2451 } else {
2452 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2453 *password = talloc_strdup(tctx, newpass);
2456 return ret;
2460 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2461 struct policy_handle *alias_handle)
2463 struct samr_GetMembersInAlias r;
2464 struct lsa_SidArray sids;
2465 NTSTATUS status;
2467 torture_comment(tctx, "Testing GetMembersInAlias\n");
2469 r.in.alias_handle = alias_handle;
2470 r.out.sids = &sids;
2472 status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2473 torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2475 return true;
2478 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2479 struct policy_handle *alias_handle,
2480 const struct dom_sid *domain_sid)
2482 struct samr_AddAliasMember r;
2483 struct samr_DeleteAliasMember d;
2484 NTSTATUS status;
2485 struct dom_sid *sid;
2487 sid = dom_sid_add_rid(tctx, domain_sid, 512);
2489 torture_comment(tctx, "testing AddAliasMember\n");
2490 r.in.alias_handle = alias_handle;
2491 r.in.sid = sid;
2493 status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2494 torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2496 d.in.alias_handle = alias_handle;
2497 d.in.sid = sid;
2499 status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2500 torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2502 return true;
2505 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2506 struct policy_handle *alias_handle)
2508 struct samr_AddMultipleMembersToAlias a;
2509 struct samr_RemoveMultipleMembersFromAlias r;
2510 NTSTATUS status;
2511 struct lsa_SidArray sids;
2513 torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2514 a.in.alias_handle = alias_handle;
2515 a.in.sids = &sids;
2517 sids.num_sids = 3;
2518 sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2520 sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2521 sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2522 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2524 status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2525 torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2528 torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2529 r.in.alias_handle = alias_handle;
2530 r.in.sids = &sids;
2532 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2533 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2535 /* strange! removing twice doesn't give any error */
2536 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2537 torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2539 /* but removing an alias that isn't there does */
2540 sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2542 status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2543 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2545 return true;
2548 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2549 struct policy_handle *user_handle)
2551 struct samr_TestPrivateFunctionsUser r;
2552 NTSTATUS status;
2554 torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2556 r.in.user_handle = user_handle;
2558 status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2559 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2561 return true;
2564 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2565 struct torture_context *tctx,
2566 struct policy_handle *handle,
2567 bool use_info2,
2568 NTTIME *pwdlastset)
2570 NTSTATUS status;
2571 uint16_t levels[] = { /* 3, */ 5, 21 };
2572 int i;
2573 NTTIME pwdlastset3 = 0;
2574 NTTIME pwdlastset5 = 0;
2575 NTTIME pwdlastset21 = 0;
2577 torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2578 use_info2 ? "2":"");
2580 for (i=0; i<ARRAY_SIZE(levels); i++) {
2582 struct samr_QueryUserInfo r;
2583 struct samr_QueryUserInfo2 r2;
2584 union samr_UserInfo *info;
2586 if (use_info2) {
2587 r2.in.user_handle = handle;
2588 r2.in.level = levels[i];
2589 r2.out.info = &info;
2590 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2592 } else {
2593 r.in.user_handle = handle;
2594 r.in.level = levels[i];
2595 r.out.info = &info;
2596 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2599 if (!NT_STATUS_IS_OK(status) &&
2600 !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2601 printf("QueryUserInfo%s level %u failed - %s\n",
2602 use_info2 ? "2":"", levels[i], nt_errstr(status));
2603 return false;
2606 switch (levels[i]) {
2607 case 3:
2608 pwdlastset3 = info->info3.last_password_change;
2609 break;
2610 case 5:
2611 pwdlastset5 = info->info5.last_password_change;
2612 break;
2613 case 21:
2614 pwdlastset21 = info->info21.last_password_change;
2615 break;
2616 default:
2617 return false;
2620 /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2621 "pwdlastset mixup"); */
2622 torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2623 "pwdlastset mixup");
2625 *pwdlastset = pwdlastset21;
2627 torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2629 return true;
2632 static bool test_SamLogon_Creds(struct dcerpc_pipe *p, struct torture_context *tctx,
2633 struct cli_credentials *machine_credentials,
2634 struct cli_credentials *test_credentials,
2635 struct creds_CredentialState *creds,
2636 NTSTATUS expected_result)
2638 NTSTATUS status;
2639 struct netr_LogonSamLogon r;
2640 struct netr_Authenticator auth, auth2;
2641 union netr_LogonLevel logon;
2642 union netr_Validation validation;
2643 uint8_t authoritative;
2644 struct netr_NetworkInfo ninfo;
2645 DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2646 int flags = CLI_CRED_NTLM_AUTH;
2648 if (lp_client_lanman_auth(tctx->lp_ctx)) {
2649 flags |= CLI_CRED_LANMAN_AUTH;
2652 if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2653 flags |= CLI_CRED_NTLMv2_AUTH;
2656 cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2657 &ninfo.identity_info.account_name.string,
2658 &ninfo.identity_info.domain_name.string);
2660 generate_random_buffer(ninfo.challenge,
2661 sizeof(ninfo.challenge));
2662 chal = data_blob_const(ninfo.challenge,
2663 sizeof(ninfo.challenge));
2665 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(machine_credentials),
2666 cli_credentials_get_domain(machine_credentials));
2668 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2669 &flags,
2670 chal,
2671 names_blob,
2672 &lm_resp, &nt_resp,
2673 NULL, NULL);
2674 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2676 ninfo.lm.data = lm_resp.data;
2677 ninfo.lm.length = lm_resp.length;
2679 ninfo.nt.data = nt_resp.data;
2680 ninfo.nt.length = nt_resp.length;
2682 ninfo.identity_info.parameter_control =
2683 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2684 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2685 ninfo.identity_info.logon_id_low = 0;
2686 ninfo.identity_info.logon_id_high = 0;
2687 ninfo.identity_info.workstation.string = cli_credentials_get_workstation(machine_credentials);
2689 logon.network = &ninfo;
2691 r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2692 r.in.computer_name = cli_credentials_get_workstation(machine_credentials);
2693 r.in.credential = &auth;
2694 r.in.return_authenticator = &auth2;
2695 r.in.logon_level = 2;
2696 r.in.logon = &logon;
2697 r.out.validation = &validation;
2698 r.out.authoritative = &authoritative;
2700 d_printf("Testing LogonSamLogon with name %s\n", ninfo.identity_info.account_name.string);
2702 ZERO_STRUCT(auth2);
2703 creds_client_authenticator(creds, &auth);
2705 r.in.validation_level = 2;
2707 status = dcerpc_netr_LogonSamLogon(p, tctx, &r);
2708 if (!NT_STATUS_IS_OK(status)) {
2709 torture_assert_ntstatus_equal(tctx, status, expected_result, "LogonSamLogon failed");
2710 return true;
2711 } else {
2712 torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");
2715 torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred),
2716 "Credential chaining failed");
2718 return true;
2721 static bool test_SamLogon(struct torture_context *tctx,
2722 struct dcerpc_pipe *p,
2723 struct cli_credentials *machine_credentials,
2724 struct cli_credentials *test_credentials,
2725 NTSTATUS expected_result)
2727 struct creds_CredentialState *creds;
2729 if (!test_SetupCredentials(p, tctx, machine_credentials, &creds)) {
2730 return false;
2733 return test_SamLogon_Creds(p, tctx, machine_credentials, test_credentials,
2734 creds, expected_result);
2737 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2738 struct dcerpc_pipe *p,
2739 struct cli_credentials *machine_creds,
2740 const char *acct_name,
2741 char *password,
2742 NTSTATUS expected_samlogon_result)
2744 bool ret = true;
2745 struct cli_credentials *test_credentials;
2747 test_credentials = cli_credentials_init(tctx);
2749 cli_credentials_set_workstation(test_credentials,
2750 TEST_ACCOUNT_NAME_PWD, CRED_SPECIFIED);
2751 cli_credentials_set_domain(test_credentials,
2752 lp_workgroup(tctx->lp_ctx), CRED_SPECIFIED);
2753 cli_credentials_set_username(test_credentials,
2754 acct_name, CRED_SPECIFIED);
2755 cli_credentials_set_password(test_credentials,
2756 password, CRED_SPECIFIED);
2757 cli_credentials_set_secure_channel_type(test_credentials, SEC_CHAN_BDC);
2759 printf("testing samlogon as %s@%s password: %s\n",
2760 acct_name, TEST_ACCOUNT_NAME_PWD, password);
2762 if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
2763 expected_samlogon_result)) {
2764 torture_warning(tctx, "new password did not work\n");
2765 ret = false;
2768 return ret;
2771 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2772 struct dcerpc_pipe *np,
2773 struct torture_context *tctx,
2774 struct policy_handle *handle,
2775 uint16_t level,
2776 uint32_t fields_present,
2777 uint8_t password_expired,
2778 bool *matched_expected_error,
2779 bool use_setinfo2,
2780 const char *acct_name,
2781 char **password,
2782 struct cli_credentials *machine_creds,
2783 bool use_queryinfo2,
2784 NTTIME *pwdlastset,
2785 NTSTATUS expected_samlogon_result)
2787 const char *fields = NULL;
2788 bool ret = true;
2790 switch (level) {
2791 case 21:
2792 case 23:
2793 case 25:
2794 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2795 fields_present);
2796 break;
2797 default:
2798 break;
2801 torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2802 "(password_expired: %d) %s\n",
2803 use_setinfo2 ? "2":"", level, password_expired,
2804 fields ? fields : "");
2806 if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2807 fields_present,
2808 password,
2809 password_expired,
2810 use_setinfo2,
2811 matched_expected_error)) {
2812 ret = false;
2815 if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2816 use_queryinfo2,
2817 pwdlastset)) {
2818 ret = false;
2821 if (*matched_expected_error == true) {
2822 return ret;
2825 if (!test_SamLogon_with_creds(tctx, np,
2826 machine_creds,
2827 acct_name,
2828 *password,
2829 expected_samlogon_result)) {
2830 ret = false;
2833 return ret;
2836 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2837 struct torture_context *tctx,
2838 uint32_t acct_flags,
2839 const char *acct_name,
2840 struct policy_handle *handle,
2841 char **password,
2842 struct cli_credentials *machine_credentials)
2844 int s = 0, q = 0, f = 0, l = 0, z = 0;
2845 bool ret = true;
2846 int delay = 500000;
2847 bool set_levels[] = { false, true };
2848 bool query_levels[] = { false, true };
2849 uint32_t levels[] = { 18, 21, 23, 24, 25, 26 };
2850 uint32_t nonzeros[] = { 1, 24 };
2851 uint32_t fields_present[] = {
2853 SAMR_FIELD_EXPIRED_FLAG,
2854 SAMR_FIELD_LAST_PWD_CHANGE,
2855 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2856 SAMR_FIELD_COMMENT,
2857 SAMR_FIELD_NT_PASSWORD_PRESENT,
2858 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2859 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2860 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2861 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2862 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2863 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2865 NTSTATUS status;
2866 struct dcerpc_pipe *np = NULL;
2868 if (torture_setting_bool(tctx, "samba3", false)) {
2869 delay = 1000000;
2870 printf("Samba3 has second granularity, setting delay to: %d\n",
2871 delay);
2874 status = torture_rpc_connection(tctx, &np, &ndr_table_netlogon);
2875 if (!NT_STATUS_IS_OK(status)) {
2876 return false;
2879 /* set to 1 to enable testing for all possible opcode
2880 (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2881 combinations */
2882 #if 0
2883 #define TEST_SET_LEVELS 1
2884 #define TEST_QUERY_LEVELS 1
2885 #endif
2886 for (l=0; l<ARRAY_SIZE(levels); l++) {
2887 for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
2888 for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2889 #ifdef TEST_SET_LEVELS
2890 for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2891 #endif
2892 #ifdef TEST_QUERY_LEVELS
2893 for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2894 #endif
2895 NTTIME pwdlastset_old = 0;
2896 NTTIME pwdlastset_new = 0;
2897 bool matched_expected_error = false;
2898 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
2900 torture_comment(tctx, "------------------------------\n"
2901 "Testing pwdLastSet attribute for flags: 0x%08x "
2902 "(s: %d (l: %d), q: %d)\n",
2903 acct_flags, s, levels[l], q);
2905 switch (levels[l]) {
2906 case 21:
2907 case 23:
2908 case 25:
2909 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2910 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
2911 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
2913 break;
2917 /* set #1 */
2919 /* set a password and force password change (pwdlastset 0) by
2920 * setting the password expired flag to a non-0 value */
2922 if (!test_SetPassword_level(p, np, tctx, handle,
2923 levels[l],
2924 fields_present[f],
2925 nonzeros[z],
2926 &matched_expected_error,
2927 set_levels[s],
2928 acct_name,
2929 password,
2930 machine_credentials,
2931 query_levels[q],
2932 &pwdlastset_old,
2933 expected_samlogon_result)) {
2934 ret = false;
2937 if (matched_expected_error == true) {
2938 /* skipping on expected failure */
2939 continue;
2942 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2943 * set without the SAMR_FIELD_EXPIRED_FLAG */
2945 switch (levels[l]) {
2946 case 21:
2947 case 23:
2948 case 25:
2949 if ((pwdlastset_new != 0) &&
2950 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
2951 torture_comment(tctx, "not considering a non-0 "
2952 "pwdLastSet as a an error as the "
2953 "SAMR_FIELD_EXPIRED_FLAG has not "
2954 "been set\n");
2955 break;
2957 default:
2958 if (pwdlastset_new != 0) {
2959 torture_warning(tctx, "pwdLastSet test failed: "
2960 "expected pwdLastSet 0 but got %lld\n",
2961 pwdlastset_old);
2962 ret = false;
2964 break;
2967 switch (levels[l]) {
2968 case 21:
2969 case 23:
2970 case 25:
2971 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2972 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
2973 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2974 (pwdlastset_old >= pwdlastset_new)) {
2975 torture_warning(tctx, "pwdlastset not increasing\n");
2976 ret = false;
2978 break;
2979 default:
2980 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2981 (pwdlastset_old >= pwdlastset_new)) {
2982 torture_warning(tctx, "pwdlastset not increasing\n");
2983 ret = false;
2985 break;
2988 usleep(delay);
2990 /* set #2 */
2992 /* set a password, pwdlastset needs to get updated (increased
2993 * value), password_expired value used here is 0 */
2995 if (!test_SetPassword_level(p, np, tctx, handle,
2996 levels[l],
2997 fields_present[f],
2999 &matched_expected_error,
3000 set_levels[s],
3001 acct_name,
3002 password,
3003 machine_credentials,
3004 query_levels[q],
3005 &pwdlastset_new,
3006 expected_samlogon_result)) {
3007 ret = false;
3010 /* when a password has been changed, pwdlastset must not be 0 afterwards
3011 * and must be larger then the old value */
3013 switch (levels[l]) {
3014 case 21:
3015 case 23:
3016 case 25:
3018 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3019 * password has been changed, old and new pwdlastset
3020 * need to be the same value */
3022 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3023 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3024 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3026 torture_assert_int_equal(tctx, pwdlastset_old,
3027 pwdlastset_new, "pwdlastset must be equal");
3028 break;
3030 default:
3031 if (pwdlastset_old >= pwdlastset_new) {
3032 torture_warning(tctx, "pwdLastSet test failed: "
3033 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3034 pwdlastset_old, pwdlastset_new);
3035 ret = false;
3037 if (pwdlastset_new == 0) {
3038 torture_warning(tctx, "pwdLastSet test failed: "
3039 "expected non-0 pwdlastset, got: %lld\n",
3040 pwdlastset_new);
3041 ret = false;
3045 switch (levels[l]) {
3046 case 21:
3047 case 23:
3048 case 25:
3049 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3050 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3051 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3052 (pwdlastset_old >= pwdlastset_new)) {
3053 torture_warning(tctx, "pwdlastset not increasing\n");
3054 ret = false;
3056 break;
3057 default:
3058 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3059 (pwdlastset_old >= pwdlastset_new)) {
3060 torture_warning(tctx, "pwdlastset not increasing\n");
3061 ret = false;
3063 break;
3066 pwdlastset_old = pwdlastset_new;
3068 usleep(delay);
3070 /* set #2b */
3072 /* set a password, pwdlastset needs to get updated (increased
3073 * value), password_expired value used here is 0 */
3075 if (!test_SetPassword_level(p, np, tctx, handle,
3076 levels[l],
3077 fields_present[f],
3079 &matched_expected_error,
3080 set_levels[s],
3081 acct_name,
3082 password,
3083 machine_credentials,
3084 query_levels[q],
3085 &pwdlastset_new,
3086 expected_samlogon_result)) {
3087 ret = false;
3090 /* when a password has been changed, pwdlastset must not be 0 afterwards
3091 * and must be larger then the old value */
3093 switch (levels[l]) {
3094 case 21:
3095 case 23:
3096 case 25:
3098 /* if no password has been changed, old and new pwdlastset
3099 * need to be the same value */
3101 if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3102 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3104 torture_assert_int_equal(tctx, pwdlastset_old,
3105 pwdlastset_new, "pwdlastset must be equal");
3106 break;
3108 default:
3109 if (pwdlastset_old >= pwdlastset_new) {
3110 torture_warning(tctx, "pwdLastSet test failed: "
3111 "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3112 pwdlastset_old, pwdlastset_new);
3113 ret = false;
3115 if (pwdlastset_new == 0) {
3116 torture_warning(tctx, "pwdLastSet test failed: "
3117 "expected non-0 pwdlastset, got: %lld\n",
3118 pwdlastset_new);
3119 ret = false;
3123 /* set #3 */
3125 /* set a password and force password change (pwdlastset 0) by
3126 * setting the password expired flag to a non-0 value */
3128 if (!test_SetPassword_level(p, np, tctx, handle,
3129 levels[l],
3130 fields_present[f],
3131 nonzeros[z],
3132 &matched_expected_error,
3133 set_levels[s],
3134 acct_name,
3135 password,
3136 machine_credentials,
3137 query_levels[q],
3138 &pwdlastset_new,
3139 expected_samlogon_result)) {
3140 ret = false;
3143 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3144 * set without the SAMR_FIELD_EXPIRED_FLAG */
3146 switch (levels[l]) {
3147 case 21:
3148 case 23:
3149 case 25:
3150 if ((pwdlastset_new != 0) &&
3151 !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3152 torture_comment(tctx, "not considering a non-0 "
3153 "pwdLastSet as a an error as the "
3154 "SAMR_FIELD_EXPIRED_FLAG has not "
3155 "been set\n");
3156 break;
3159 /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3160 * password has been changed, old and new pwdlastset
3161 * need to be the same value */
3163 if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3164 !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3165 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3167 torture_assert_int_equal(tctx, pwdlastset_old,
3168 pwdlastset_new, "pwdlastset must be equal");
3169 break;
3171 default:
3173 if (pwdlastset_old == pwdlastset_new) {
3174 torture_warning(tctx, "pwdLastSet test failed: "
3175 "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
3176 pwdlastset_old, pwdlastset_new);
3177 ret = false;
3180 if (pwdlastset_new != 0) {
3181 torture_warning(tctx, "pwdLastSet test failed: "
3182 "expected pwdLastSet 0, got %lld\n",
3183 pwdlastset_old);
3184 ret = false;
3186 break;
3189 switch (levels[l]) {
3190 case 21:
3191 case 23:
3192 case 25:
3193 if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3194 (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3195 (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3196 (pwdlastset_old >= pwdlastset_new)) {
3197 torture_warning(tctx, "pwdlastset not increasing\n");
3198 ret = false;
3200 break;
3201 default:
3202 if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3203 (pwdlastset_old >= pwdlastset_new)) {
3204 torture_warning(tctx, "pwdlastset not increasing\n");
3205 ret = false;
3207 break;
3210 /* if the level we are testing does not have a fields_present
3211 * field, skip all fields present tests by setting f to to
3212 * arraysize */
3213 switch (levels[l]) {
3214 case 18:
3215 case 24:
3216 case 26:
3217 f = ARRAY_SIZE(fields_present);
3218 break;
3221 #ifdef TEST_QUERY_LEVELS
3223 #endif
3224 #ifdef TEST_SET_LEVELS
3226 #endif
3227 } /* fields present */
3228 } /* nonzeros */
3229 } /* levels */
3231 #undef TEST_SET_LEVELS
3232 #undef TEST_QUERY_LEVELS
3234 return ret;
3237 static bool test_user_ops(struct dcerpc_pipe *p,
3238 struct torture_context *tctx,
3239 struct policy_handle *user_handle,
3240 struct policy_handle *domain_handle,
3241 uint32_t base_acct_flags,
3242 const char *base_acct_name, enum torture_samr_choice which_ops,
3243 struct cli_credentials *machine_credentials)
3245 char *password = NULL;
3246 struct samr_QueryUserInfo q;
3247 union samr_UserInfo *info;
3248 NTSTATUS status;
3250 bool ret = true;
3251 int i;
3252 uint32_t rid;
3253 const uint32_t password_fields[] = {
3254 SAMR_FIELD_NT_PASSWORD_PRESENT,
3255 SAMR_FIELD_LM_PASSWORD_PRESENT,
3256 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3260 status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3261 if (!NT_STATUS_IS_OK(status)) {
3262 ret = false;
3265 switch (which_ops) {
3266 case TORTURE_SAMR_USER_ATTRIBUTES:
3267 if (!test_QuerySecurity(p, tctx, user_handle)) {
3268 ret = false;
3271 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3272 ret = false;
3275 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3276 ret = false;
3279 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3280 base_acct_name)) {
3281 ret = false;
3284 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3285 ret = false;
3288 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3289 ret = false;
3292 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3293 ret = false;
3295 break;
3296 case TORTURE_SAMR_PASSWORDS:
3297 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3298 char simple_pass[9];
3299 char *v = generate_random_str(tctx, 1);
3301 ZERO_STRUCT(simple_pass);
3302 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3304 printf("Testing machine account password policy rules\n");
3306 /* Workstation trust accounts don't seem to need to honour password quality policy */
3307 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3308 ret = false;
3311 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3312 ret = false;
3315 /* reset again, to allow another 'user' password change */
3316 if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3317 ret = false;
3320 /* Try a 'short' password */
3321 if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3322 ret = false;
3325 /* Try a compleatly random password */
3326 if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3327 ret = false;
3331 for (i = 0; password_fields[i]; i++) {
3332 if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3333 ret = false;
3336 /* check it was set right */
3337 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3338 ret = false;
3342 for (i = 0; password_fields[i]; i++) {
3343 if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3344 ret = false;
3347 /* check it was set right */
3348 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3349 ret = false;
3353 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
3354 ret = false;
3357 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
3358 ret = false;
3361 if (torture_setting_bool(tctx, "samba4", false)) {
3362 printf("skipping Set Password level 18 and 21 against Samba4\n");
3363 } else {
3365 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
3366 ret = false;
3369 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3370 ret = false;
3373 for (i = 0; password_fields[i]; i++) {
3375 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
3376 /* we need to skip as that would break
3377 * the ChangePasswordUser3 verify */
3378 continue;
3381 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
3382 ret = false;
3385 /* check it was set right */
3386 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3387 ret = false;
3392 q.in.user_handle = user_handle;
3393 q.in.level = 5;
3394 q.out.info = &info;
3396 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
3397 if (!NT_STATUS_IS_OK(status)) {
3398 printf("QueryUserInfo level %u failed - %s\n",
3399 q.in.level, nt_errstr(status));
3400 ret = false;
3401 } else {
3402 uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
3403 if ((info->info5.acct_flags) != expected_flags) {
3404 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3405 info->info5.acct_flags,
3406 expected_flags);
3407 ret = false;
3409 if (info->info5.rid != rid) {
3410 printf("QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
3411 info->info5.rid, rid);
3416 break;
3418 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
3420 /* test last password change timestamp behaviour */
3421 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
3422 base_acct_name,
3423 user_handle, &password,
3424 machine_credentials)) {
3425 ret = false;
3428 if (ret == true) {
3429 torture_comment(tctx, "pwdLastSet test succeeded\n");
3430 } else {
3431 torture_warning(tctx, "pwdLastSet test failed\n");
3434 break;
3436 case TORTURE_SAMR_OTHER:
3437 /* We just need the account to exist */
3438 break;
3440 return ret;
3443 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
3444 struct policy_handle *alias_handle,
3445 const struct dom_sid *domain_sid)
3447 bool ret = true;
3449 if (!test_QuerySecurity(p, tctx, alias_handle)) {
3450 ret = false;
3453 if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
3454 ret = false;
3457 if (!test_SetAliasInfo(p, tctx, alias_handle)) {
3458 ret = false;
3461 if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
3462 ret = false;
3465 if (torture_setting_bool(tctx, "samba4", false)) {
3466 printf("skipping MultipleMembers Alias tests against Samba4\n");
3467 return ret;
3470 if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
3471 ret = false;
3474 return ret;
3478 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3479 struct policy_handle *user_handle)
3481 struct samr_DeleteUser d;
3482 NTSTATUS status;
3483 torture_comment(tctx, "Testing DeleteUser\n");
3485 d.in.user_handle = user_handle;
3486 d.out.user_handle = user_handle;
3488 status = dcerpc_samr_DeleteUser(p, tctx, &d);
3489 torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
3491 return true;
3494 bool test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3495 struct policy_handle *handle, const char *name)
3497 NTSTATUS status;
3498 struct samr_DeleteUser d;
3499 struct policy_handle user_handle;
3500 uint32_t rid;
3502 status = test_LookupName(p, mem_ctx, handle, name, &rid);
3503 if (!NT_STATUS_IS_OK(status)) {
3504 goto failed;
3507 status = test_OpenUser_byname(p, mem_ctx, handle, name, &user_handle);
3508 if (!NT_STATUS_IS_OK(status)) {
3509 goto failed;
3512 d.in.user_handle = &user_handle;
3513 d.out.user_handle = &user_handle;
3514 status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
3515 if (!NT_STATUS_IS_OK(status)) {
3516 goto failed;
3519 return true;
3521 failed:
3522 printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
3523 return false;
3527 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3528 struct policy_handle *handle, const char *name)
3530 NTSTATUS status;
3531 struct samr_OpenGroup r;
3532 struct samr_DeleteDomainGroup d;
3533 struct policy_handle group_handle;
3534 uint32_t rid;
3536 status = test_LookupName(p, mem_ctx, handle, name, &rid);
3537 if (!NT_STATUS_IS_OK(status)) {
3538 goto failed;
3541 r.in.domain_handle = handle;
3542 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3543 r.in.rid = rid;
3544 r.out.group_handle = &group_handle;
3545 status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
3546 if (!NT_STATUS_IS_OK(status)) {
3547 goto failed;
3550 d.in.group_handle = &group_handle;
3551 d.out.group_handle = &group_handle;
3552 status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
3553 if (!NT_STATUS_IS_OK(status)) {
3554 goto failed;
3557 return true;
3559 failed:
3560 printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
3561 return false;
3565 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3566 struct policy_handle *domain_handle, const char *name)
3568 NTSTATUS status;
3569 struct samr_OpenAlias r;
3570 struct samr_DeleteDomAlias d;
3571 struct policy_handle alias_handle;
3572 uint32_t rid;
3574 printf("testing DeleteAlias_byname\n");
3576 status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
3577 if (!NT_STATUS_IS_OK(status)) {
3578 goto failed;
3581 r.in.domain_handle = domain_handle;
3582 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3583 r.in.rid = rid;
3584 r.out.alias_handle = &alias_handle;
3585 status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
3586 if (!NT_STATUS_IS_OK(status)) {
3587 goto failed;
3590 d.in.alias_handle = &alias_handle;
3591 d.out.alias_handle = &alias_handle;
3592 status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
3593 if (!NT_STATUS_IS_OK(status)) {
3594 goto failed;
3597 return true;
3599 failed:
3600 printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
3601 return false;
3604 static bool test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3605 struct policy_handle *alias_handle)
3607 struct samr_DeleteDomAlias d;
3608 NTSTATUS status;
3609 bool ret = true;
3610 printf("Testing DeleteAlias\n");
3612 d.in.alias_handle = alias_handle;
3613 d.out.alias_handle = alias_handle;
3615 status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
3616 if (!NT_STATUS_IS_OK(status)) {
3617 printf("DeleteAlias failed - %s\n", nt_errstr(status));
3618 ret = false;
3621 return ret;
3624 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
3625 struct policy_handle *domain_handle,
3626 struct policy_handle *alias_handle,
3627 const struct dom_sid *domain_sid)
3629 NTSTATUS status;
3630 struct samr_CreateDomAlias r;
3631 struct lsa_String name;
3632 uint32_t rid;
3633 bool ret = true;
3635 init_lsa_String(&name, TEST_ALIASNAME);
3636 r.in.domain_handle = domain_handle;
3637 r.in.alias_name = &name;
3638 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3639 r.out.alias_handle = alias_handle;
3640 r.out.rid = &rid;
3642 printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
3644 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
3646 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
3647 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3648 printf("Server correctly refused create of '%s'\n", r.in.alias_name->string);
3649 return true;
3650 } else {
3651 printf("Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
3652 nt_errstr(status));
3653 return false;
3657 if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
3658 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
3659 return false;
3661 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
3664 if (!NT_STATUS_IS_OK(status)) {
3665 printf("CreateAlias failed - %s\n", nt_errstr(status));
3666 return false;
3669 if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
3670 ret = false;
3673 return ret;
3676 static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3677 const char *acct_name,
3678 struct policy_handle *domain_handle, char **password)
3680 bool ret = true;
3682 if (!*password) {
3683 return false;
3686 if (!test_ChangePasswordUser(p, mem_ctx, acct_name, domain_handle, password)) {
3687 ret = false;
3690 if (!test_ChangePasswordUser2(p, mem_ctx, acct_name, password, 0, true)) {
3691 ret = false;
3694 if (!test_OemChangePasswordUser2(p, mem_ctx, acct_name, domain_handle, password)) {
3695 ret = false;
3698 /* test what happens when setting the old password again */
3699 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, *password, 0, true)) {
3700 ret = false;
3704 char simple_pass[9];
3705 char *v = generate_random_str(mem_ctx, 1);
3707 ZERO_STRUCT(simple_pass);
3708 memset(simple_pass, *v, sizeof(simple_pass) - 1);
3710 /* test what happens when picking a simple password */
3711 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, simple_pass, 0, true)) {
3712 ret = false;
3716 /* set samr_SetDomainInfo level 1 with min_length 5 */
3718 struct samr_QueryDomainInfo r;
3719 union samr_DomainInfo *info = NULL;
3720 struct samr_SetDomainInfo s;
3721 uint16_t len_old, len;
3722 uint32_t pwd_prop_old;
3723 int64_t min_pwd_age_old;
3724 NTSTATUS status;
3726 len = 5;
3728 r.in.domain_handle = domain_handle;
3729 r.in.level = 1;
3730 r.out.info = &info;
3732 printf("testing samr_QueryDomainInfo level 1\n");
3733 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
3734 if (!NT_STATUS_IS_OK(status)) {
3735 return false;
3738 s.in.domain_handle = domain_handle;
3739 s.in.level = 1;
3740 s.in.info = info;
3742 /* remember the old min length, so we can reset it */
3743 len_old = s.in.info->info1.min_password_length;
3744 s.in.info->info1.min_password_length = len;
3745 pwd_prop_old = s.in.info->info1.password_properties;
3746 /* turn off password complexity checks for this test */
3747 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
3749 min_pwd_age_old = s.in.info->info1.min_password_age;
3750 s.in.info->info1.min_password_age = 0;
3752 printf("testing samr_SetDomainInfo level 1\n");
3753 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
3754 if (!NT_STATUS_IS_OK(status)) {
3755 return false;
3758 printf("calling test_ChangePasswordUser3 with too short password\n");
3760 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, len - 1, password, NULL, 0, true)) {
3761 ret = false;
3764 s.in.info->info1.min_password_length = len_old;
3765 s.in.info->info1.password_properties = pwd_prop_old;
3766 s.in.info->info1.min_password_age = min_pwd_age_old;
3768 printf("testing samr_SetDomainInfo level 1\n");
3769 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
3770 if (!NT_STATUS_IS_OK(status)) {
3771 return false;
3777 NTSTATUS status;
3778 struct samr_OpenUser r;
3779 struct samr_QueryUserInfo q;
3780 union samr_UserInfo *info;
3781 struct samr_LookupNames n;
3782 struct policy_handle user_handle;
3783 struct samr_Ids rids, types;
3785 n.in.domain_handle = domain_handle;
3786 n.in.num_names = 1;
3787 n.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
3788 n.in.names[0].string = acct_name;
3789 n.out.rids = &rids;
3790 n.out.types = &types;
3792 status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
3793 if (!NT_STATUS_IS_OK(status)) {
3794 printf("LookupNames failed - %s\n", nt_errstr(status));
3795 return false;
3798 r.in.domain_handle = domain_handle;
3799 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3800 r.in.rid = n.out.rids->ids[0];
3801 r.out.user_handle = &user_handle;
3803 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
3804 if (!NT_STATUS_IS_OK(status)) {
3805 printf("OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
3806 return false;
3809 q.in.user_handle = &user_handle;
3810 q.in.level = 5;
3811 q.out.info = &info;
3813 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
3814 if (!NT_STATUS_IS_OK(status)) {
3815 printf("QueryUserInfo failed - %s\n", nt_errstr(status));
3816 return false;
3819 printf("calling test_ChangePasswordUser3 with too early password change\n");
3821 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL,
3822 info->info5.last_password_change, true)) {
3823 ret = false;
3827 /* we change passwords twice - this has the effect of verifying
3828 they were changed correctly for the final call */
3829 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
3830 ret = false;
3833 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, true)) {
3834 ret = false;
3837 return ret;
3840 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
3841 struct policy_handle *domain_handle,
3842 struct policy_handle *user_handle_out,
3843 struct dom_sid *domain_sid,
3844 enum torture_samr_choice which_ops,
3845 struct cli_credentials *machine_credentials)
3848 TALLOC_CTX *user_ctx;
3850 NTSTATUS status;
3851 struct samr_CreateUser r;
3852 struct samr_QueryUserInfo q;
3853 union samr_UserInfo *info;
3854 struct samr_DeleteUser d;
3855 uint32_t rid;
3857 /* This call creates a 'normal' account - check that it really does */
3858 const uint32_t acct_flags = ACB_NORMAL;
3859 struct lsa_String name;
3860 bool ret = true;
3862 struct policy_handle user_handle;
3863 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
3864 init_lsa_String(&name, TEST_ACCOUNT_NAME);
3866 r.in.domain_handle = domain_handle;
3867 r.in.account_name = &name;
3868 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3869 r.out.user_handle = &user_handle;
3870 r.out.rid = &rid;
3872 printf("Testing CreateUser(%s)\n", r.in.account_name->string);
3874 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
3876 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
3877 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
3878 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
3879 return true;
3880 } else {
3881 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
3882 nt_errstr(status));
3883 return false;
3887 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
3888 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
3889 talloc_free(user_ctx);
3890 return false;
3892 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
3894 if (!NT_STATUS_IS_OK(status)) {
3895 talloc_free(user_ctx);
3896 printf("CreateUser failed - %s\n", nt_errstr(status));
3897 return false;
3898 } else {
3899 q.in.user_handle = &user_handle;
3900 q.in.level = 16;
3901 q.out.info = &info;
3903 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
3904 if (!NT_STATUS_IS_OK(status)) {
3905 printf("QueryUserInfo level %u failed - %s\n",
3906 q.in.level, nt_errstr(status));
3907 ret = false;
3908 } else {
3909 if ((info->info16.acct_flags & acct_flags) != acct_flags) {
3910 printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
3911 info->info16.acct_flags,
3912 acct_flags);
3913 ret = false;
3917 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
3918 acct_flags, name.string, which_ops,
3919 machine_credentials)) {
3920 ret = false;
3923 if (user_handle_out) {
3924 *user_handle_out = user_handle;
3925 } else {
3926 printf("Testing DeleteUser (createuser test)\n");
3928 d.in.user_handle = &user_handle;
3929 d.out.user_handle = &user_handle;
3931 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
3932 if (!NT_STATUS_IS_OK(status)) {
3933 printf("DeleteUser failed - %s\n", nt_errstr(status));
3934 ret = false;
3940 talloc_free(user_ctx);
3942 return ret;
3946 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
3947 struct policy_handle *domain_handle,
3948 struct dom_sid *domain_sid,
3949 enum torture_samr_choice which_ops,
3950 struct cli_credentials *machine_credentials)
3952 NTSTATUS status;
3953 struct samr_CreateUser2 r;
3954 struct samr_QueryUserInfo q;
3955 union samr_UserInfo *info;
3956 struct samr_DeleteUser d;
3957 struct policy_handle user_handle;
3958 uint32_t rid;
3959 struct lsa_String name;
3960 bool ret = true;
3961 int i;
3963 struct {
3964 uint32_t acct_flags;
3965 const char *account_name;
3966 NTSTATUS nt_status;
3967 } account_types[] = {
3968 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
3969 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
3970 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
3971 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
3972 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
3973 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
3974 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
3975 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
3976 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
3977 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
3978 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
3979 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
3980 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
3981 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
3982 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
3985 for (i = 0; account_types[i].account_name; i++) {
3986 TALLOC_CTX *user_ctx;
3987 uint32_t acct_flags = account_types[i].acct_flags;
3988 uint32_t access_granted;
3989 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
3990 init_lsa_String(&name, account_types[i].account_name);
3992 r.in.domain_handle = domain_handle;
3993 r.in.account_name = &name;
3994 r.in.acct_flags = acct_flags;
3995 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3996 r.out.user_handle = &user_handle;
3997 r.out.access_granted = &access_granted;
3998 r.out.rid = &rid;
4000 printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
4002 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4004 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4005 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
4006 printf("Server correctly refused create of '%s'\n", r.in.account_name->string);
4007 continue;
4008 } else {
4009 printf("Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
4010 nt_errstr(status));
4011 ret = false;
4012 continue;
4016 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4017 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
4018 talloc_free(user_ctx);
4019 ret = false;
4020 continue;
4022 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
4025 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
4026 printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
4027 nt_errstr(status), nt_errstr(account_types[i].nt_status));
4028 ret = false;
4031 if (NT_STATUS_IS_OK(status)) {
4032 q.in.user_handle = &user_handle;
4033 q.in.level = 5;
4034 q.out.info = &info;
4036 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
4037 if (!NT_STATUS_IS_OK(status)) {
4038 printf("QueryUserInfo level %u failed - %s\n",
4039 q.in.level, nt_errstr(status));
4040 ret = false;
4041 } else {
4042 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4043 if (acct_flags == ACB_NORMAL) {
4044 expected_flags |= ACB_PW_EXPIRED;
4046 if ((info->info5.acct_flags) != expected_flags) {
4047 printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4048 info->info5.acct_flags,
4049 expected_flags);
4050 ret = false;
4052 switch (acct_flags) {
4053 case ACB_SVRTRUST:
4054 if (info->info5.primary_gid != DOMAIN_RID_DCS) {
4055 printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
4056 DOMAIN_RID_DCS, info->info5.primary_gid);
4057 ret = false;
4059 break;
4060 case ACB_WSTRUST:
4061 if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
4062 printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
4063 DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
4064 ret = false;
4066 break;
4067 case ACB_NORMAL:
4068 if (info->info5.primary_gid != DOMAIN_RID_USERS) {
4069 printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
4070 DOMAIN_RID_USERS, info->info5.primary_gid);
4071 ret = false;
4073 break;
4077 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
4078 acct_flags, name.string, which_ops,
4079 machine_credentials)) {
4080 ret = false;
4083 printf("Testing DeleteUser (createuser2 test)\n");
4085 d.in.user_handle = &user_handle;
4086 d.out.user_handle = &user_handle;
4088 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
4089 if (!NT_STATUS_IS_OK(status)) {
4090 printf("DeleteUser failed - %s\n", nt_errstr(status));
4091 ret = false;
4094 talloc_free(user_ctx);
4097 return ret;
4100 static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4101 struct policy_handle *handle)
4103 NTSTATUS status;
4104 struct samr_QueryAliasInfo r;
4105 union samr_AliasInfo *info;
4106 uint16_t levels[] = {1, 2, 3};
4107 int i;
4108 bool ret = true;
4110 for (i=0;i<ARRAY_SIZE(levels);i++) {
4111 printf("Testing QueryAliasInfo level %u\n", levels[i]);
4113 r.in.alias_handle = handle;
4114 r.in.level = levels[i];
4115 r.out.info = &info;
4117 status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
4118 if (!NT_STATUS_IS_OK(status)) {
4119 printf("QueryAliasInfo level %u failed - %s\n",
4120 levels[i], nt_errstr(status));
4121 ret = false;
4125 return ret;
4128 static bool test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4129 struct policy_handle *handle)
4131 NTSTATUS status;
4132 struct samr_QueryGroupInfo r;
4133 union samr_GroupInfo *info;
4134 uint16_t levels[] = {1, 2, 3, 4, 5};
4135 int i;
4136 bool ret = true;
4138 for (i=0;i<ARRAY_SIZE(levels);i++) {
4139 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4141 r.in.group_handle = handle;
4142 r.in.level = levels[i];
4143 r.out.info = &info;
4145 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
4146 if (!NT_STATUS_IS_OK(status)) {
4147 printf("QueryGroupInfo level %u failed - %s\n",
4148 levels[i], nt_errstr(status));
4149 ret = false;
4153 return ret;
4156 static bool test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4157 struct policy_handle *handle)
4159 NTSTATUS status;
4160 struct samr_QueryGroupMember r;
4161 struct samr_RidTypeArray *rids = NULL;
4162 bool ret = true;
4164 printf("Testing QueryGroupMember\n");
4166 r.in.group_handle = handle;
4167 r.out.rids = &rids;
4169 status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r);
4170 if (!NT_STATUS_IS_OK(status)) {
4171 printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
4172 ret = false;
4175 return ret;
4179 static bool test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4180 struct policy_handle *handle)
4182 NTSTATUS status;
4183 struct samr_QueryGroupInfo r;
4184 union samr_GroupInfo *info;
4185 struct samr_SetGroupInfo s;
4186 uint16_t levels[] = {1, 2, 3, 4};
4187 uint16_t set_ok[] = {0, 1, 1, 1};
4188 int i;
4189 bool ret = true;
4191 for (i=0;i<ARRAY_SIZE(levels);i++) {
4192 printf("Testing QueryGroupInfo level %u\n", levels[i]);
4194 r.in.group_handle = handle;
4195 r.in.level = levels[i];
4196 r.out.info = &info;
4198 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
4199 if (!NT_STATUS_IS_OK(status)) {
4200 printf("QueryGroupInfo level %u failed - %s\n",
4201 levels[i], nt_errstr(status));
4202 ret = false;
4205 printf("Testing SetGroupInfo level %u\n", levels[i]);
4207 s.in.group_handle = handle;
4208 s.in.level = levels[i];
4209 s.in.info = *r.out.info;
4211 #if 0
4212 /* disabled this, as it changes the name only from the point of view of samr,
4213 but leaves the name from the point of view of w2k3 internals (and ldap). This means
4214 the name is still reserved, so creating the old name fails, but deleting by the old name
4215 also fails */
4216 if (s.in.level == 2) {
4217 init_lsa_String(&s.in.info->string, "NewName");
4219 #endif
4221 if (s.in.level == 4) {
4222 init_lsa_String(&s.in.info->description, "test description");
4225 status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
4226 if (set_ok[i]) {
4227 if (!NT_STATUS_IS_OK(status)) {
4228 printf("SetGroupInfo level %u failed - %s\n",
4229 r.in.level, nt_errstr(status));
4230 ret = false;
4231 continue;
4233 } else {
4234 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
4235 printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
4236 r.in.level, nt_errstr(status));
4237 ret = false;
4238 continue;
4243 return ret;
4246 static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4247 struct policy_handle *handle)
4249 NTSTATUS status;
4250 struct samr_QueryUserInfo r;
4251 union samr_UserInfo *info;
4252 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4253 11, 12, 13, 14, 16, 17, 20, 21};
4254 int i;
4255 bool ret = true;
4257 for (i=0;i<ARRAY_SIZE(levels);i++) {
4258 printf("Testing QueryUserInfo level %u\n", levels[i]);
4260 r.in.user_handle = handle;
4261 r.in.level = levels[i];
4262 r.out.info = &info;
4264 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r);
4265 if (!NT_STATUS_IS_OK(status)) {
4266 printf("QueryUserInfo level %u failed - %s\n",
4267 levels[i], nt_errstr(status));
4268 ret = false;
4272 return ret;
4275 static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4276 struct policy_handle *handle)
4278 NTSTATUS status;
4279 struct samr_QueryUserInfo2 r;
4280 union samr_UserInfo *info;
4281 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
4282 11, 12, 13, 14, 16, 17, 20, 21};
4283 int i;
4284 bool ret = true;
4286 for (i=0;i<ARRAY_SIZE(levels);i++) {
4287 printf("Testing QueryUserInfo2 level %u\n", levels[i]);
4289 r.in.user_handle = handle;
4290 r.in.level = levels[i];
4291 r.out.info = &info;
4293 status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r);
4294 if (!NT_STATUS_IS_OK(status)) {
4295 printf("QueryUserInfo2 level %u failed - %s\n",
4296 levels[i], nt_errstr(status));
4297 ret = false;
4301 return ret;
4304 static bool test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4305 struct policy_handle *handle, uint32_t rid)
4307 NTSTATUS status;
4308 struct samr_OpenUser r;
4309 struct policy_handle user_handle;
4310 bool ret = true;
4312 printf("Testing OpenUser(%u)\n", rid);
4314 r.in.domain_handle = handle;
4315 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4316 r.in.rid = rid;
4317 r.out.user_handle = &user_handle;
4319 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
4320 if (!NT_STATUS_IS_OK(status)) {
4321 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4322 return false;
4325 if (!test_QuerySecurity(p, mem_ctx, &user_handle)) {
4326 ret = false;
4329 if (!test_QueryUserInfo(p, mem_ctx, &user_handle)) {
4330 ret = false;
4333 if (!test_QueryUserInfo2(p, mem_ctx, &user_handle)) {
4334 ret = false;
4337 if (!test_GetUserPwInfo(p, mem_ctx, &user_handle)) {
4338 ret = false;
4341 if (!test_GetGroupsForUser(p,mem_ctx, &user_handle)) {
4342 ret = false;
4345 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
4346 ret = false;
4349 return ret;
4352 static bool test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4353 struct policy_handle *handle, uint32_t rid)
4355 NTSTATUS status;
4356 struct samr_OpenGroup r;
4357 struct policy_handle group_handle;
4358 bool ret = true;
4360 printf("Testing OpenGroup(%u)\n", rid);
4362 r.in.domain_handle = handle;
4363 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4364 r.in.rid = rid;
4365 r.out.group_handle = &group_handle;
4367 status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
4368 if (!NT_STATUS_IS_OK(status)) {
4369 printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
4370 return false;
4373 if (!test_QuerySecurity(p, mem_ctx, &group_handle)) {
4374 ret = false;
4377 if (!test_QueryGroupInfo(p, mem_ctx, &group_handle)) {
4378 ret = false;
4381 if (!test_QueryGroupMember(p, mem_ctx, &group_handle)) {
4382 ret = false;
4385 if (!test_samr_handle_Close(p, mem_ctx, &group_handle)) {
4386 ret = false;
4389 return ret;
4392 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4393 struct policy_handle *handle, uint32_t rid)
4395 NTSTATUS status;
4396 struct samr_OpenAlias r;
4397 struct policy_handle alias_handle;
4398 bool ret = true;
4400 torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
4402 r.in.domain_handle = handle;
4403 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4404 r.in.rid = rid;
4405 r.out.alias_handle = &alias_handle;
4407 status = dcerpc_samr_OpenAlias(p, tctx, &r);
4408 if (!NT_STATUS_IS_OK(status)) {
4409 printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
4410 return false;
4413 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
4414 ret = false;
4417 if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
4418 ret = false;
4421 if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
4422 ret = false;
4425 if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
4426 ret = false;
4429 return ret;
4432 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
4433 struct policy_handle *handle, uint32_t rid,
4434 uint32_t acct_flag_mask)
4436 NTSTATUS status;
4437 struct samr_OpenUser r;
4438 struct samr_QueryUserInfo q;
4439 union samr_UserInfo *info;
4440 struct policy_handle user_handle;
4441 bool ret = true;
4443 torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
4445 r.in.domain_handle = handle;
4446 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4447 r.in.rid = rid;
4448 r.out.user_handle = &user_handle;
4450 status = dcerpc_samr_OpenUser(p, tctx, &r);
4451 if (!NT_STATUS_IS_OK(status)) {
4452 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
4453 return false;
4456 q.in.user_handle = &user_handle;
4457 q.in.level = 16;
4458 q.out.info = &info;
4460 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4461 if (!NT_STATUS_IS_OK(status)) {
4462 printf("QueryUserInfo level 16 failed - %s\n",
4463 nt_errstr(status));
4464 ret = false;
4465 } else {
4466 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
4467 printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
4468 acct_flag_mask, info->info16.acct_flags, rid);
4469 ret = false;
4473 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
4474 ret = false;
4477 return ret;
4480 static bool test_EnumDomainUsers(struct dcerpc_pipe *p, struct torture_context *tctx,
4481 struct policy_handle *handle)
4483 NTSTATUS status = STATUS_MORE_ENTRIES;
4484 struct samr_EnumDomainUsers r;
4485 uint32_t mask, resume_handle=0;
4486 int i, mask_idx;
4487 bool ret = true;
4488 struct samr_LookupNames n;
4489 struct samr_LookupRids lr ;
4490 struct lsa_Strings names;
4491 struct samr_Ids rids, types;
4492 struct samr_SamArray *sam = NULL;
4493 uint32_t num_entries = 0;
4495 uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
4496 ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
4497 ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
4498 ACB_PWNOEXP, 0};
4500 printf("Testing EnumDomainUsers\n");
4502 for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
4503 r.in.domain_handle = handle;
4504 r.in.resume_handle = &resume_handle;
4505 r.in.acct_flags = mask = masks[mask_idx];
4506 r.in.max_size = (uint32_t)-1;
4507 r.out.resume_handle = &resume_handle;
4508 r.out.num_entries = &num_entries;
4509 r.out.sam = &sam;
4511 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
4512 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
4513 !NT_STATUS_IS_OK(status)) {
4514 printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
4515 return false;
4518 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
4520 if (sam->count == 0) {
4521 continue;
4524 for (i=0;i<sam->count;i++) {
4525 if (mask) {
4526 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
4527 ret = false;
4529 } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
4530 ret = false;
4535 printf("Testing LookupNames\n");
4536 n.in.domain_handle = handle;
4537 n.in.num_names = sam->count;
4538 n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
4539 n.out.rids = &rids;
4540 n.out.types = &types;
4541 for (i=0;i<sam->count;i++) {
4542 n.in.names[i].string = sam->entries[i].name.string;
4544 status = dcerpc_samr_LookupNames(p, tctx, &n);
4545 if (!NT_STATUS_IS_OK(status)) {
4546 printf("LookupNames failed - %s\n", nt_errstr(status));
4547 ret = false;
4551 printf("Testing LookupRids\n");
4552 lr.in.domain_handle = handle;
4553 lr.in.num_rids = sam->count;
4554 lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
4555 lr.out.names = &names;
4556 lr.out.types = &types;
4557 for (i=0;i<sam->count;i++) {
4558 lr.in.rids[i] = sam->entries[i].idx;
4560 status = dcerpc_samr_LookupRids(p, tctx, &lr);
4561 torture_assert_ntstatus_ok(tctx, status, "LookupRids");
4563 return ret;
4567 try blasting the server with a bunch of sync requests
4569 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
4570 struct policy_handle *handle)
4572 NTSTATUS status;
4573 struct samr_EnumDomainUsers r;
4574 uint32_t resume_handle=0;
4575 int i;
4576 #define ASYNC_COUNT 100
4577 struct rpc_request *req[ASYNC_COUNT];
4579 if (!torture_setting_bool(tctx, "dangerous", false)) {
4580 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
4583 torture_comment(tctx, "Testing EnumDomainUsers_async\n");
4585 r.in.domain_handle = handle;
4586 r.in.resume_handle = &resume_handle;
4587 r.in.acct_flags = 0;
4588 r.in.max_size = (uint32_t)-1;
4589 r.out.resume_handle = &resume_handle;
4591 for (i=0;i<ASYNC_COUNT;i++) {
4592 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
4595 for (i=0;i<ASYNC_COUNT;i++) {
4596 status = dcerpc_ndr_request_recv(req[i]);
4597 if (!NT_STATUS_IS_OK(status)) {
4598 printf("EnumDomainUsers[%d] failed - %s\n",
4599 i, nt_errstr(status));
4600 return false;
4604 torture_comment(tctx, "%d async requests OK\n", i);
4606 return true;
4609 static bool test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4610 struct policy_handle *handle)
4612 NTSTATUS status;
4613 struct samr_EnumDomainGroups r;
4614 uint32_t resume_handle=0;
4615 struct samr_SamArray *sam = NULL;
4616 uint32_t num_entries = 0;
4617 int i;
4618 bool ret = true;
4620 printf("Testing EnumDomainGroups\n");
4622 r.in.domain_handle = handle;
4623 r.in.resume_handle = &resume_handle;
4624 r.in.max_size = (uint32_t)-1;
4625 r.out.resume_handle = &resume_handle;
4626 r.out.num_entries = &num_entries;
4627 r.out.sam = &sam;
4629 status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
4630 if (!NT_STATUS_IS_OK(status)) {
4631 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
4632 return false;
4635 if (!sam) {
4636 return false;
4639 for (i=0;i<sam->count;i++) {
4640 if (!test_OpenGroup(p, mem_ctx, handle, sam->entries[i].idx)) {
4641 ret = false;
4645 return ret;
4648 static bool test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4649 struct policy_handle *handle)
4651 NTSTATUS status;
4652 struct samr_EnumDomainAliases r;
4653 uint32_t resume_handle=0;
4654 struct samr_SamArray *sam = NULL;
4655 uint32_t num_entries = 0;
4656 int i;
4657 bool ret = true;
4659 printf("Testing EnumDomainAliases\n");
4661 r.in.domain_handle = handle;
4662 r.in.resume_handle = &resume_handle;
4663 r.in.max_size = (uint32_t)-1;
4664 r.out.sam = &sam;
4665 r.out.num_entries = &num_entries;
4666 r.out.resume_handle = &resume_handle;
4668 status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
4669 if (!NT_STATUS_IS_OK(status)) {
4670 printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
4671 return false;
4674 if (!sam) {
4675 return false;
4678 for (i=0;i<sam->count;i++) {
4679 if (!test_OpenAlias(p, mem_ctx, handle, sam->entries[i].idx)) {
4680 ret = false;
4684 return ret;
4687 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4688 struct policy_handle *handle)
4690 NTSTATUS status;
4691 struct samr_GetDisplayEnumerationIndex r;
4692 bool ret = true;
4693 uint16_t levels[] = {1, 2, 3, 4, 5};
4694 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
4695 struct lsa_String name;
4696 uint32_t idx = 0;
4697 int i;
4699 for (i=0;i<ARRAY_SIZE(levels);i++) {
4700 printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
4702 init_lsa_String(&name, TEST_ACCOUNT_NAME);
4704 r.in.domain_handle = handle;
4705 r.in.level = levels[i];
4706 r.in.name = &name;
4707 r.out.idx = &idx;
4709 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
4711 if (ok_lvl[i] &&
4712 !NT_STATUS_IS_OK(status) &&
4713 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4714 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
4715 levels[i], nt_errstr(status));
4716 ret = false;
4719 init_lsa_String(&name, "zzzzzzzz");
4721 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
4723 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4724 printf("GetDisplayEnumerationIndex level %u failed - %s\n",
4725 levels[i], nt_errstr(status));
4726 ret = false;
4730 return ret;
4733 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4734 struct policy_handle *handle)
4736 NTSTATUS status;
4737 struct samr_GetDisplayEnumerationIndex2 r;
4738 bool ret = true;
4739 uint16_t levels[] = {1, 2, 3, 4, 5};
4740 uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
4741 struct lsa_String name;
4742 uint32_t idx = 0;
4743 int i;
4745 for (i=0;i<ARRAY_SIZE(levels);i++) {
4746 printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
4748 init_lsa_String(&name, TEST_ACCOUNT_NAME);
4750 r.in.domain_handle = handle;
4751 r.in.level = levels[i];
4752 r.in.name = &name;
4753 r.out.idx = &idx;
4755 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
4756 if (ok_lvl[i] &&
4757 !NT_STATUS_IS_OK(status) &&
4758 !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4759 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
4760 levels[i], nt_errstr(status));
4761 ret = false;
4764 init_lsa_String(&name, "zzzzzzzz");
4766 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
4767 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
4768 printf("GetDisplayEnumerationIndex2 level %u failed - %s\n",
4769 levels[i], nt_errstr(status));
4770 ret = false;
4774 return ret;
4777 #define STRING_EQUAL_QUERY(s1, s2, user) \
4778 if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
4779 /* odd, but valid */ \
4780 } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
4781 printf("%s mismatch for %s: %s != %s (%s)\n", \
4782 #s1, user.string, s1.string, s2.string, __location__); \
4783 ret = false; \
4785 #define INT_EQUAL_QUERY(s1, s2, user) \
4786 if (s1 != s2) { \
4787 printf("%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
4788 #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
4789 ret = false; \
4792 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4793 struct samr_QueryDisplayInfo *querydisplayinfo,
4794 bool *seen_testuser)
4796 struct samr_OpenUser r;
4797 struct samr_QueryUserInfo q;
4798 union samr_UserInfo *info;
4799 struct policy_handle user_handle;
4800 int i, ret = true;
4801 NTSTATUS status;
4802 r.in.domain_handle = querydisplayinfo->in.domain_handle;
4803 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4804 for (i = 0; ; i++) {
4805 switch (querydisplayinfo->in.level) {
4806 case 1:
4807 if (i >= querydisplayinfo->out.info->info1.count) {
4808 return ret;
4810 r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
4811 break;
4812 case 2:
4813 if (i >= querydisplayinfo->out.info->info2.count) {
4814 return ret;
4816 r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
4817 break;
4818 case 3:
4819 /* Groups */
4820 case 4:
4821 case 5:
4822 /* Not interested in validating just the account name */
4823 return true;
4826 r.out.user_handle = &user_handle;
4828 switch (querydisplayinfo->in.level) {
4829 case 1:
4830 case 2:
4831 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
4832 if (!NT_STATUS_IS_OK(status)) {
4833 printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
4834 return false;
4838 q.in.user_handle = &user_handle;
4839 q.in.level = 21;
4840 q.out.info = &info;
4841 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
4842 if (!NT_STATUS_IS_OK(status)) {
4843 printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
4844 return false;
4847 switch (querydisplayinfo->in.level) {
4848 case 1:
4849 if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
4850 *seen_testuser = true;
4852 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
4853 info->info21.full_name, info->info21.account_name);
4854 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
4855 info->info21.account_name, info->info21.account_name);
4856 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
4857 info->info21.description, info->info21.account_name);
4858 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
4859 info->info21.rid, info->info21.account_name);
4860 INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
4861 info->info21.acct_flags, info->info21.account_name);
4863 break;
4864 case 2:
4865 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
4866 info->info21.account_name, info->info21.account_name);
4867 STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
4868 info->info21.description, info->info21.account_name);
4869 INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
4870 info->info21.rid, info->info21.account_name);
4871 INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
4872 info->info21.acct_flags, info->info21.account_name);
4874 if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
4875 printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
4876 info->info21.account_name.string);
4879 if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
4880 printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
4881 info->info21.account_name.string,
4882 querydisplayinfo->out.info->info2.entries[i].acct_flags,
4883 info->info21.acct_flags);
4884 return false;
4887 break;
4890 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
4891 return false;
4894 return ret;
4897 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
4898 struct policy_handle *handle)
4900 NTSTATUS status;
4901 struct samr_QueryDisplayInfo r;
4902 struct samr_QueryDomainInfo dom_info;
4903 union samr_DomainInfo *info = NULL;
4904 bool ret = true;
4905 uint16_t levels[] = {1, 2, 3, 4, 5};
4906 int i;
4907 bool seen_testuser = false;
4908 uint32_t total_size;
4909 uint32_t returned_size;
4910 union samr_DispInfo disp_info;
4913 for (i=0;i<ARRAY_SIZE(levels);i++) {
4914 printf("Testing QueryDisplayInfo level %u\n", levels[i]);
4916 r.in.start_idx = 0;
4917 status = STATUS_MORE_ENTRIES;
4918 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
4919 r.in.domain_handle = handle;
4920 r.in.level = levels[i];
4921 r.in.max_entries = 2;
4922 r.in.buf_size = (uint32_t)-1;
4923 r.out.total_size = &total_size;
4924 r.out.returned_size = &returned_size;
4925 r.out.info = &disp_info;
4927 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
4928 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
4929 printf("QueryDisplayInfo level %u failed - %s\n",
4930 levels[i], nt_errstr(status));
4931 ret = false;
4933 switch (r.in.level) {
4934 case 1:
4935 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) {
4936 ret = false;
4938 r.in.start_idx += r.out.info->info1.count;
4939 break;
4940 case 2:
4941 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) {
4942 ret = false;
4944 r.in.start_idx += r.out.info->info2.count;
4945 break;
4946 case 3:
4947 r.in.start_idx += r.out.info->info3.count;
4948 break;
4949 case 4:
4950 r.in.start_idx += r.out.info->info4.count;
4951 break;
4952 case 5:
4953 r.in.start_idx += r.out.info->info5.count;
4954 break;
4957 dom_info.in.domain_handle = handle;
4958 dom_info.in.level = 2;
4959 dom_info.out.info = &info;
4961 /* Check number of users returned is correct */
4962 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info);
4963 if (!NT_STATUS_IS_OK(status)) {
4964 printf("QueryDomainInfo level %u failed - %s\n",
4965 r.in.level, nt_errstr(status));
4966 ret = false;
4967 break;
4969 switch (r.in.level) {
4970 case 1:
4971 case 4:
4972 if (info->general.num_users < r.in.start_idx) {
4973 printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
4974 r.in.start_idx, info->general.num_groups,
4975 info->general.domain_name.string);
4976 ret = false;
4978 if (!seen_testuser) {
4979 struct policy_handle user_handle;
4980 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
4981 printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
4982 info->general.domain_name.string);
4983 ret = false;
4984 test_samr_handle_Close(p, mem_ctx, &user_handle);
4987 break;
4988 case 3:
4989 case 5:
4990 if (info->general.num_groups != r.in.start_idx) {
4991 printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
4992 r.in.start_idx, info->general.num_groups,
4993 info->general.domain_name.string);
4994 ret = false;
4997 break;
5002 return ret;
5005 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
5006 struct policy_handle *handle)
5008 NTSTATUS status;
5009 struct samr_QueryDisplayInfo2 r;
5010 bool ret = true;
5011 uint16_t levels[] = {1, 2, 3, 4, 5};
5012 int i;
5013 uint32_t total_size;
5014 uint32_t returned_size;
5015 union samr_DispInfo info;
5017 for (i=0;i<ARRAY_SIZE(levels);i++) {
5018 printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
5020 r.in.domain_handle = handle;
5021 r.in.level = levels[i];
5022 r.in.start_idx = 0;
5023 r.in.max_entries = 1000;
5024 r.in.buf_size = (uint32_t)-1;
5025 r.out.total_size = &total_size;
5026 r.out.returned_size = &returned_size;
5027 r.out.info = &info;
5029 status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
5030 if (!NT_STATUS_IS_OK(status)) {
5031 printf("QueryDisplayInfo2 level %u failed - %s\n",
5032 levels[i], nt_errstr(status));
5033 ret = false;
5037 return ret;
5040 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
5041 struct policy_handle *handle)
5043 NTSTATUS status;
5044 struct samr_QueryDisplayInfo3 r;
5045 bool ret = true;
5046 uint16_t levels[] = {1, 2, 3, 4, 5};
5047 int i;
5048 uint32_t total_size;
5049 uint32_t returned_size;
5050 union samr_DispInfo info;
5052 for (i=0;i<ARRAY_SIZE(levels);i++) {
5053 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
5055 r.in.domain_handle = handle;
5056 r.in.level = levels[i];
5057 r.in.start_idx = 0;
5058 r.in.max_entries = 1000;
5059 r.in.buf_size = (uint32_t)-1;
5060 r.out.total_size = &total_size;
5061 r.out.returned_size = &returned_size;
5062 r.out.info = &info;
5064 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
5065 if (!NT_STATUS_IS_OK(status)) {
5066 printf("QueryDisplayInfo3 level %u failed - %s\n",
5067 levels[i], nt_errstr(status));
5068 ret = false;
5072 return ret;
5076 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
5077 struct policy_handle *handle)
5079 NTSTATUS status;
5080 struct samr_QueryDisplayInfo r;
5081 bool ret = true;
5082 uint32_t total_size;
5083 uint32_t returned_size;
5084 union samr_DispInfo info;
5086 printf("Testing QueryDisplayInfo continuation\n");
5088 r.in.domain_handle = handle;
5089 r.in.level = 1;
5090 r.in.start_idx = 0;
5091 r.in.max_entries = 1;
5092 r.in.buf_size = (uint32_t)-1;
5093 r.out.total_size = &total_size;
5094 r.out.returned_size = &returned_size;
5095 r.out.info = &info;
5097 do {
5098 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
5099 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
5100 if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
5101 printf("expected idx %d but got %d\n",
5102 r.in.start_idx + 1,
5103 r.out.info->info1.entries[0].idx);
5104 break;
5107 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5108 !NT_STATUS_IS_OK(status)) {
5109 printf("QueryDisplayInfo level %u failed - %s\n",
5110 r.in.level, nt_errstr(status));
5111 ret = false;
5112 break;
5114 r.in.start_idx++;
5115 } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
5116 NT_STATUS_IS_OK(status)) &&
5117 *r.out.returned_size != 0);
5119 return ret;
5122 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
5123 struct policy_handle *handle)
5125 NTSTATUS status;
5126 struct samr_QueryDomainInfo r;
5127 union samr_DomainInfo *info = NULL;
5128 struct samr_SetDomainInfo s;
5129 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5130 uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0};
5131 int i;
5132 bool ret = true;
5133 const char *domain_comment = talloc_asprintf(tctx,
5134 "Tortured by Samba4 RPC-SAMR: %s",
5135 timestring(tctx, time(NULL)));
5137 s.in.domain_handle = handle;
5138 s.in.level = 4;
5139 s.in.info = talloc(tctx, union samr_DomainInfo);
5141 s.in.info->oem.oem_information.string = domain_comment;
5142 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5143 if (!NT_STATUS_IS_OK(status)) {
5144 printf("SetDomainInfo level %u (set comment) failed - %s\n",
5145 r.in.level, nt_errstr(status));
5146 return false;
5149 for (i=0;i<ARRAY_SIZE(levels);i++) {
5150 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
5152 r.in.domain_handle = handle;
5153 r.in.level = levels[i];
5154 r.out.info = &info;
5156 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 printf("QueryDomainInfo level %u failed - %s\n",
5159 r.in.level, nt_errstr(status));
5160 ret = false;
5161 continue;
5164 switch (levels[i]) {
5165 case 2:
5166 if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
5167 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5168 levels[i], info->general.oem_information.string, domain_comment);
5169 ret = false;
5171 if (!info->general.primary.string) {
5172 printf("QueryDomainInfo level %u returned no PDC name\n",
5173 levels[i]);
5174 ret = false;
5175 } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
5176 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
5177 printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
5178 levels[i], info->general.primary.string, dcerpc_server_name(p));
5181 break;
5182 case 4:
5183 if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
5184 printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
5185 levels[i], info->oem.oem_information.string, domain_comment);
5186 ret = false;
5188 break;
5189 case 6:
5190 if (!info->info6.primary.string) {
5191 printf("QueryDomainInfo level %u returned no PDC name\n",
5192 levels[i]);
5193 ret = false;
5195 break;
5196 case 11:
5197 if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
5198 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
5199 levels[i], info->general2.general.oem_information.string, domain_comment);
5200 ret = false;
5202 break;
5205 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
5207 s.in.domain_handle = handle;
5208 s.in.level = levels[i];
5209 s.in.info = info;
5211 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5212 if (set_ok[i]) {
5213 if (!NT_STATUS_IS_OK(status)) {
5214 printf("SetDomainInfo level %u failed - %s\n",
5215 r.in.level, nt_errstr(status));
5216 ret = false;
5217 continue;
5219 } else {
5220 if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5221 printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5222 r.in.level, nt_errstr(status));
5223 ret = false;
5224 continue;
5228 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5229 if (!NT_STATUS_IS_OK(status)) {
5230 printf("QueryDomainInfo level %u failed - %s\n",
5231 r.in.level, nt_errstr(status));
5232 ret = false;
5233 continue;
5237 return ret;
5241 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
5242 struct policy_handle *handle)
5244 NTSTATUS status;
5245 struct samr_QueryDomainInfo2 r;
5246 union samr_DomainInfo *info = NULL;
5247 uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
5248 int i;
5249 bool ret = true;
5251 for (i=0;i<ARRAY_SIZE(levels);i++) {
5252 printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
5254 r.in.domain_handle = handle;
5255 r.in.level = levels[i];
5256 r.out.info = &info;
5258 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
5259 if (!NT_STATUS_IS_OK(status)) {
5260 printf("QueryDomainInfo2 level %u failed - %s\n",
5261 r.in.level, nt_errstr(status));
5262 ret = false;
5263 continue;
5267 return true;
5270 /* Test whether querydispinfo level 5 and enumdomgroups return the same
5271 set of group names. */
5272 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
5273 struct policy_handle *handle)
5275 struct samr_EnumDomainGroups q1;
5276 struct samr_QueryDisplayInfo q2;
5277 NTSTATUS status;
5278 uint32_t resume_handle=0;
5279 struct samr_SamArray *sam = NULL;
5280 uint32_t num_entries = 0;
5281 int i;
5282 bool ret = true;
5283 uint32_t total_size;
5284 uint32_t returned_size;
5285 union samr_DispInfo info;
5287 int num_names = 0;
5288 const char **names = NULL;
5290 torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
5292 q1.in.domain_handle = handle;
5293 q1.in.resume_handle = &resume_handle;
5294 q1.in.max_size = 5;
5295 q1.out.resume_handle = &resume_handle;
5296 q1.out.num_entries = &num_entries;
5297 q1.out.sam = &sam;
5299 status = STATUS_MORE_ENTRIES;
5300 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5301 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
5303 if (!NT_STATUS_IS_OK(status) &&
5304 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5305 break;
5307 for (i=0; i<*q1.out.num_entries; i++) {
5308 add_string_to_array(tctx,
5309 sam->entries[i].name.string,
5310 &names, &num_names);
5314 torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
5316 torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
5318 q2.in.domain_handle = handle;
5319 q2.in.level = 5;
5320 q2.in.start_idx = 0;
5321 q2.in.max_entries = 5;
5322 q2.in.buf_size = (uint32_t)-1;
5323 q2.out.total_size = &total_size;
5324 q2.out.returned_size = &returned_size;
5325 q2.out.info = &info;
5327 status = STATUS_MORE_ENTRIES;
5328 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
5329 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
5331 if (!NT_STATUS_IS_OK(status) &&
5332 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
5333 break;
5335 for (i=0; i<q2.out.info->info5.count; i++) {
5336 int j;
5337 const char *name = q2.out.info->info5.entries[i].account_name.string;
5338 bool found = false;
5339 for (j=0; j<num_names; j++) {
5340 if (names[j] == NULL)
5341 continue;
5342 if (strequal(names[j], name)) {
5343 names[j] = NULL;
5344 found = true;
5345 break;
5349 if (!found) {
5350 printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
5351 name);
5352 ret = false;
5355 q2.in.start_idx += q2.out.info->info5.count;
5358 if (!NT_STATUS_IS_OK(status)) {
5359 printf("QueryDisplayInfo level 5 failed - %s\n",
5360 nt_errstr(status));
5361 ret = false;
5364 for (i=0; i<num_names; i++) {
5365 if (names[i] != NULL) {
5366 printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
5367 names[i]);
5368 ret = false;
5372 return ret;
5375 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
5376 struct policy_handle *group_handle)
5378 struct samr_DeleteDomainGroup d;
5379 NTSTATUS status;
5381 torture_comment(tctx, "Testing DeleteDomainGroup\n");
5383 d.in.group_handle = group_handle;
5384 d.out.group_handle = group_handle;
5386 status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
5387 torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
5389 return true;
5392 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5393 struct policy_handle *domain_handle)
5395 struct samr_TestPrivateFunctionsDomain r;
5396 NTSTATUS status;
5397 bool ret = true;
5399 torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
5401 r.in.domain_handle = domain_handle;
5403 status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
5404 torture_assert_ntstatus_equal(tctx, NT_STATUS_NOT_IMPLEMENTED, status, "TestPrivateFunctionsDomain");
5406 return ret;
5409 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
5410 struct dom_sid *domain_sid,
5411 struct policy_handle *domain_handle)
5413 struct samr_RidToSid r;
5414 NTSTATUS status;
5415 bool ret = true;
5416 struct dom_sid *calc_sid, *out_sid;
5417 int rids[] = { 0, 42, 512, 10200 };
5418 int i;
5420 for (i=0;i<ARRAY_SIZE(rids);i++) {
5421 torture_comment(tctx, "Testing RidToSid\n");
5423 calc_sid = dom_sid_dup(tctx, domain_sid);
5424 r.in.domain_handle = domain_handle;
5425 r.in.rid = rids[i];
5426 r.out.sid = &out_sid;
5428 status = dcerpc_samr_RidToSid(p, tctx, &r);
5429 if (!NT_STATUS_IS_OK(status)) {
5430 printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
5431 ret = false;
5432 } else {
5433 calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
5435 if (!dom_sid_equal(calc_sid, out_sid)) {
5436 printf("RidToSid for %d failed - got %s, expected %s\n", rids[i],
5437 dom_sid_string(tctx, out_sid),
5438 dom_sid_string(tctx, calc_sid));
5439 ret = false;
5444 return ret;
5447 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
5448 struct policy_handle *domain_handle)
5450 struct samr_GetBootKeyInformation r;
5451 NTSTATUS status;
5452 bool ret = true;
5453 uint32_t unknown = 0;
5455 torture_comment(tctx, "Testing GetBootKeyInformation\n");
5457 r.in.domain_handle = domain_handle;
5458 r.out.unknown = &unknown;
5460 status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 /* w2k3 seems to fail this sometimes and pass it sometimes */
5463 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
5466 return ret;
5469 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
5470 struct policy_handle *domain_handle,
5471 struct policy_handle *group_handle)
5473 NTSTATUS status;
5474 struct samr_AddGroupMember r;
5475 struct samr_DeleteGroupMember d;
5476 struct samr_QueryGroupMember q;
5477 struct samr_RidTypeArray *rids = NULL;
5478 struct samr_SetMemberAttributesOfGroup s;
5479 uint32_t rid;
5481 status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
5482 torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
5484 r.in.group_handle = group_handle;
5485 r.in.rid = rid;
5486 r.in.flags = 0; /* ??? */
5488 torture_comment(tctx, "Testing AddGroupMember and DeleteGroupMember\n");
5490 d.in.group_handle = group_handle;
5491 d.in.rid = rid;
5493 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5494 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
5496 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5497 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5499 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5500 torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
5502 if (torture_setting_bool(tctx, "samba4", false)) {
5503 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba4\n");
5504 } else {
5505 /* this one is quite strange. I am using random inputs in the
5506 hope of triggering an error that might give us a clue */
5508 s.in.group_handle = group_handle;
5509 s.in.unknown1 = random();
5510 s.in.unknown2 = random();
5512 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
5513 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
5516 q.in.group_handle = group_handle;
5517 q.out.rids = &rids;
5519 status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
5520 torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
5522 status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
5523 torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
5525 status = dcerpc_samr_AddGroupMember(p, tctx, &r);
5526 torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
5528 return true;
5532 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
5533 struct torture_context *tctx,
5534 struct policy_handle *domain_handle,
5535 struct policy_handle *group_handle,
5536 struct dom_sid *domain_sid)
5538 NTSTATUS status;
5539 struct samr_CreateDomainGroup r;
5540 uint32_t rid;
5541 struct lsa_String name;
5542 bool ret = true;
5544 init_lsa_String(&name, TEST_GROUPNAME);
5546 r.in.domain_handle = domain_handle;
5547 r.in.name = &name;
5548 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5549 r.out.group_handle = group_handle;
5550 r.out.rid = &rid;
5552 printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
5554 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5556 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5557 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
5558 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
5559 return true;
5560 } else {
5561 printf("Server should have refused create of '%s', got %s instead\n", r.in.name->string,
5562 nt_errstr(status));
5563 return false;
5567 if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
5568 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
5569 printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
5570 nt_errstr(status));
5571 return false;
5573 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5575 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5576 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
5578 printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
5579 nt_errstr(status));
5580 return false;
5582 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
5584 torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
5586 if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
5587 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
5588 ret = false;
5591 if (!test_SetGroupInfo(p, tctx, group_handle)) {
5592 ret = false;
5595 return ret;
5600 its not totally clear what this does. It seems to accept any sid you like.
5602 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
5603 struct torture_context *tctx,
5604 struct policy_handle *domain_handle)
5606 NTSTATUS status;
5607 struct samr_RemoveMemberFromForeignDomain r;
5609 r.in.domain_handle = domain_handle;
5610 r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
5612 status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
5613 torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
5615 return true;
5620 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
5621 struct policy_handle *handle);
5623 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5624 struct policy_handle *handle, struct dom_sid *sid,
5625 enum torture_samr_choice which_ops,
5626 struct cli_credentials *machine_credentials)
5628 NTSTATUS status;
5629 struct samr_OpenDomain r;
5630 struct policy_handle domain_handle;
5631 struct policy_handle alias_handle;
5632 struct policy_handle user_handle;
5633 struct policy_handle group_handle;
5634 bool ret = true;
5636 ZERO_STRUCT(alias_handle);
5637 ZERO_STRUCT(user_handle);
5638 ZERO_STRUCT(group_handle);
5639 ZERO_STRUCT(domain_handle);
5641 torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
5643 r.in.connect_handle = handle;
5644 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5645 r.in.sid = sid;
5646 r.out.domain_handle = &domain_handle;
5648 status = dcerpc_samr_OpenDomain(p, tctx, &r);
5649 torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
5651 /* run the domain tests with the main handle closed - this tests
5652 the servers reference counting */
5653 ret &= test_samr_handle_Close(p, tctx, handle);
5655 switch (which_ops) {
5656 case TORTURE_SAMR_USER_ATTRIBUTES:
5657 case TORTURE_SAMR_PASSWORDS:
5658 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, NULL);
5659 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
5660 /* This test needs 'complex' users to validate */
5661 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
5662 if (!ret) {
5663 printf("Testing PASSWORDS or ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
5665 break;
5666 case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
5667 ret &= test_CreateUser2(p, tctx, &domain_handle, sid, which_ops, machine_credentials);
5668 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, machine_credentials);
5669 if (!ret) {
5670 printf("Testing PASSWORDS PWDLASTSET on domain %s failed!\n", dom_sid_string(tctx, sid));
5672 break;
5673 case TORTURE_SAMR_OTHER:
5674 ret &= test_CreateUser(p, tctx, &domain_handle, &user_handle, sid, which_ops, NULL);
5675 if (!ret) {
5676 printf("Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
5678 ret &= test_QuerySecurity(p, tctx, &domain_handle);
5679 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
5680 ret &= test_CreateAlias(p, tctx, &domain_handle, &alias_handle, sid);
5681 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, &group_handle, sid);
5682 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
5683 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
5684 ret &= test_EnumDomainUsers(p, tctx, &domain_handle);
5685 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
5686 ret &= test_EnumDomainGroups(p, tctx, &domain_handle);
5687 ret &= test_EnumDomainAliases(p, tctx, &domain_handle);
5688 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
5689 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
5690 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
5692 if (torture_setting_bool(tctx, "samba4", false)) {
5693 torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
5694 } else {
5695 ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
5696 ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
5698 ret &= test_GroupList(p, tctx, &domain_handle);
5699 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
5700 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
5701 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
5702 if (!ret) {
5703 torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
5705 break;
5708 if (!policy_handle_empty(&user_handle) &&
5709 !test_DeleteUser(p, tctx, &user_handle)) {
5710 ret = false;
5713 if (!policy_handle_empty(&alias_handle) &&
5714 !test_DeleteAlias(p, tctx, &alias_handle)) {
5715 ret = false;
5718 if (!policy_handle_empty(&group_handle) &&
5719 !test_DeleteDomainGroup(p, tctx, &group_handle)) {
5720 ret = false;
5723 ret &= test_samr_handle_Close(p, tctx, &domain_handle);
5725 /* reconnect the main handle */
5726 ret &= test_Connect(p, tctx, handle);
5728 if (!ret) {
5729 printf("Testing domain %s failed!\n", dom_sid_string(tctx, sid));
5732 return ret;
5735 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
5736 struct policy_handle *handle, const char *domain,
5737 enum torture_samr_choice which_ops,
5738 struct cli_credentials *machine_credentials)
5740 NTSTATUS status;
5741 struct samr_LookupDomain r;
5742 struct dom_sid2 *sid = NULL;
5743 struct lsa_String n1;
5744 struct lsa_String n2;
5745 bool ret = true;
5747 torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
5749 /* check for correct error codes */
5750 r.in.connect_handle = handle;
5751 r.in.domain_name = &n2;
5752 r.out.sid = &sid;
5753 n2.string = NULL;
5755 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5756 torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
5758 init_lsa_String(&n2, "xxNODOMAINxx");
5760 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5761 torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
5763 r.in.connect_handle = handle;
5765 init_lsa_String(&n1, domain);
5766 r.in.domain_name = &n1;
5768 status = dcerpc_samr_LookupDomain(p, tctx, &r);
5769 torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
5771 if (!test_GetDomPwInfo(p, tctx, &n1)) {
5772 ret = false;
5775 if (!test_OpenDomain(p, tctx, handle, *r.out.sid, which_ops,
5776 machine_credentials)) {
5777 ret = false;
5780 return ret;
5784 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
5785 struct policy_handle *handle, enum torture_samr_choice which_ops,
5786 struct cli_credentials *machine_credentials)
5788 NTSTATUS status;
5789 struct samr_EnumDomains r;
5790 uint32_t resume_handle = 0;
5791 uint32_t num_entries = 0;
5792 struct samr_SamArray *sam = NULL;
5793 int i;
5794 bool ret = true;
5796 r.in.connect_handle = handle;
5797 r.in.resume_handle = &resume_handle;
5798 r.in.buf_size = (uint32_t)-1;
5799 r.out.resume_handle = &resume_handle;
5800 r.out.num_entries = &num_entries;
5801 r.out.sam = &sam;
5803 status = dcerpc_samr_EnumDomains(p, tctx, &r);
5804 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
5806 if (!*r.out.sam) {
5807 return false;
5810 for (i=0;i<sam->count;i++) {
5811 if (!test_LookupDomain(p, tctx, handle,
5812 sam->entries[i].name.string, which_ops,
5813 machine_credentials)) {
5814 ret = false;
5818 status = dcerpc_samr_EnumDomains(p, tctx, &r);
5819 torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
5821 return ret;
5825 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
5826 struct policy_handle *handle)
5828 NTSTATUS status;
5829 struct samr_Connect r;
5830 struct samr_Connect2 r2;
5831 struct samr_Connect3 r3;
5832 struct samr_Connect4 r4;
5833 struct samr_Connect5 r5;
5834 union samr_ConnectInfo info;
5835 struct policy_handle h;
5836 uint32_t level_out = 0;
5837 bool ret = true, got_handle = false;
5839 torture_comment(tctx, "testing samr_Connect\n");
5841 r.in.system_name = 0;
5842 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5843 r.out.connect_handle = &h;
5845 status = dcerpc_samr_Connect(p, tctx, &r);
5846 if (!NT_STATUS_IS_OK(status)) {
5847 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
5848 ret = false;
5849 } else {
5850 got_handle = true;
5851 *handle = h;
5854 torture_comment(tctx, "testing samr_Connect2\n");
5856 r2.in.system_name = NULL;
5857 r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5858 r2.out.connect_handle = &h;
5860 status = dcerpc_samr_Connect2(p, tctx, &r2);
5861 if (!NT_STATUS_IS_OK(status)) {
5862 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
5863 ret = false;
5864 } else {
5865 if (got_handle) {
5866 test_samr_handle_Close(p, tctx, handle);
5868 got_handle = true;
5869 *handle = h;
5872 torture_comment(tctx, "testing samr_Connect3\n");
5874 r3.in.system_name = NULL;
5875 r3.in.unknown = 0;
5876 r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5877 r3.out.connect_handle = &h;
5879 status = dcerpc_samr_Connect3(p, tctx, &r3);
5880 if (!NT_STATUS_IS_OK(status)) {
5881 printf("Connect3 failed - %s\n", nt_errstr(status));
5882 ret = false;
5883 } else {
5884 if (got_handle) {
5885 test_samr_handle_Close(p, tctx, handle);
5887 got_handle = true;
5888 *handle = h;
5891 torture_comment(tctx, "testing samr_Connect4\n");
5893 r4.in.system_name = "";
5894 r4.in.client_version = 0;
5895 r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5896 r4.out.connect_handle = &h;
5898 status = dcerpc_samr_Connect4(p, tctx, &r4);
5899 if (!NT_STATUS_IS_OK(status)) {
5900 printf("Connect4 failed - %s\n", nt_errstr(status));
5901 ret = false;
5902 } else {
5903 if (got_handle) {
5904 test_samr_handle_Close(p, tctx, handle);
5906 got_handle = true;
5907 *handle = h;
5910 torture_comment(tctx, "testing samr_Connect5\n");
5912 info.info1.client_version = 0;
5913 info.info1.unknown2 = 0;
5915 r5.in.system_name = "";
5916 r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5917 r5.in.level_in = 1;
5918 r5.out.level_out = &level_out;
5919 r5.in.info_in = &info;
5920 r5.out.info_out = &info;
5921 r5.out.connect_handle = &h;
5923 status = dcerpc_samr_Connect5(p, tctx, &r5);
5924 if (!NT_STATUS_IS_OK(status)) {
5925 printf("Connect5 failed - %s\n", nt_errstr(status));
5926 ret = false;
5927 } else {
5928 if (got_handle) {
5929 test_samr_handle_Close(p, tctx, handle);
5931 got_handle = true;
5932 *handle = h;
5935 return ret;
5939 bool torture_rpc_samr(struct torture_context *torture)
5941 NTSTATUS status;
5942 struct dcerpc_pipe *p;
5943 bool ret = true;
5944 struct policy_handle handle;
5946 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
5947 if (!NT_STATUS_IS_OK(status)) {
5948 return false;
5951 ret &= test_Connect(p, torture, &handle);
5953 ret &= test_QuerySecurity(p, torture, &handle);
5955 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER, NULL);
5957 ret &= test_SetDsrmPassword(p, torture, &handle);
5959 ret &= test_Shutdown(p, torture, &handle);
5961 ret &= test_samr_handle_Close(p, torture, &handle);
5963 return ret;
5967 bool torture_rpc_samr_users(struct torture_context *torture)
5969 NTSTATUS status;
5970 struct dcerpc_pipe *p;
5971 bool ret = true;
5972 struct policy_handle handle;
5974 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 return false;
5979 ret &= test_Connect(p, torture, &handle);
5981 ret &= test_QuerySecurity(p, torture, &handle);
5983 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES, NULL);
5985 ret &= test_SetDsrmPassword(p, torture, &handle);
5987 ret &= test_Shutdown(p, torture, &handle);
5989 ret &= test_samr_handle_Close(p, torture, &handle);
5991 return ret;
5995 bool torture_rpc_samr_passwords(struct torture_context *torture)
5997 NTSTATUS status;
5998 struct dcerpc_pipe *p;
5999 bool ret = true;
6000 struct policy_handle handle;
6002 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6003 if (!NT_STATUS_IS_OK(status)) {
6004 return false;
6007 ret &= test_Connect(p, torture, &handle);
6009 ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS, NULL);
6011 ret &= test_samr_handle_Close(p, torture, &handle);
6013 return ret;
6016 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
6017 struct dcerpc_pipe *p2,
6018 struct cli_credentials *machine_credentials)
6020 NTSTATUS status;
6021 struct dcerpc_pipe *p;
6022 bool ret = true;
6023 struct policy_handle handle;
6025 status = torture_rpc_connection(torture, &p, &ndr_table_samr);
6026 if (!NT_STATUS_IS_OK(status)) {
6027 return false;
6030 ret &= test_Connect(p, torture, &handle);
6032 ret &= test_EnumDomains(p, torture, &handle,
6033 TORTURE_SAMR_PASSWORDS_PWDLASTSET,
6034 machine_credentials);
6036 ret &= test_samr_handle_Close(p, torture, &handle);
6038 return ret;
6041 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
6043 struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
6044 struct torture_rpc_tcase *tcase;
6046 tcase = torture_suite_add_machine_rpc_iface_tcase(suite, "samr",
6047 &ndr_table_samr,
6048 TEST_ACCOUNT_NAME_PWD);
6050 torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
6051 torture_rpc_samr_pwdlastset);
6053 return suite;