s4:torture/rpc/samr.c - test_SetPassword_LastSet - fix "pwdLastSet" test
[samba.git] / source4 / torture / rpc / samr.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for samr rpc operations
4
5    Copyright (C) Andrew Tridgell 2003
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7    Copyright (C) Guenther Deschner 2008-2010
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include <tevent.h>
26 #include "system/time.h"
27 #include "librpc/gen_ndr/lsa.h"
28 #include "librpc/gen_ndr/ndr_netlogon.h"
29 #include "librpc/gen_ndr/ndr_netlogon_c.h"
30 #include "librpc/gen_ndr/ndr_samr_c.h"
31 #include "librpc/gen_ndr/ndr_lsa_c.h"
32 #include "../lib/crypto/crypto.h"
33 #include "libcli/auth/libcli_auth.h"
34 #include "libcli/security/security.h"
35 #include "torture/rpc/torture_rpc.h"
36 #include "param/param.h"
37 #include "auth/gensec/gensec.h"
38 #include "auth/gensec/gensec_proto.h"
39 #include "../libcli/auth/schannel.h"
40
41 #include <unistd.h>
42
43 #define TEST_ACCOUNT_NAME "samrtorturetest"
44 #define TEST_ACCOUNT_NAME_PWD "samrpwdlastset"
45 #define TEST_ALIASNAME "samrtorturetestalias"
46 #define TEST_GROUPNAME "samrtorturetestgroup"
47 #define TEST_MACHINENAME "samrtestmach$"
48 #define TEST_DOMAINNAME "samrtestdom$"
49
50 enum torture_samr_choice {
51         TORTURE_SAMR_PASSWORDS,
52         TORTURE_SAMR_PASSWORDS_PWDLASTSET,
53         TORTURE_SAMR_PASSWORDS_BADPWDCOUNT,
54         TORTURE_SAMR_PASSWORDS_LOCKOUT,
55         TORTURE_SAMR_USER_ATTRIBUTES,
56         TORTURE_SAMR_USER_PRIVILEGES,
57         TORTURE_SAMR_OTHER,
58         TORTURE_SAMR_MANY_ACCOUNTS,
59         TORTURE_SAMR_MANY_GROUPS,
60         TORTURE_SAMR_MANY_ALIASES
61 };
62
63 struct torture_samr_context {
64         struct policy_handle handle;
65         struct cli_credentials *machine_credentials;
66         enum torture_samr_choice choice;
67         uint32_t num_objects_large_dc;
68 };
69
70 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
71                                struct torture_context *tctx,
72                                struct policy_handle *handle);
73
74 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
75                                 struct torture_context *tctx,
76                                 struct policy_handle *handle);
77
78 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
79                                 struct torture_context *tctx,
80                                 struct policy_handle *handle);
81
82 static bool test_ChangePassword(struct dcerpc_pipe *p,
83                                 struct torture_context *tctx,
84                                 const char *acct_name,
85                                 struct policy_handle *domain_handle, char **password);
86
87 static void init_lsa_String(struct lsa_String *string, const char *s)
88 {
89         string->string = s;
90 }
91
92 static void init_lsa_StringLarge(struct lsa_StringLarge *string, const char *s)
93 {
94         string->string = s;
95 }
96
97 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
98 {
99         string->length = length;
100         string->size = length;
101         string->array = (uint16_t *)discard_const(s);
102 }
103
104 bool test_samr_handle_Close(struct dcerpc_binding_handle *b,
105                             struct torture_context *tctx,
106                             struct policy_handle *handle)
107 {
108         struct samr_Close r;
109
110         r.in.handle = handle;
111         r.out.handle = handle;
112
113         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Close_r(b, tctx, &r),
114                 "Close failed");
115         torture_assert_ntstatus_ok(tctx, r.out.result, "Close failed");
116
117         return true;
118 }
119
120 static bool test_Shutdown(struct dcerpc_binding_handle *b,
121                           struct torture_context *tctx,
122                           struct policy_handle *handle)
123 {
124         struct samr_Shutdown r;
125
126         if (!torture_setting_bool(tctx, "dangerous", false)) {
127                 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
128                 return true;
129         }
130
131         r.in.connect_handle = handle;
132
133         torture_comment(tctx, "Testing samr_Shutdown\n");
134
135         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Shutdown_r(b, tctx, &r),
136                 "Shutdown failed");
137         torture_assert_ntstatus_ok(tctx, r.out.result, "Shutdown failed");
138
139         return true;
140 }
141
142 static bool test_SetDsrmPassword(struct dcerpc_binding_handle *b,
143                                  struct torture_context *tctx,
144                                  struct policy_handle *handle)
145 {
146         struct samr_SetDsrmPassword r;
147         struct lsa_String string;
148         struct samr_Password hash;
149
150         if (!torture_setting_bool(tctx, "dangerous", false)) {
151                 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
152         }
153
154         E_md4hash("TeSTDSRM123", hash.hash);
155
156         init_lsa_String(&string, "Administrator");
157
158         r.in.name = &string;
159         r.in.unknown = 0;
160         r.in.hash = &hash;
161
162         torture_comment(tctx, "Testing samr_SetDsrmPassword\n");
163
164         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDsrmPassword_r(b, tctx, &r),
165                 "SetDsrmPassword failed");
166         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_SUPPORTED, "SetDsrmPassword failed");
167
168         return true;
169 }
170
171
172 static bool test_QuerySecurity(struct dcerpc_binding_handle *b,
173                                struct torture_context *tctx,
174                                struct policy_handle *handle)
175 {
176         struct samr_QuerySecurity r;
177         struct samr_SetSecurity s;
178         struct sec_desc_buf *sdbuf = NULL;
179
180         r.in.handle = handle;
181         r.in.sec_info = 7;
182         r.out.sdbuf = &sdbuf;
183
184         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
185                 "QuerySecurity failed");
186         torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
187
188         torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
189
190         s.in.handle = handle;
191         s.in.sec_info = 7;
192         s.in.sdbuf = sdbuf;
193
194         if (torture_setting_bool(tctx, "samba4", false)) {
195                 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
196         }
197
198         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetSecurity_r(b, tctx, &s),
199                 "SetSecurity failed");
200         torture_assert_ntstatus_ok(tctx, r.out.result, "SetSecurity failed");
201
202         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QuerySecurity_r(b, tctx, &r),
203                 "QuerySecurity failed");
204         torture_assert_ntstatus_ok(tctx, r.out.result, "QuerySecurity failed");
205
206         return true;
207 }
208
209
210 static bool test_SetUserInfo(struct dcerpc_binding_handle *b, struct torture_context *tctx,
211                              struct policy_handle *handle, uint32_t base_acct_flags,
212                              const char *base_account_name)
213 {
214         struct samr_SetUserInfo s;
215         struct samr_SetUserInfo2 s2;
216         struct samr_QueryUserInfo q;
217         struct samr_QueryUserInfo q0;
218         union samr_UserInfo u;
219         union samr_UserInfo *info;
220         bool ret = true;
221         const char *test_account_name;
222
223         uint32_t user_extra_flags = 0;
224
225         if (!torture_setting_bool(tctx, "samba3", false)) {
226                 if (base_acct_flags == ACB_NORMAL) {
227                         /* When created, accounts are expired by default */
228                         user_extra_flags = ACB_PW_EXPIRED;
229                 }
230         }
231
232         s.in.user_handle = handle;
233         s.in.info = &u;
234
235         s2.in.user_handle = handle;
236         s2.in.info = &u;
237
238         q.in.user_handle = handle;
239         q.out.info = &info;
240         q0 = q;
241
242 #define TESTCALL(call, r) \
243                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ ##call## _r(b, tctx, &r),\
244                         #call " failed"); \
245                 if (!NT_STATUS_IS_OK(r.out.result)) { \
246                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
247                                r.in.level, nt_errstr(r.out.result), __location__); \
248                         ret = false; \
249                         break; \
250                 }
251
252 #define STRING_EQUAL(s1, s2, field) \
253                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
254                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
255                                #field, s2, __location__); \
256                         ret = false; \
257                         break; \
258                 }
259
260 #define MEM_EQUAL(s1, s2, length, field) \
261                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
262                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
263                                #field, (const char *)s2, __location__); \
264                         ret = false; \
265                         break; \
266                 }
267
268 #define INT_EQUAL(i1, i2, field) \
269                 if (i1 != i2) { \
270                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
271                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
272                         ret = false; \
273                         break; \
274                 }
275
276 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
277                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
278                 q.in.level = lvl1; \
279                 TESTCALL(QueryUserInfo, q) \
280                 s.in.level = lvl1; \
281                 s2.in.level = lvl1; \
282                 u = *info; \
283                 if (lvl1 == 21) { \
284                         ZERO_STRUCT(u.info21); \
285                         u.info21.fields_present = fpval; \
286                 } \
287                 init_lsa_String(&u.info ## lvl1.field1, value); \
288                 TESTCALL(SetUserInfo, s) \
289                 TESTCALL(SetUserInfo2, s2) \
290                 init_lsa_String(&u.info ## lvl1.field1, ""); \
291                 TESTCALL(QueryUserInfo, q); \
292                 u = *info; \
293                 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
294                 q.in.level = lvl2; \
295                 TESTCALL(QueryUserInfo, q) \
296                 u = *info; \
297                 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
298         } while (0)
299
300 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
301                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
302                 q.in.level = lvl1; \
303                 TESTCALL(QueryUserInfo, q) \
304                 s.in.level = lvl1; \
305                 s2.in.level = lvl1; \
306                 u = *info; \
307                 if (lvl1 == 21) { \
308                         ZERO_STRUCT(u.info21); \
309                         u.info21.fields_present = fpval; \
310                 } \
311                 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
312                 TESTCALL(SetUserInfo, s) \
313                 TESTCALL(SetUserInfo2, s2) \
314                 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
315                 TESTCALL(QueryUserInfo, q); \
316                 u = *info; \
317                 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
318                 q.in.level = lvl2; \
319                 TESTCALL(QueryUserInfo, q) \
320                 u = *info; \
321                 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
322         } while (0)
323
324 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
325                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
326                 q.in.level = lvl1; \
327                 TESTCALL(QueryUserInfo, q) \
328                 s.in.level = lvl1; \
329                 s2.in.level = lvl1; \
330                 u = *info; \
331                 if (lvl1 == 21) { \
332                         uint8_t *bits = u.info21.logon_hours.bits; \
333                         ZERO_STRUCT(u.info21); \
334                         if (fpval == SAMR_FIELD_LOGON_HOURS) { \
335                                 u.info21.logon_hours.units_per_week = 168; \
336                                 u.info21.logon_hours.bits = bits; \
337                         } \
338                         u.info21.fields_present = fpval; \
339                 } \
340                 u.info ## lvl1.field1 = value; \
341                 TESTCALL(SetUserInfo, s) \
342                 TESTCALL(SetUserInfo2, s2) \
343                 u.info ## lvl1.field1 = 0; \
344                 TESTCALL(QueryUserInfo, q); \
345                 u = *info; \
346                 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
347                 q.in.level = lvl2; \
348                 TESTCALL(QueryUserInfo, q) \
349                 u = *info; \
350                 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
351         } while (0)
352
353 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
354         TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
355         } while (0)
356
357         q0.in.level = 12;
358         do { TESTCALL(QueryUserInfo, q0) } while (0);
359
360         TEST_USERINFO_STRING(2, comment,  1, comment, "xx2-1 comment", 0);
361         TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
362         TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment",
363                            SAMR_FIELD_COMMENT);
364
365         test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
366         TEST_USERINFO_STRING(7, account_name,  1, account_name, base_account_name, 0);
367         test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
368         TEST_USERINFO_STRING(7, account_name,  3, account_name, base_account_name, 0);
369         test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
370         TEST_USERINFO_STRING(7, account_name,  5, account_name, base_account_name, 0);
371         test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
372         TEST_USERINFO_STRING(7, account_name,  6, account_name, base_account_name, 0);
373         test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
374         TEST_USERINFO_STRING(7, account_name,  7, account_name, base_account_name, 0);
375         test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
376         TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
377         test_account_name = base_account_name;
378         TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name,
379                            SAMR_FIELD_ACCOUNT_NAME);
380
381         TEST_USERINFO_STRING(6, full_name,  1, full_name, "xx6-1 full_name", 0);
382         TEST_USERINFO_STRING(6, full_name,  3, full_name, "xx6-3 full_name", 0);
383         TEST_USERINFO_STRING(6, full_name,  5, full_name, "xx6-5 full_name", 0);
384         TEST_USERINFO_STRING(6, full_name,  6, full_name, "xx6-6 full_name", 0);
385         TEST_USERINFO_STRING(6, full_name,  8, full_name, "xx6-8 full_name", 0);
386         TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
387         TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
388         TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name",
389                            SAMR_FIELD_FULL_NAME);
390
391         TEST_USERINFO_STRING(6, full_name,  1, full_name, "", 0);
392         TEST_USERINFO_STRING(6, full_name,  3, full_name, "", 0);
393         TEST_USERINFO_STRING(6, full_name,  5, full_name, "", 0);
394         TEST_USERINFO_STRING(6, full_name,  6, full_name, "", 0);
395         TEST_USERINFO_STRING(6, full_name,  8, full_name, "", 0);
396         TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
397         TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
398         TEST_USERINFO_STRING(21, full_name, 21, full_name, "",
399                            SAMR_FIELD_FULL_NAME);
400
401         TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
402         TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
403         TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
404         TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script",
405                            SAMR_FIELD_LOGON_SCRIPT);
406
407         TEST_USERINFO_STRING(12, profile_path,  3, profile_path, "xx12-3 profile_path", 0);
408         TEST_USERINFO_STRING(12, profile_path,  5, profile_path, "xx12-5 profile_path", 0);
409         TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
410         TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path",
411                            SAMR_FIELD_PROFILE_PATH);
412
413         TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
414         TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
415         TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
416         TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
417                              SAMR_FIELD_HOME_DIRECTORY);
418         TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
419                              SAMR_FIELD_HOME_DIRECTORY);
420
421         TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
422         TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
423         TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
424         TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
425                              SAMR_FIELD_HOME_DRIVE);
426         TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
427                              SAMR_FIELD_HOME_DRIVE);
428
429         TEST_USERINFO_STRING(13, description,  1, description, "xx13-1 description", 0);
430         TEST_USERINFO_STRING(13, description,  5, description, "xx13-5 description", 0);
431         TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
432         TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description",
433                            SAMR_FIELD_DESCRIPTION);
434
435         TEST_USERINFO_STRING(14, workstations,  3, workstations, "14workstation3", 0);
436         TEST_USERINFO_STRING(14, workstations,  5, workstations, "14workstation4", 0);
437         TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
438         TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21",
439                            SAMR_FIELD_WORKSTATIONS);
440         TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3",
441                            SAMR_FIELD_WORKSTATIONS);
442         TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5",
443                            SAMR_FIELD_WORKSTATIONS);
444         TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14",
445                            SAMR_FIELD_WORKSTATIONS);
446
447         TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
448         TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
449                            SAMR_FIELD_PARAMETERS);
450         TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
451                            SAMR_FIELD_PARAMETERS);
452         /* also empty user parameters are allowed */
453         TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "", 0);
454         TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "",
455                            SAMR_FIELD_PARAMETERS);
456         TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "",
457                            SAMR_FIELD_PARAMETERS);
458
459         /* Samba 3 cannot store country_code and copy_page atm. - gd */
460         if (!torture_setting_bool(tctx, "samba3", false)) {
461                 TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
462                 TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
463                 TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__,
464                                   SAMR_FIELD_COUNTRY_CODE);
465                 TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__,
466                                   SAMR_FIELD_COUNTRY_CODE);
467
468                 TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
469                 TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__,
470                                   SAMR_FIELD_CODE_PAGE);
471                 TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__,
472                                   SAMR_FIELD_CODE_PAGE);
473         }
474
475         if (!torture_setting_bool(tctx, "samba3", false)) {
476                 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
477                 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
478                 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__,
479                                   SAMR_FIELD_ACCT_EXPIRY);
480                 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__,
481                                   SAMR_FIELD_ACCT_EXPIRY);
482                 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__,
483                                   SAMR_FIELD_ACCT_EXPIRY);
484         } else {
485                 /* Samba 3 can only store seconds / time_t in passdb - gd */
486                 NTTIME nt;
487                 unix_to_nt_time(&nt, time(NULL) + __LINE__);
488                 TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, nt, 0);
489                 unix_to_nt_time(&nt, time(NULL) + __LINE__);
490                 TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, nt, 0);
491                 unix_to_nt_time(&nt, time(NULL) + __LINE__);
492                 TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
493                 unix_to_nt_time(&nt, time(NULL) + __LINE__);
494                 TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
495                 unix_to_nt_time(&nt, time(NULL) + __LINE__);
496                 TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, nt, SAMR_FIELD_ACCT_EXPIRY);
497         }
498
499         TEST_USERINFO_INT(4, logon_hours.bits[3],  3, logon_hours.bits[3], 1, 0);
500         TEST_USERINFO_INT(4, logon_hours.bits[3],  5, logon_hours.bits[3], 2, 0);
501         TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
502         TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4,
503                           SAMR_FIELD_LOGON_HOURS);
504
505         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
506                               (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ),
507                               (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
508                               0);
509         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
510                               (base_acct_flags  | ACB_DISABLED),
511                               (base_acct_flags  | ACB_DISABLED | user_extra_flags),
512                               0);
513
514         /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
515         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags,
516                               (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP),
517                               (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP),
518                               0);
519         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
520                               (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ),
521                               (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags),
522                               0);
523
524
525         /* The 'autolock' flag doesn't stick - check this */
526         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
527                               (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK),
528                               (base_acct_flags | ACB_DISABLED | user_extra_flags),
529                               0);
530 #if 0
531         /* Removing the 'disabled' flag doesn't stick - check this */
532         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
533                               (base_acct_flags),
534                               (base_acct_flags | ACB_DISABLED | user_extra_flags),
535                               0);
536 #endif
537
538         /* Samba3 cannot store these atm */
539         if (!torture_setting_bool(tctx, "samba3", false)) {
540         /* The 'store plaintext' flag does stick */
541         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
542                               (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED),
543                               (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags),
544                               0);
545         /* The 'use DES' flag does stick */
546         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
547                               (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY),
548                               (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags),
549                               0);
550         /* The 'don't require kerberos pre-authentication flag does stick */
551         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
552                               (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH),
553                               (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags),
554                               0);
555         /* The 'no kerberos PAC required' flag sticks */
556         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags,
557                               (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD),
558                               (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags),
559                               0);
560         }
561         TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags,
562                               (base_acct_flags | ACB_DISABLED),
563                               (base_acct_flags | ACB_DISABLED | user_extra_flags),
564                               SAMR_FIELD_ACCT_FLAGS);
565
566 #if 0
567         /* these fail with win2003 - it appears you can't set the primary gid?
568            the set succeeds, but the gid isn't changed. Very weird! */
569         TEST_USERINFO_INT(9, primary_gid,  1, primary_gid, 513);
570         TEST_USERINFO_INT(9, primary_gid,  3, primary_gid, 513);
571         TEST_USERINFO_INT(9, primary_gid,  5, primary_gid, 513);
572         TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
573 #endif
574
575         return ret;
576 }
577
578 /*
579   generate a random password for password change tests
580 */
581 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
582 {
583         size_t len = MAX(8, min_len);
584         char *s = generate_random_password(mem_ctx, len, len+6);
585         return s;
586 }
587
588 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
589 {
590         char *s = samr_rand_pass_silent(mem_ctx, min_len);
591         printf("Generated password '%s'\n", s);
592         return s;
593
594 }
595
596 /*
597   generate a random password for password change tests
598 */
599 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
600 {
601         int i;
602         DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
603         generate_random_buffer(password.data, password.length);
604
605         for (i=0; i < len; i++) {
606                 if (((uint16_t *)password.data)[i] == 0) {
607                         ((uint16_t *)password.data)[i] = 1;
608                 }
609         }
610
611         return password;
612 }
613
614 /*
615   generate a random password for password change tests (fixed length)
616 */
617 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
618 {
619         char *s = generate_random_password(mem_ctx, len, len);
620         printf("Generated password '%s'\n", s);
621         return s;
622 }
623
624 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
625                              struct policy_handle *handle, char **password)
626 {
627         NTSTATUS status;
628         struct samr_SetUserInfo s;
629         union samr_UserInfo u;
630         bool ret = true;
631         DATA_BLOB session_key;
632         char *newpass;
633         struct dcerpc_binding_handle *b = p->binding_handle;
634         struct samr_GetUserPwInfo pwp;
635         struct samr_PwInfo info;
636         int policy_min_pw_len = 0;
637         pwp.in.user_handle = handle;
638         pwp.out.info = &info;
639
640         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
641                 "GetUserPwInfo failed");
642         if (NT_STATUS_IS_OK(pwp.out.result)) {
643                 policy_min_pw_len = pwp.out.info->min_password_length;
644         }
645         newpass = samr_rand_pass(tctx, policy_min_pw_len);
646
647         s.in.user_handle = handle;
648         s.in.info = &u;
649         s.in.level = 24;
650
651         encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
652         u.info24.password_expired = 0;
653
654         status = dcerpc_fetch_session_key(p, &session_key);
655         if (!NT_STATUS_IS_OK(status)) {
656                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
657                        s.in.level, nt_errstr(status));
658                 return false;
659         }
660
661         arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
662
663         torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
664
665         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
666                 "SetUserInfo failed");
667         if (!NT_STATUS_IS_OK(s.out.result)) {
668                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
669                        s.in.level, nt_errstr(s.out.result));
670                 ret = false;
671         } else {
672                 *password = newpass;
673         }
674
675         return ret;
676 }
677
678
679 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
680                                 struct policy_handle *handle, uint32_t fields_present,
681                                 char **password)
682 {
683         NTSTATUS status;
684         struct samr_SetUserInfo s;
685         union samr_UserInfo u;
686         bool ret = true;
687         DATA_BLOB session_key;
688         struct dcerpc_binding_handle *b = p->binding_handle;
689         char *newpass;
690         struct samr_GetUserPwInfo pwp;
691         struct samr_PwInfo info;
692         int policy_min_pw_len = 0;
693         pwp.in.user_handle = handle;
694         pwp.out.info = &info;
695
696         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
697                 "GetUserPwInfo failed");
698         if (NT_STATUS_IS_OK(pwp.out.result)) {
699                 policy_min_pw_len = pwp.out.info->min_password_length;
700         }
701         newpass = samr_rand_pass(tctx, policy_min_pw_len);
702
703         s.in.user_handle = handle;
704         s.in.info = &u;
705         s.in.level = 23;
706
707         ZERO_STRUCT(u);
708
709         u.info23.info.fields_present = fields_present;
710
711         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
712
713         status = dcerpc_fetch_session_key(p, &session_key);
714         if (!NT_STATUS_IS_OK(status)) {
715                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
716                        s.in.level, nt_errstr(status));
717                 return false;
718         }
719
720         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
721
722         torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
723
724         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
725                 "SetUserInfo failed");
726         if (!NT_STATUS_IS_OK(s.out.result)) {
727                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
728                        s.in.level, nt_errstr(s.out.result));
729                 ret = false;
730         } else {
731                 *password = newpass;
732         }
733
734         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
735
736         status = dcerpc_fetch_session_key(p, &session_key);
737         if (!NT_STATUS_IS_OK(status)) {
738                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
739                        s.in.level, nt_errstr(status));
740                 return false;
741         }
742
743         /* This should break the key nicely */
744         session_key.length--;
745         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
746
747         torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
748
749         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
750                 "SetUserInfo failed");
751         if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
752                 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
753                        s.in.level, nt_errstr(s.out.result));
754                 ret = false;
755         }
756
757         return ret;
758 }
759
760
761 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
762                                struct policy_handle *handle, bool makeshort,
763                                char **password)
764 {
765         NTSTATUS status;
766         struct samr_SetUserInfo s;
767         union samr_UserInfo u;
768         bool ret = true;
769         DATA_BLOB session_key;
770         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
771         uint8_t confounder[16];
772         char *newpass;
773         struct dcerpc_binding_handle *b = p->binding_handle;
774         struct MD5Context ctx;
775         struct samr_GetUserPwInfo pwp;
776         struct samr_PwInfo info;
777         int policy_min_pw_len = 0;
778         pwp.in.user_handle = handle;
779         pwp.out.info = &info;
780
781         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
782                 "GetUserPwInfo failed");
783         if (NT_STATUS_IS_OK(pwp.out.result)) {
784                 policy_min_pw_len = pwp.out.info->min_password_length;
785         }
786         if (makeshort && policy_min_pw_len) {
787                 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
788         } else {
789                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
790         }
791
792         s.in.user_handle = handle;
793         s.in.info = &u;
794         s.in.level = 26;
795
796         encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
797         u.info26.password_expired = 0;
798
799         status = dcerpc_fetch_session_key(p, &session_key);
800         if (!NT_STATUS_IS_OK(status)) {
801                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
802                        s.in.level, nt_errstr(status));
803                 return false;
804         }
805
806         generate_random_buffer((uint8_t *)confounder, 16);
807
808         MD5Init(&ctx);
809         MD5Update(&ctx, confounder, 16);
810         MD5Update(&ctx, session_key.data, session_key.length);
811         MD5Final(confounded_session_key.data, &ctx);
812
813         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
814         memcpy(&u.info26.password.data[516], confounder, 16);
815
816         torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
817
818         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
819                 "SetUserInfo failed");
820         if (!NT_STATUS_IS_OK(s.out.result)) {
821                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
822                        s.in.level, nt_errstr(s.out.result));
823                 ret = false;
824         } else {
825                 *password = newpass;
826         }
827
828         /* This should break the key nicely */
829         confounded_session_key.data[0]++;
830
831         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
832         memcpy(&u.info26.password.data[516], confounder, 16);
833
834         torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
835
836         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
837                 "SetUserInfo failed");
838         if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
839                 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
840                        s.in.level, nt_errstr(s.out.result));
841                 ret = false;
842         } else {
843                 *password = newpass;
844         }
845
846         return ret;
847 }
848
849 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
850                                 struct policy_handle *handle, uint32_t fields_present,
851                                 char **password)
852 {
853         NTSTATUS status;
854         struct samr_SetUserInfo s;
855         union samr_UserInfo u;
856         bool ret = true;
857         DATA_BLOB session_key;
858         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
859         struct MD5Context ctx;
860         uint8_t confounder[16];
861         char *newpass;
862         struct dcerpc_binding_handle *b = p->binding_handle;
863         struct samr_GetUserPwInfo pwp;
864         struct samr_PwInfo info;
865         int policy_min_pw_len = 0;
866         pwp.in.user_handle = handle;
867         pwp.out.info = &info;
868
869         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
870                 "GetUserPwInfo failed");
871         if (NT_STATUS_IS_OK(pwp.out.result)) {
872                 policy_min_pw_len = pwp.out.info->min_password_length;
873         }
874         newpass = samr_rand_pass(tctx, policy_min_pw_len);
875
876         s.in.user_handle = handle;
877         s.in.info = &u;
878         s.in.level = 25;
879
880         ZERO_STRUCT(u);
881
882         u.info25.info.fields_present = fields_present;
883
884         encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
885
886         status = dcerpc_fetch_session_key(p, &session_key);
887         if (!NT_STATUS_IS_OK(status)) {
888                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
889                        s.in.level, nt_errstr(status));
890                 return false;
891         }
892
893         generate_random_buffer((uint8_t *)confounder, 16);
894
895         MD5Init(&ctx);
896         MD5Update(&ctx, confounder, 16);
897         MD5Update(&ctx, session_key.data, session_key.length);
898         MD5Final(confounded_session_key.data, &ctx);
899
900         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
901         memcpy(&u.info25.password.data[516], confounder, 16);
902
903         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
904
905         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
906                 "SetUserInfo failed");
907         if (!NT_STATUS_IS_OK(s.out.result)) {
908                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
909                        s.in.level, nt_errstr(s.out.result));
910                 ret = false;
911         } else {
912                 *password = newpass;
913         }
914
915         /* This should break the key nicely */
916         confounded_session_key.data[0]++;
917
918         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
919         memcpy(&u.info25.password.data[516], confounder, 16);
920
921         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
922
923         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
924                 "SetUserInfo failed");
925         if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
926                 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
927                        s.in.level, nt_errstr(s.out.result));
928                 ret = false;
929         }
930
931         return ret;
932 }
933
934 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
935                                 struct policy_handle *handle, char **password)
936 {
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 dcerpc_binding_handle *b = p->binding_handle;
944         struct samr_GetUserPwInfo pwp;
945         struct samr_PwInfo info;
946         int policy_min_pw_len = 0;
947         uint8_t lm_hash[16], nt_hash[16];
948
949         pwp.in.user_handle = handle;
950         pwp.out.info = &info;
951
952         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
953                 "GetUserPwInfo failed");
954         if (NT_STATUS_IS_OK(pwp.out.result)) {
955                 policy_min_pw_len = pwp.out.info->min_password_length;
956         }
957         newpass = samr_rand_pass(tctx, policy_min_pw_len);
958
959         s.in.user_handle = handle;
960         s.in.info = &u;
961         s.in.level = 18;
962
963         ZERO_STRUCT(u);
964
965         u.info18.nt_pwd_active = true;
966         u.info18.lm_pwd_active = true;
967
968         E_md4hash(newpass, nt_hash);
969         E_deshash(newpass, lm_hash);
970
971         status = dcerpc_fetch_session_key(p, &session_key);
972         if (!NT_STATUS_IS_OK(status)) {
973                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
974                        s.in.level, nt_errstr(status));
975                 return false;
976         }
977
978         {
979                 DATA_BLOB in,out;
980                 in = data_blob_const(nt_hash, 16);
981                 out = data_blob_talloc_zero(tctx, 16);
982                 sess_crypt_blob(&out, &in, &session_key, true);
983                 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
984         }
985         {
986                 DATA_BLOB in,out;
987                 in = data_blob_const(lm_hash, 16);
988                 out = data_blob_talloc_zero(tctx, 16);
989                 sess_crypt_blob(&out, &in, &session_key, true);
990                 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
991         }
992
993         torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
994
995         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
996                 "SetUserInfo failed");
997         if (!NT_STATUS_IS_OK(s.out.result)) {
998                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
999                        s.in.level, nt_errstr(s.out.result));
1000                 ret = false;
1001         } else {
1002                 *password = newpass;
1003         }
1004
1005         return ret;
1006 }
1007
1008 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1009                                 struct policy_handle *handle, uint32_t fields_present,
1010                                 char **password)
1011 {
1012         NTSTATUS status;
1013         struct samr_SetUserInfo s;
1014         union samr_UserInfo u;
1015         bool ret = true;
1016         DATA_BLOB session_key;
1017         char *newpass;
1018         struct dcerpc_binding_handle *b = p->binding_handle;
1019         struct samr_GetUserPwInfo pwp;
1020         struct samr_PwInfo info;
1021         int policy_min_pw_len = 0;
1022         uint8_t lm_hash[16], nt_hash[16];
1023
1024         pwp.in.user_handle = handle;
1025         pwp.out.info = &info;
1026
1027         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1028                 "GetUserPwInfo failed");
1029         if (NT_STATUS_IS_OK(pwp.out.result)) {
1030                 policy_min_pw_len = pwp.out.info->min_password_length;
1031         }
1032         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1033
1034         s.in.user_handle = handle;
1035         s.in.info = &u;
1036         s.in.level = 21;
1037
1038         E_md4hash(newpass, nt_hash);
1039         E_deshash(newpass, lm_hash);
1040
1041         ZERO_STRUCT(u);
1042
1043         u.info21.fields_present = fields_present;
1044
1045         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1046                 u.info21.lm_owf_password.length = 16;
1047                 u.info21.lm_owf_password.size = 16;
1048                 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1049                 u.info21.lm_password_set = true;
1050         }
1051
1052         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1053                 u.info21.nt_owf_password.length = 16;
1054                 u.info21.nt_owf_password.size = 16;
1055                 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1056                 u.info21.nt_password_set = true;
1057         }
1058
1059         status = dcerpc_fetch_session_key(p, &session_key);
1060         if (!NT_STATUS_IS_OK(status)) {
1061                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1062                        s.in.level, nt_errstr(status));
1063                 return false;
1064         }
1065
1066         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1067                 DATA_BLOB in,out;
1068                 in = data_blob_const(u.info21.lm_owf_password.array,
1069                                      u.info21.lm_owf_password.length);
1070                 out = data_blob_talloc_zero(tctx, 16);
1071                 sess_crypt_blob(&out, &in, &session_key, true);
1072                 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1073         }
1074
1075         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1076                 DATA_BLOB in,out;
1077                 in = data_blob_const(u.info21.nt_owf_password.array,
1078                                      u.info21.nt_owf_password.length);
1079                 out = data_blob_talloc_zero(tctx, 16);
1080                 sess_crypt_blob(&out, &in, &session_key, true);
1081                 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1082         }
1083
1084         torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1085
1086         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1087                 "SetUserInfo failed");
1088         if (!NT_STATUS_IS_OK(s.out.result)) {
1089                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1090                        s.in.level, nt_errstr(s.out.result));
1091                 ret = false;
1092         } else {
1093                 *password = newpass;
1094         }
1095
1096         /* try invalid length */
1097         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1098
1099                 u.info21.nt_owf_password.length++;
1100
1101                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1102                         "SetUserInfo failed");
1103                 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1104                         torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1105                                s.in.level, nt_errstr(s.out.result));
1106                         ret = false;
1107                 }
1108         }
1109
1110         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1111
1112                 u.info21.lm_owf_password.length++;
1113
1114                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1115                         "SetUserInfo failed");
1116                 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1117                         torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1118                                s.in.level, nt_errstr(s.out.result));
1119                         ret = false;
1120                 }
1121         }
1122
1123         return ret;
1124 }
1125
1126 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1127                                       struct torture_context *tctx,
1128                                       struct policy_handle *handle,
1129                                       uint16_t level,
1130                                       uint32_t fields_present,
1131                                       char **password, uint8_t password_expired,
1132                                       bool use_setinfo2,
1133                                       bool *matched_expected_error)
1134 {
1135         NTSTATUS status;
1136         NTSTATUS expected_error = NT_STATUS_OK;
1137         struct samr_SetUserInfo s;
1138         struct samr_SetUserInfo2 s2;
1139         union samr_UserInfo u;
1140         bool ret = true;
1141         DATA_BLOB session_key;
1142         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1143         struct MD5Context ctx;
1144         uint8_t confounder[16];
1145         char *newpass;
1146         struct dcerpc_binding_handle *b = p->binding_handle;
1147         struct samr_GetUserPwInfo pwp;
1148         struct samr_PwInfo info;
1149         int policy_min_pw_len = 0;
1150         const char *comment = NULL;
1151         uint8_t lm_hash[16], nt_hash[16];
1152
1153         pwp.in.user_handle = handle;
1154         pwp.out.info = &info;
1155
1156         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1157                 "GetUserPwInfo failed");
1158         if (NT_STATUS_IS_OK(pwp.out.result)) {
1159                 policy_min_pw_len = pwp.out.info->min_password_length;
1160         }
1161         newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1162
1163         if (use_setinfo2) {
1164                 s2.in.user_handle = handle;
1165                 s2.in.info = &u;
1166                 s2.in.level = level;
1167         } else {
1168                 s.in.user_handle = handle;
1169                 s.in.info = &u;
1170                 s.in.level = level;
1171         }
1172
1173         if (fields_present & SAMR_FIELD_COMMENT) {
1174                 comment = talloc_asprintf(tctx, "comment: %ld\n", time(NULL));
1175         }
1176
1177         ZERO_STRUCT(u);
1178
1179         switch (level) {
1180         case 18:
1181                 E_md4hash(newpass, nt_hash);
1182                 E_deshash(newpass, lm_hash);
1183
1184                 u.info18.nt_pwd_active = true;
1185                 u.info18.lm_pwd_active = true;
1186                 u.info18.password_expired = password_expired;
1187
1188                 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1189                 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1190
1191                 break;
1192         case 21:
1193                 E_md4hash(newpass, nt_hash);
1194                 E_deshash(newpass, lm_hash);
1195
1196                 u.info21.fields_present = fields_present;
1197                 u.info21.password_expired = password_expired;
1198                 u.info21.comment.string = comment;
1199
1200                 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1201                         u.info21.lm_owf_password.length = 16;
1202                         u.info21.lm_owf_password.size = 16;
1203                         u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1204                         u.info21.lm_password_set = true;
1205                 }
1206
1207                 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1208                         u.info21.nt_owf_password.length = 16;
1209                         u.info21.nt_owf_password.size = 16;
1210                         u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1211                         u.info21.nt_password_set = true;
1212                 }
1213
1214                 break;
1215         case 23:
1216                 u.info23.info.fields_present = fields_present;
1217                 u.info23.info.password_expired = password_expired;
1218                 u.info23.info.comment.string = comment;
1219
1220                 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1221
1222                 break;
1223         case 24:
1224                 u.info24.password_expired = password_expired;
1225
1226                 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1227
1228                 break;
1229         case 25:
1230                 u.info25.info.fields_present = fields_present;
1231                 u.info25.info.password_expired = password_expired;
1232                 u.info25.info.comment.string = comment;
1233
1234                 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1235
1236                 break;
1237         case 26:
1238                 u.info26.password_expired = password_expired;
1239
1240                 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1241
1242                 break;
1243         }
1244
1245         status = dcerpc_fetch_session_key(p, &session_key);
1246         if (!NT_STATUS_IS_OK(status)) {
1247                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1248                        s.in.level, nt_errstr(status));
1249                 return false;
1250         }
1251
1252         generate_random_buffer((uint8_t *)confounder, 16);
1253
1254         MD5Init(&ctx);
1255         MD5Update(&ctx, confounder, 16);
1256         MD5Update(&ctx, session_key.data, session_key.length);
1257         MD5Final(confounded_session_key.data, &ctx);
1258
1259         switch (level) {
1260         case 18:
1261                 {
1262                         DATA_BLOB in,out;
1263                         in = data_blob_const(u.info18.nt_pwd.hash, 16);
1264                         out = data_blob_talloc_zero(tctx, 16);
1265                         sess_crypt_blob(&out, &in, &session_key, true);
1266                         memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1267                 }
1268                 {
1269                         DATA_BLOB in,out;
1270                         in = data_blob_const(u.info18.lm_pwd.hash, 16);
1271                         out = data_blob_talloc_zero(tctx, 16);
1272                         sess_crypt_blob(&out, &in, &session_key, true);
1273                         memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1274                 }
1275
1276                 break;
1277         case 21:
1278                 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1279                         DATA_BLOB in,out;
1280                         in = data_blob_const(u.info21.lm_owf_password.array,
1281                                              u.info21.lm_owf_password.length);
1282                         out = data_blob_talloc_zero(tctx, 16);
1283                         sess_crypt_blob(&out, &in, &session_key, true);
1284                         u.info21.lm_owf_password.array = (uint16_t *)out.data;
1285                 }
1286                 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1287                         DATA_BLOB in,out;
1288                         in = data_blob_const(u.info21.nt_owf_password.array,
1289                                              u.info21.nt_owf_password.length);
1290                         out = data_blob_talloc_zero(tctx, 16);
1291                         sess_crypt_blob(&out, &in, &session_key, true);
1292                         u.info21.nt_owf_password.array = (uint16_t *)out.data;
1293                 }
1294                 break;
1295         case 23:
1296                 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1297                 break;
1298         case 24:
1299                 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1300                 break;
1301         case 25:
1302                 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1303                 memcpy(&u.info25.password.data[516], confounder, 16);
1304                 break;
1305         case 26:
1306                 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1307                 memcpy(&u.info26.password.data[516], confounder, 16);
1308                 break;
1309         }
1310
1311         if (use_setinfo2) {
1312                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1313                         "SetUserInfo2 failed");
1314                 status = s2.out.result;
1315         } else {
1316                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1317                         "SetUserInfo failed");
1318                 status = s.out.result;
1319         }
1320
1321         if (!NT_STATUS_IS_OK(status)) {
1322                 if (fields_present == 0) {
1323                         expected_error = NT_STATUS_INVALID_PARAMETER;
1324                 }
1325                 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1326                         expected_error = NT_STATUS_ACCESS_DENIED;
1327                 }
1328         }
1329
1330         if (!NT_STATUS_IS_OK(expected_error)) {
1331                 if (use_setinfo2) {
1332                         torture_assert_ntstatus_equal(tctx,
1333                                 s2.out.result,
1334                                 expected_error, "SetUserInfo2 failed");
1335                 } else {
1336                         torture_assert_ntstatus_equal(tctx,
1337                                 s.out.result,
1338                                 expected_error, "SetUserInfo failed");
1339                 }
1340                 *matched_expected_error = true;
1341                 return true;
1342         }
1343
1344         if (!NT_STATUS_IS_OK(status)) {
1345                 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1346                        use_setinfo2 ? "2":"", level, nt_errstr(status));
1347                 ret = false;
1348         } else {
1349                 *password = newpass;
1350         }
1351
1352         return ret;
1353 }
1354
1355 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1356                               struct torture_context *tctx,
1357                               struct policy_handle *handle)
1358 {
1359         struct samr_SetAliasInfo r;
1360         struct samr_QueryAliasInfo q;
1361         union samr_AliasInfo *info;
1362         uint16_t levels[] = {2, 3};
1363         int i;
1364         bool ret = true;
1365
1366         /* Ignoring switch level 1, as that includes the number of members for the alias
1367          * and setting this to a wrong value might have negative consequences
1368          */
1369
1370         for (i=0;i<ARRAY_SIZE(levels);i++) {
1371                 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1372
1373                 r.in.alias_handle = handle;
1374                 r.in.level = levels[i];
1375                 r.in.info  = talloc(tctx, union samr_AliasInfo);
1376                 switch (r.in.level) {
1377                     case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1378                     case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1379                                 "Test Description, should test I18N as well"); break;
1380                     case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1381                 }
1382
1383                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1384                         "SetAliasInfo failed");
1385                 if (!NT_STATUS_IS_OK(r.out.result)) {
1386                         torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1387                                levels[i], nt_errstr(r.out.result));
1388                         ret = false;
1389                 }
1390
1391                 q.in.alias_handle = handle;
1392                 q.in.level = levels[i];
1393                 q.out.info = &info;
1394
1395                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1396                         "QueryAliasInfo failed");
1397                 if (!NT_STATUS_IS_OK(q.out.result)) {
1398                         torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1399                                levels[i], nt_errstr(q.out.result));
1400                         ret = false;
1401                 }
1402         }
1403
1404         return ret;
1405 }
1406
1407 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1408                                   struct torture_context *tctx,
1409                                   struct policy_handle *user_handle)
1410 {
1411         struct samr_GetGroupsForUser r;
1412         struct samr_RidWithAttributeArray *rids = NULL;
1413
1414         torture_comment(tctx, "Testing GetGroupsForUser\n");
1415
1416         r.in.user_handle = user_handle;
1417         r.out.rids = &rids;
1418
1419         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1420                 "GetGroupsForUser failed");
1421         torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1422
1423         return true;
1424
1425 }
1426
1427 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1428                               struct lsa_String *domain_name)
1429 {
1430         struct samr_GetDomPwInfo r;
1431         struct samr_PwInfo info;
1432         struct dcerpc_binding_handle *b = p->binding_handle;
1433
1434         r.in.domain_name = domain_name;
1435         r.out.info = &info;
1436
1437         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1438
1439         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1440                 "GetDomPwInfo failed");
1441         torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1442
1443         r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1444         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1445
1446         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1447                 "GetDomPwInfo failed");
1448         torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1449
1450         r.in.domain_name->string = "\\\\__NONAME__";
1451         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1452
1453         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1454                 "GetDomPwInfo failed");
1455         torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1456
1457         r.in.domain_name->string = "\\\\Builtin";
1458         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1459
1460         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1461                 "GetDomPwInfo failed");
1462         torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1463
1464         return true;
1465 }
1466
1467 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1468                                struct torture_context *tctx,
1469                                struct policy_handle *handle)
1470 {
1471         struct samr_GetUserPwInfo r;
1472         struct samr_PwInfo info;
1473
1474         torture_comment(tctx, "Testing GetUserPwInfo\n");
1475
1476         r.in.user_handle = handle;
1477         r.out.info = &info;
1478
1479         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1480                 "GetUserPwInfo failed");
1481         torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1482
1483         return true;
1484 }
1485
1486 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1487                                 struct torture_context *tctx,
1488                                 struct policy_handle *domain_handle, const char *name,
1489                                 uint32_t *rid)
1490 {
1491         NTSTATUS status;
1492         struct samr_LookupNames n;
1493         struct lsa_String sname[2];
1494         struct samr_Ids rids, types;
1495
1496         init_lsa_String(&sname[0], name);
1497
1498         n.in.domain_handle = domain_handle;
1499         n.in.num_names = 1;
1500         n.in.names = sname;
1501         n.out.rids = &rids;
1502         n.out.types = &types;
1503         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1504         if (!NT_STATUS_IS_OK(status)) {
1505                 return status;
1506         }
1507         if (NT_STATUS_IS_OK(n.out.result)) {
1508                 *rid = n.out.rids->ids[0];
1509         } else {
1510                 return n.out.result;
1511         }
1512
1513         init_lsa_String(&sname[1], "xxNONAMExx");
1514         n.in.num_names = 2;
1515         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1516         if (!NT_STATUS_IS_OK(status)) {
1517                 return status;
1518         }
1519         if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1520                 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1521                 if (NT_STATUS_IS_OK(n.out.result)) {
1522                         return NT_STATUS_UNSUCCESSFUL;
1523                 }
1524                 return n.out.result;
1525         }
1526
1527         n.in.num_names = 0;
1528         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1529         if (!NT_STATUS_IS_OK(status)) {
1530                 return status;
1531         }
1532         if (!NT_STATUS_IS_OK(n.out.result)) {
1533                 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1534                 return n.out.result;
1535         }
1536
1537         init_lsa_String(&sname[0], "xxNONAMExx");
1538         n.in.num_names = 1;
1539         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1540         if (!NT_STATUS_IS_OK(status)) {
1541                 return status;
1542         }
1543         if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1544                 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1545                 if (NT_STATUS_IS_OK(n.out.result)) {
1546                         return NT_STATUS_UNSUCCESSFUL;
1547                 }
1548                 return n.out.result;
1549         }
1550
1551         init_lsa_String(&sname[0], "xxNONAMExx");
1552         init_lsa_String(&sname[1], "xxNONAME2xx");
1553         n.in.num_names = 2;
1554         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1555         if (!NT_STATUS_IS_OK(status)) {
1556                 return status;
1557         }
1558         if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1559                 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1560                 if (NT_STATUS_IS_OK(n.out.result)) {
1561                         return NT_STATUS_UNSUCCESSFUL;
1562                 }
1563                 return n.out.result;
1564         }
1565
1566         return NT_STATUS_OK;
1567 }
1568
1569 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1570                                      struct torture_context *tctx,
1571                                      struct policy_handle *domain_handle,
1572                                      const char *name, struct policy_handle *user_handle)
1573 {
1574         NTSTATUS status;
1575         struct samr_OpenUser r;
1576         uint32_t rid;
1577
1578         status = test_LookupName(b, tctx, domain_handle, name, &rid);
1579         if (!NT_STATUS_IS_OK(status)) {
1580                 return status;
1581         }
1582
1583         r.in.domain_handle = domain_handle;
1584         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1585         r.in.rid = rid;
1586         r.out.user_handle = user_handle;
1587         status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1588         if (!NT_STATUS_IS_OK(status)) {
1589                 return status;
1590         }
1591         if (!NT_STATUS_IS_OK(r.out.result)) {
1592                 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1593         }
1594
1595         return r.out.result;
1596 }
1597
1598 #if 0
1599 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1600                                    struct torture_context *tctx,
1601                                    struct policy_handle *handle)
1602 {
1603         NTSTATUS status;
1604         struct samr_ChangePasswordUser r;
1605         bool ret = true;
1606         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1607         struct policy_handle user_handle;
1608         char *oldpass = "test";
1609         char *newpass = "test2";
1610         uint8_t old_nt_hash[16], new_nt_hash[16];
1611         uint8_t old_lm_hash[16], new_lm_hash[16];
1612
1613         status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1614         if (!NT_STATUS_IS_OK(status)) {
1615                 return false;
1616         }
1617
1618         torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1619
1620         torture_comment(tctx, "old password: %s\n", oldpass);
1621         torture_comment(tctx, "new password: %s\n", newpass);
1622
1623         E_md4hash(oldpass, old_nt_hash);
1624         E_md4hash(newpass, new_nt_hash);
1625         E_deshash(oldpass, old_lm_hash);
1626         E_deshash(newpass, new_lm_hash);
1627
1628         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1629         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1630         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1631         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1632         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1633         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1634
1635         r.in.handle = &user_handle;
1636         r.in.lm_present = 1;
1637         r.in.old_lm_crypted = &hash1;
1638         r.in.new_lm_crypted = &hash2;
1639         r.in.nt_present = 1;
1640         r.in.old_nt_crypted = &hash3;
1641         r.in.new_nt_crypted = &hash4;
1642         r.in.cross1_present = 1;
1643         r.in.nt_cross = &hash5;
1644         r.in.cross2_present = 1;
1645         r.in.lm_cross = &hash6;
1646
1647         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1648                 "ChangePasswordUser failed");
1649         if (!NT_STATUS_IS_OK(r.out.result)) {
1650                 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1651                 ret = false;
1652         }
1653
1654         if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1655                 ret = false;
1656         }
1657
1658         return ret;
1659 }
1660 #endif
1661
1662 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1663                                     struct torture_context *tctx,
1664                                     const char *acct_name,
1665                                     struct policy_handle *handle, char **password)
1666 {
1667         NTSTATUS status;
1668         struct samr_ChangePasswordUser r;
1669         bool ret = true;
1670         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1671         struct policy_handle user_handle;
1672         char *oldpass;
1673         uint8_t old_nt_hash[16], new_nt_hash[16];
1674         uint8_t old_lm_hash[16], new_lm_hash[16];
1675         bool changed = true;
1676
1677         char *newpass;
1678         struct samr_GetUserPwInfo pwp;
1679         struct samr_PwInfo info;
1680         int policy_min_pw_len = 0;
1681
1682         status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1683         if (!NT_STATUS_IS_OK(status)) {
1684                 return false;
1685         }
1686         pwp.in.user_handle = &user_handle;
1687         pwp.out.info = &info;
1688
1689         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1690                 "GetUserPwInfo failed");
1691         if (NT_STATUS_IS_OK(pwp.out.result)) {
1692                 policy_min_pw_len = pwp.out.info->min_password_length;
1693         }
1694         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1695
1696         torture_comment(tctx, "Testing ChangePasswordUser\n");
1697
1698         torture_assert(tctx, *password != NULL,
1699                                    "Failing ChangePasswordUser as old password was NULL.  Previous test failed?");
1700
1701         oldpass = *password;
1702
1703         E_md4hash(oldpass, old_nt_hash);
1704         E_md4hash(newpass, new_nt_hash);
1705         E_deshash(oldpass, old_lm_hash);
1706         E_deshash(newpass, new_lm_hash);
1707
1708         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1709         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1710         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1711         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1712         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1713         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1714
1715         r.in.user_handle = &user_handle;
1716         r.in.lm_present = 1;
1717         /* Break the LM hash */
1718         hash1.hash[0]++;
1719         r.in.old_lm_crypted = &hash1;
1720         r.in.new_lm_crypted = &hash2;
1721         r.in.nt_present = 1;
1722         r.in.old_nt_crypted = &hash3;
1723         r.in.new_nt_crypted = &hash4;
1724         r.in.cross1_present = 1;
1725         r.in.nt_cross = &hash5;
1726         r.in.cross2_present = 1;
1727         r.in.lm_cross = &hash6;
1728
1729         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1730                 "ChangePasswordUser failed");
1731         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1732                 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1733
1734         /* Unbreak the LM hash */
1735         hash1.hash[0]--;
1736
1737         r.in.user_handle = &user_handle;
1738         r.in.lm_present = 1;
1739         r.in.old_lm_crypted = &hash1;
1740         r.in.new_lm_crypted = &hash2;
1741         /* Break the NT hash */
1742         hash3.hash[0]--;
1743         r.in.nt_present = 1;
1744         r.in.old_nt_crypted = &hash3;
1745         r.in.new_nt_crypted = &hash4;
1746         r.in.cross1_present = 1;
1747         r.in.nt_cross = &hash5;
1748         r.in.cross2_present = 1;
1749         r.in.lm_cross = &hash6;
1750
1751         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1752                 "ChangePasswordUser failed");
1753         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1754                 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1755
1756         /* Unbreak the NT hash */
1757         hash3.hash[0]--;
1758
1759         r.in.user_handle = &user_handle;
1760         r.in.lm_present = 1;
1761         r.in.old_lm_crypted = &hash1;
1762         r.in.new_lm_crypted = &hash2;
1763         r.in.nt_present = 1;
1764         r.in.old_nt_crypted = &hash3;
1765         r.in.new_nt_crypted = &hash4;
1766         r.in.cross1_present = 1;
1767         r.in.nt_cross = &hash5;
1768         r.in.cross2_present = 1;
1769         /* Break the LM cross */
1770         hash6.hash[0]++;
1771         r.in.lm_cross = &hash6;
1772
1773         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1774                 "ChangePasswordUser failed");
1775         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1776                 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
1777                 ret = false;
1778         }
1779
1780         /* Unbreak the LM cross */
1781         hash6.hash[0]--;
1782
1783         r.in.user_handle = &user_handle;
1784         r.in.lm_present = 1;
1785         r.in.old_lm_crypted = &hash1;
1786         r.in.new_lm_crypted = &hash2;
1787         r.in.nt_present = 1;
1788         r.in.old_nt_crypted = &hash3;
1789         r.in.new_nt_crypted = &hash4;
1790         r.in.cross1_present = 1;
1791         /* Break the NT cross */
1792         hash5.hash[0]++;
1793         r.in.nt_cross = &hash5;
1794         r.in.cross2_present = 1;
1795         r.in.lm_cross = &hash6;
1796
1797         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1798                 "ChangePasswordUser failed");
1799         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1800                 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
1801                 ret = false;
1802         }
1803
1804         /* Unbreak the NT cross */
1805         hash5.hash[0]--;
1806
1807
1808         /* Reset the hashes to not broken values */
1809         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1810         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1811         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1812         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1813         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1814         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1815
1816         r.in.user_handle = &user_handle;
1817         r.in.lm_present = 1;
1818         r.in.old_lm_crypted = &hash1;
1819         r.in.new_lm_crypted = &hash2;
1820         r.in.nt_present = 1;
1821         r.in.old_nt_crypted = &hash3;
1822         r.in.new_nt_crypted = &hash4;
1823         r.in.cross1_present = 1;
1824         r.in.nt_cross = &hash5;
1825         r.in.cross2_present = 0;
1826         r.in.lm_cross = NULL;
1827
1828         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1829                 "ChangePasswordUser failed");
1830         if (NT_STATUS_IS_OK(r.out.result)) {
1831                 changed = true;
1832                 *password = newpass;
1833         } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1834                 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1835                 ret = false;
1836         }
1837
1838         oldpass = newpass;
1839         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1840
1841         E_md4hash(oldpass, old_nt_hash);
1842         E_md4hash(newpass, new_nt_hash);
1843         E_deshash(oldpass, old_lm_hash);
1844         E_deshash(newpass, new_lm_hash);
1845
1846
1847         /* Reset the hashes to not broken values */
1848         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1849         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1850         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1851         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1852         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1853         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1854
1855         r.in.user_handle = &user_handle;
1856         r.in.lm_present = 1;
1857         r.in.old_lm_crypted = &hash1;
1858         r.in.new_lm_crypted = &hash2;
1859         r.in.nt_present = 1;
1860         r.in.old_nt_crypted = &hash3;
1861         r.in.new_nt_crypted = &hash4;
1862         r.in.cross1_present = 0;
1863         r.in.nt_cross = NULL;
1864         r.in.cross2_present = 1;
1865         r.in.lm_cross = &hash6;
1866
1867         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1868                 "ChangePasswordUser failed");
1869         if (NT_STATUS_IS_OK(r.out.result)) {
1870                 changed = true;
1871                 *password = newpass;
1872         } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1873                 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(r.out.result));
1874                 ret = false;
1875         }
1876
1877         oldpass = newpass;
1878         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1879
1880         E_md4hash(oldpass, old_nt_hash);
1881         E_md4hash(newpass, new_nt_hash);
1882         E_deshash(oldpass, old_lm_hash);
1883         E_deshash(newpass, new_lm_hash);
1884
1885
1886         /* Reset the hashes to not broken values */
1887         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1888         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1889         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1890         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1891         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1892         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1893
1894         r.in.user_handle = &user_handle;
1895         r.in.lm_present = 1;
1896         r.in.old_lm_crypted = &hash1;
1897         r.in.new_lm_crypted = &hash2;
1898         r.in.nt_present = 1;
1899         r.in.old_nt_crypted = &hash3;
1900         r.in.new_nt_crypted = &hash4;
1901         r.in.cross1_present = 1;
1902         r.in.nt_cross = &hash5;
1903         r.in.cross2_present = 1;
1904         r.in.lm_cross = &hash6;
1905
1906         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1907                 "ChangePasswordUser failed");
1908         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1909                 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1910         } else  if (!NT_STATUS_IS_OK(r.out.result)) {
1911                 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1912                 ret = false;
1913         } else {
1914                 changed = true;
1915                 *password = newpass;
1916         }
1917
1918         r.in.user_handle = &user_handle;
1919         r.in.lm_present = 1;
1920         r.in.old_lm_crypted = &hash1;
1921         r.in.new_lm_crypted = &hash2;
1922         r.in.nt_present = 1;
1923         r.in.old_nt_crypted = &hash3;
1924         r.in.new_nt_crypted = &hash4;
1925         r.in.cross1_present = 1;
1926         r.in.nt_cross = &hash5;
1927         r.in.cross2_present = 1;
1928         r.in.lm_cross = &hash6;
1929
1930         if (changed) {
1931                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1932                         "ChangePasswordUser failed");
1933                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1934                         torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1935                 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1936                         torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
1937                         ret = false;
1938                 }
1939         }
1940
1941
1942         if (!test_samr_handle_Close(b, tctx, &user_handle)) {
1943                 ret = false;
1944         }
1945
1946         return ret;
1947 }
1948
1949
1950 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
1951                                         struct torture_context *tctx,
1952                                         const char *acct_name,
1953                                         struct policy_handle *handle, char **password)
1954 {
1955         struct samr_OemChangePasswordUser2 r;
1956         bool ret = true;
1957         struct samr_Password lm_verifier;
1958         struct samr_CryptPassword lm_pass;
1959         struct lsa_AsciiString server, account, account_bad;
1960         char *oldpass;
1961         char *newpass;
1962         struct dcerpc_binding_handle *b = p->binding_handle;
1963         uint8_t old_lm_hash[16], new_lm_hash[16];
1964
1965         struct samr_GetDomPwInfo dom_pw_info;
1966         struct samr_PwInfo info;
1967         int policy_min_pw_len = 0;
1968
1969         struct lsa_String domain_name;
1970
1971         domain_name.string = "";
1972         dom_pw_info.in.domain_name = &domain_name;
1973         dom_pw_info.out.info = &info;
1974
1975         torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1976
1977         torture_assert(tctx, *password != NULL,
1978                                    "Failing OemChangePasswordUser2 as old password was NULL.  Previous test failed?");
1979
1980         oldpass = *password;
1981
1982         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
1983                 "GetDomPwInfo failed");
1984         if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
1985                 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1986         }
1987
1988         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1989
1990         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1991         account.string = acct_name;
1992
1993         E_deshash(oldpass, old_lm_hash);
1994         E_deshash(newpass, new_lm_hash);
1995
1996         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1997         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1998         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1999
2000         r.in.server = &server;
2001         r.in.account = &account;
2002         r.in.password = &lm_pass;
2003         r.in.hash = &lm_verifier;
2004
2005         /* Break the verification */
2006         lm_verifier.hash[0]++;
2007
2008         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2009                 "OemChangePasswordUser2 failed");
2010
2011         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2012             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2013                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2014                         nt_errstr(r.out.result));
2015                 ret = false;
2016         }
2017
2018         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2019         /* Break the old password */
2020         old_lm_hash[0]++;
2021         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2022         /* unbreak it for the next operation */
2023         old_lm_hash[0]--;
2024         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2025
2026         r.in.server = &server;
2027         r.in.account = &account;
2028         r.in.password = &lm_pass;
2029         r.in.hash = &lm_verifier;
2030
2031         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2032                 "OemChangePasswordUser2 failed");
2033
2034         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2035             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2036                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2037                         nt_errstr(r.out.result));
2038                 ret = false;
2039         }
2040
2041         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2042         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2043
2044         r.in.server = &server;
2045         r.in.account = &account;
2046         r.in.password = &lm_pass;
2047         r.in.hash = NULL;
2048
2049         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2050                 "OemChangePasswordUser2 failed");
2051
2052         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2053             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2054                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2055                         nt_errstr(r.out.result));
2056                 ret = false;
2057         }
2058
2059         /* This shouldn't be a valid name */
2060         account_bad.string = TEST_ACCOUNT_NAME "XX";
2061         r.in.account = &account_bad;
2062
2063         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2064                 "OemChangePasswordUser2 failed");
2065
2066         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2067                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2068                         nt_errstr(r.out.result));
2069                 ret = false;
2070         }
2071
2072         /* This shouldn't be a valid name */
2073         account_bad.string = TEST_ACCOUNT_NAME "XX";
2074         r.in.account = &account_bad;
2075         r.in.password = &lm_pass;
2076         r.in.hash = &lm_verifier;
2077
2078         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2079                 "OemChangePasswordUser2 failed");
2080
2081         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2082                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2083                         nt_errstr(r.out.result));
2084                 ret = false;
2085         }
2086
2087         /* This shouldn't be a valid name */
2088         account_bad.string = TEST_ACCOUNT_NAME "XX";
2089         r.in.account = &account_bad;
2090         r.in.password = NULL;
2091         r.in.hash = &lm_verifier;
2092
2093         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2094                 "OemChangePasswordUser2 failed");
2095
2096         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2097                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2098                         nt_errstr(r.out.result));
2099                 ret = false;
2100         }
2101
2102         E_deshash(oldpass, old_lm_hash);
2103         E_deshash(newpass, new_lm_hash);
2104
2105         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2106         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2107         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2108
2109         r.in.server = &server;
2110         r.in.account = &account;
2111         r.in.password = &lm_pass;
2112         r.in.hash = &lm_verifier;
2113
2114         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2115                 "OemChangePasswordUser2 failed");
2116
2117         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2118                 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2119         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2120                 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2121                 ret = false;
2122         } else {
2123                 *password = newpass;
2124         }
2125
2126         return ret;
2127 }
2128
2129
2130 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2131                                      const char *acct_name,
2132                                      char **password,
2133                                      char *newpass, bool allow_password_restriction)
2134 {
2135         struct samr_ChangePasswordUser2 r;
2136         bool ret = true;
2137         struct lsa_String server, account;
2138         struct samr_CryptPassword nt_pass, lm_pass;
2139         struct samr_Password nt_verifier, lm_verifier;
2140         char *oldpass;
2141         struct dcerpc_binding_handle *b = p->binding_handle;
2142         uint8_t old_nt_hash[16], new_nt_hash[16];
2143         uint8_t old_lm_hash[16], new_lm_hash[16];
2144
2145         struct samr_GetDomPwInfo dom_pw_info;
2146         struct samr_PwInfo info;
2147
2148         struct lsa_String domain_name;
2149
2150         domain_name.string = "";
2151         dom_pw_info.in.domain_name = &domain_name;
2152         dom_pw_info.out.info = &info;
2153
2154         torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2155
2156         torture_assert(tctx, *password != NULL,
2157                                    "Failing ChangePasswordUser2 as old password was NULL.  Previous test failed?");
2158         oldpass = *password;
2159
2160         if (!newpass) {
2161                 int policy_min_pw_len = 0;
2162                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2163                         "GetDomPwInfo failed");
2164                 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2165                         policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2166                 }
2167
2168                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2169         }
2170
2171         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2172         init_lsa_String(&account, acct_name);
2173
2174         E_md4hash(oldpass, old_nt_hash);
2175         E_md4hash(newpass, new_nt_hash);
2176
2177         E_deshash(oldpass, old_lm_hash);
2178         E_deshash(newpass, new_lm_hash);
2179
2180         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2181         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2182         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2183
2184         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2185         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2186         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2187
2188         r.in.server = &server;
2189         r.in.account = &account;
2190         r.in.nt_password = &nt_pass;
2191         r.in.nt_verifier = &nt_verifier;
2192         r.in.lm_change = 1;
2193         r.in.lm_password = &lm_pass;
2194         r.in.lm_verifier = &lm_verifier;
2195
2196         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2197                 "ChangePasswordUser2 failed");
2198
2199         if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2200                 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2201         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2202                 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2203                 ret = false;
2204         } else {
2205                 *password = newpass;
2206         }
2207
2208         return ret;
2209 }
2210
2211
2212 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2213                               const char *account_string,
2214                               int policy_min_pw_len,
2215                               char **password,
2216                               const char *newpass,
2217                               NTTIME last_password_change,
2218                               bool handle_reject_reason)
2219 {
2220         struct samr_ChangePasswordUser3 r;
2221         bool ret = true;
2222         struct lsa_String server, account, account_bad;
2223         struct samr_CryptPassword nt_pass, lm_pass;
2224         struct samr_Password nt_verifier, lm_verifier;
2225         char *oldpass;
2226         struct dcerpc_binding_handle *b = p->binding_handle;
2227         uint8_t old_nt_hash[16], new_nt_hash[16];
2228         uint8_t old_lm_hash[16], new_lm_hash[16];
2229         NTTIME t;
2230         struct samr_DomInfo1 *dominfo = NULL;
2231         struct userPwdChangeFailureInformation *reject = NULL;
2232
2233         torture_comment(tctx, "Testing ChangePasswordUser3\n");
2234
2235         if (newpass == NULL) {
2236                 do {
2237                         if (policy_min_pw_len == 0) {
2238                                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2239                         } else {
2240                                 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2241                         }
2242                 } while (check_password_quality(newpass) == false);
2243         } else {
2244                 torture_comment(tctx, "Using password '%s'\n", newpass);
2245         }
2246
2247         torture_assert(tctx, *password != NULL,
2248                                    "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
2249
2250         oldpass = *password;
2251         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2252         init_lsa_String(&account, account_string);
2253
2254         E_md4hash(oldpass, old_nt_hash);
2255         E_md4hash(newpass, new_nt_hash);
2256
2257         E_deshash(oldpass, old_lm_hash);
2258         E_deshash(newpass, new_lm_hash);
2259
2260         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2261         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2262         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2263
2264         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2265         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2266         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2267
2268         /* Break the verification */
2269         nt_verifier.hash[0]++;
2270
2271         r.in.server = &server;
2272         r.in.account = &account;
2273         r.in.nt_password = &nt_pass;
2274         r.in.nt_verifier = &nt_verifier;
2275         r.in.lm_change = 1;
2276         r.in.lm_password = &lm_pass;
2277         r.in.lm_verifier = &lm_verifier;
2278         r.in.password3 = NULL;
2279         r.out.dominfo = &dominfo;
2280         r.out.reject = &reject;
2281
2282         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2283                 "ChangePasswordUser3 failed");
2284         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2285             (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2286                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2287                         nt_errstr(r.out.result));
2288                 ret = false;
2289         }
2290
2291         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2292         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2293         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2294
2295         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2296         /* Break the NT hash */
2297         old_nt_hash[0]++;
2298         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2299         /* Unbreak it again */
2300         old_nt_hash[0]--;
2301         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2302
2303         r.in.server = &server;
2304         r.in.account = &account;
2305         r.in.nt_password = &nt_pass;
2306         r.in.nt_verifier = &nt_verifier;
2307         r.in.lm_change = 1;
2308         r.in.lm_password = &lm_pass;
2309         r.in.lm_verifier = &lm_verifier;
2310         r.in.password3 = NULL;
2311         r.out.dominfo = &dominfo;
2312         r.out.reject = &reject;
2313
2314         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2315                 "ChangePasswordUser3 failed");
2316         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2317             (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2318                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2319                         nt_errstr(r.out.result));
2320                 ret = false;
2321         }
2322
2323         /* This shouldn't be a valid name */
2324         init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2325
2326         r.in.account = &account_bad;
2327         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2328                 "ChangePasswordUser3 failed");
2329         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2330                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2331                         nt_errstr(r.out.result));
2332                 ret = false;
2333         }
2334
2335         E_md4hash(oldpass, old_nt_hash);
2336         E_md4hash(newpass, new_nt_hash);
2337
2338         E_deshash(oldpass, old_lm_hash);
2339         E_deshash(newpass, new_lm_hash);
2340
2341         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2342         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2343         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2344
2345         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2346         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2347         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2348
2349         r.in.server = &server;
2350         r.in.account = &account;
2351         r.in.nt_password = &nt_pass;
2352         r.in.nt_verifier = &nt_verifier;
2353         r.in.lm_change = 1;
2354         r.in.lm_password = &lm_pass;
2355         r.in.lm_verifier = &lm_verifier;
2356         r.in.password3 = NULL;
2357         r.out.dominfo = &dominfo;
2358         r.out.reject = &reject;
2359
2360         unix_to_nt_time(&t, time(NULL));
2361
2362         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2363                 "ChangePasswordUser3 failed");
2364
2365         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2366             && dominfo
2367             && reject
2368             && handle_reject_reason
2369             && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2370                 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2371
2372                         if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2373                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2374                                         SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2375                                 return false;
2376                         }
2377                 }
2378
2379                 /* We tested the order of precendence which is as follows:
2380
2381                 * pwd min_age
2382                 * pwd length
2383                 * pwd complexity
2384                 * pwd history
2385
2386                 Guenther */
2387
2388                 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2389                            (last_password_change + dominfo->min_password_age > t)) {
2390
2391                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2392                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2393                                         SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2394                                 return false;
2395                         }
2396
2397                 } else if ((dominfo->min_password_length > 0) &&
2398                            (strlen(newpass) < dominfo->min_password_length)) {
2399
2400                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2401                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2402                                         SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2403                                 return false;
2404                         }
2405
2406                 } else if ((dominfo->password_history_length > 0) &&
2407                             strequal(oldpass, newpass)) {
2408
2409                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2410                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2411                                         SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2412                                 return false;
2413                         }
2414                 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2415
2416                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2417                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2418                                         SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2419                                 return false;
2420                         }
2421
2422                 }
2423
2424                 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2425                         /* retry with adjusted size */
2426                         return test_ChangePasswordUser3(p, tctx, account_string,
2427                                                         dominfo->min_password_length,
2428                                                         password, NULL, 0, false);
2429
2430                 }
2431
2432         } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2433                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2434                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2435                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2436                         return false;
2437                 }
2438                 /* Perhaps the server has a 'min password age' set? */
2439
2440         } else {
2441                 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2442
2443                 *password = talloc_strdup(tctx, newpass);
2444         }
2445
2446         return ret;
2447 }
2448
2449 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2450                                     const char *account_string,
2451                                     struct policy_handle *handle,
2452                                     char **password)
2453 {
2454         NTSTATUS status;
2455         struct samr_ChangePasswordUser3 r;
2456         struct samr_SetUserInfo s;
2457         union samr_UserInfo u;
2458         DATA_BLOB session_key;
2459         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2460         uint8_t confounder[16];
2461         struct MD5Context ctx;
2462
2463         bool ret = true;
2464         struct lsa_String server, account;
2465         struct samr_CryptPassword nt_pass;
2466         struct samr_Password nt_verifier;
2467         DATA_BLOB new_random_pass;
2468         char *newpass;
2469         char *oldpass;
2470         struct dcerpc_binding_handle *b = p->binding_handle;
2471         uint8_t old_nt_hash[16], new_nt_hash[16];
2472         NTTIME t;
2473         struct samr_DomInfo1 *dominfo = NULL;
2474         struct userPwdChangeFailureInformation *reject = NULL;
2475
2476         new_random_pass = samr_very_rand_pass(tctx, 128);
2477
2478         torture_assert(tctx, *password != NULL,
2479                                    "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
2480
2481         oldpass = *password;
2482         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2483         init_lsa_String(&account, account_string);
2484
2485         s.in.user_handle = handle;
2486         s.in.info = &u;
2487         s.in.level = 25;
2488
2489         ZERO_STRUCT(u);
2490
2491         u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2492
2493         set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2494
2495         status = dcerpc_fetch_session_key(p, &session_key);
2496         if (!NT_STATUS_IS_OK(status)) {
2497                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2498                        s.in.level, nt_errstr(status));
2499                 return false;
2500         }
2501
2502         generate_random_buffer((uint8_t *)confounder, 16);
2503
2504         MD5Init(&ctx);
2505         MD5Update(&ctx, confounder, 16);
2506         MD5Update(&ctx, session_key.data, session_key.length);
2507         MD5Final(confounded_session_key.data, &ctx);
2508
2509         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2510         memcpy(&u.info25.password.data[516], confounder, 16);
2511
2512         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2513
2514         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2515                 "SetUserInfo failed");
2516         if (!NT_STATUS_IS_OK(s.out.result)) {
2517                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2518                        s.in.level, nt_errstr(s.out.result));
2519                 ret = false;
2520         }
2521
2522         torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2523
2524         mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2525
2526         new_random_pass = samr_very_rand_pass(tctx, 128);
2527
2528         mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2529
2530         set_pw_in_buffer(nt_pass.data, &new_random_pass);
2531         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2532         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2533
2534         r.in.server = &server;
2535         r.in.account = &account;
2536         r.in.nt_password = &nt_pass;
2537         r.in.nt_verifier = &nt_verifier;
2538         r.in.lm_change = 0;
2539         r.in.lm_password = NULL;
2540         r.in.lm_verifier = NULL;
2541         r.in.password3 = NULL;
2542         r.out.dominfo = &dominfo;
2543         r.out.reject = &reject;
2544
2545         unix_to_nt_time(&t, time(NULL));
2546
2547         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2548                 "ChangePasswordUser3 failed");
2549
2550         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2551                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2552                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2553                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2554                         return false;
2555                 }
2556                 /* Perhaps the server has a 'min password age' set? */
2557
2558         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2559                 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2560                 ret = false;
2561         }
2562
2563         newpass = samr_rand_pass(tctx, 128);
2564
2565         mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2566
2567         E_md4hash(newpass, new_nt_hash);
2568
2569         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2570         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2571         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2572
2573         r.in.server = &server;
2574         r.in.account = &account;
2575         r.in.nt_password = &nt_pass;
2576         r.in.nt_verifier = &nt_verifier;
2577         r.in.lm_change = 0;
2578         r.in.lm_password = NULL;
2579         r.in.lm_verifier = NULL;
2580         r.in.password3 = NULL;
2581         r.out.dominfo = &dominfo;
2582         r.out.reject = &reject;
2583
2584         unix_to_nt_time(&t, time(NULL));
2585
2586         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2587                 "ChangePasswordUser3 failed");
2588
2589         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2590                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2591                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2592                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2593                         return false;
2594                 }
2595                 /* Perhaps the server has a 'min password age' set? */
2596
2597         } else {
2598                 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2599                 *password = talloc_strdup(tctx, newpass);
2600         }
2601
2602         return ret;
2603 }
2604
2605
2606 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2607                                    struct torture_context *tctx,
2608                                    struct policy_handle *alias_handle)
2609 {
2610         struct samr_GetMembersInAlias r;
2611         struct lsa_SidArray sids;
2612
2613         torture_comment(tctx, "Testing GetMembersInAlias\n");
2614
2615         r.in.alias_handle = alias_handle;
2616         r.out.sids = &sids;
2617
2618         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2619                 "GetMembersInAlias failed");
2620         torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2621
2622         return true;
2623 }
2624
2625 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2626                                   struct torture_context *tctx,
2627                                   struct policy_handle *alias_handle,
2628                                   const struct dom_sid *domain_sid)
2629 {
2630         struct samr_AddAliasMember r;
2631         struct samr_DeleteAliasMember d;
2632         struct dom_sid *sid;
2633
2634         sid = dom_sid_add_rid(tctx, domain_sid, 512);
2635
2636         torture_comment(tctx, "Testing AddAliasMember\n");
2637         r.in.alias_handle = alias_handle;
2638         r.in.sid = sid;
2639
2640         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2641                 "AddAliasMember failed");
2642         torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2643
2644         d.in.alias_handle = alias_handle;
2645         d.in.sid = sid;
2646
2647         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2648                 "DeleteAliasMember failed");
2649         torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2650
2651         return true;
2652 }
2653
2654 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2655                                            struct torture_context *tctx,
2656                                            struct policy_handle *alias_handle)
2657 {
2658         struct samr_AddMultipleMembersToAlias a;
2659         struct samr_RemoveMultipleMembersFromAlias r;
2660         struct lsa_SidArray sids;
2661
2662         torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2663         a.in.alias_handle = alias_handle;
2664         a.in.sids = &sids;
2665
2666         sids.num_sids = 3;
2667         sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2668
2669         sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2670         sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2671         sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2672
2673         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2674                 "AddMultipleMembersToAlias failed");
2675         torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2676
2677
2678         torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2679         r.in.alias_handle = alias_handle;
2680         r.in.sids = &sids;
2681
2682         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2683                 "RemoveMultipleMembersFromAlias failed");
2684         torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2685
2686         /* strange! removing twice doesn't give any error */
2687         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2688                 "RemoveMultipleMembersFromAlias failed");
2689         torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2690
2691         /* but removing an alias that isn't there does */
2692         sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2693
2694         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2695                 "RemoveMultipleMembersFromAlias failed");
2696         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2697
2698         return true;
2699 }
2700
2701 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2702                                     struct torture_context *tctx,
2703                                     struct policy_handle *domain_handle)
2704 {
2705         struct samr_GetAliasMembership r;
2706         struct lsa_SidArray sids;
2707         struct samr_Ids rids;
2708
2709         torture_comment(tctx, "Testing GetAliasMembership\n");
2710
2711         r.in.domain_handle      = domain_handle;
2712         r.in.sids               = &sids;
2713         r.out.rids              = &rids;
2714
2715         sids.num_sids = 0;
2716         sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2717
2718         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2719                 "GetAliasMembership failed");
2720         torture_assert_ntstatus_ok(tctx, r.out.result,
2721                 "samr_GetAliasMembership failed");
2722
2723         torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2724                 "protocol misbehaviour");
2725
2726         sids.num_sids = 1;
2727         sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2728         sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2729
2730         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2731                 "samr_GetAliasMembership failed");
2732         torture_assert_ntstatus_ok(tctx, r.out.result,
2733                 "samr_GetAliasMembership failed");
2734
2735 #if 0
2736         /* only true for w2k8 it seems
2737          * win7, xp, w2k3 will return a 0 length array pointer */
2738
2739         if (rids.ids && (rids.count == 0)) {
2740                 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2741         }
2742 #endif
2743         if (!rids.ids && rids.count) {
2744                 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2745         }
2746
2747         return true;
2748 }
2749
2750 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2751                                           struct torture_context *tctx,
2752                                           struct policy_handle *user_handle)
2753 {
2754         struct samr_TestPrivateFunctionsUser r;
2755
2756         torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2757
2758         r.in.user_handle = user_handle;
2759
2760         torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2761                 "TestPrivateFunctionsUser failed");
2762         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2763
2764         return true;
2765 }
2766
2767 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2768                                           struct torture_context *tctx,
2769                                           struct policy_handle *handle,
2770                                           bool use_info2,
2771                                           NTTIME *pwdlastset)
2772 {
2773         NTSTATUS status;
2774         uint16_t levels[] = { /* 3, */ 5, 21 };
2775         int i;
2776         NTTIME pwdlastset3 = 0;
2777         NTTIME pwdlastset5 = 0;
2778         NTTIME pwdlastset21 = 0;
2779
2780         torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2781                         use_info2 ? "2":"");
2782
2783         for (i=0; i<ARRAY_SIZE(levels); i++) {
2784
2785                 struct samr_QueryUserInfo r;
2786                 struct samr_QueryUserInfo2 r2;
2787                 union samr_UserInfo *info;
2788
2789                 if (use_info2) {
2790                         r2.in.user_handle = handle;
2791                         r2.in.level = levels[i];
2792                         r2.out.info = &info;
2793                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2794                                 "QueryUserInfo2 failed");
2795                         status = r2.out.result;
2796
2797                 } else {
2798                         r.in.user_handle = handle;
2799                         r.in.level = levels[i];
2800                         r.out.info = &info;
2801                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2802                                 "QueryUserInfo failed");
2803                         status = r.out.result;
2804                 }
2805
2806                 if (!NT_STATUS_IS_OK(status) &&
2807                     !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2808                         torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2809                                use_info2 ? "2":"", levels[i], nt_errstr(status));
2810                         return false;
2811                 }
2812
2813                 switch (levels[i]) {
2814                 case 3:
2815                         pwdlastset3 = info->info3.last_password_change;
2816                         break;
2817                 case 5:
2818                         pwdlastset5 = info->info5.last_password_change;
2819                         break;
2820                 case 21:
2821                         pwdlastset21 = info->info21.last_password_change;
2822                         break;
2823                 default:
2824                         return false;
2825                 }
2826         }
2827         /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2828                                     "pwdlastset mixup"); */
2829         torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2830                                  "pwdlastset mixup");
2831
2832         *pwdlastset = pwdlastset21;
2833
2834         torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2835
2836         return true;
2837 }
2838
2839 static bool test_SamLogon(struct torture_context *tctx,
2840                           struct dcerpc_pipe *p,
2841                           struct cli_credentials *test_credentials,
2842                           NTSTATUS expected_result,
2843                           bool interactive)
2844 {
2845         NTSTATUS status;
2846         struct netr_LogonSamLogonEx r;
2847         union netr_LogonLevel logon;
2848         union netr_Validation validation;
2849         uint8_t authoritative;
2850         struct netr_IdentityInfo identity;
2851         struct netr_NetworkInfo ninfo;
2852         struct netr_PasswordInfo pinfo;
2853         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2854         int flags = CLI_CRED_NTLM_AUTH;
2855         uint32_t samlogon_flags = 0;
2856         struct netlogon_creds_CredentialState *creds;
2857         struct netr_Authenticator a;
2858         struct dcerpc_binding_handle *b = p->binding_handle;
2859
2860         torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2861
2862         if (lp_client_lanman_auth(tctx->lp_ctx)) {
2863                 flags |= CLI_CRED_LANMAN_AUTH;
2864         }
2865
2866         if (lp_client_ntlmv2_auth(tctx->lp_ctx)) {
2867                 flags |= CLI_CRED_NTLMv2_AUTH;
2868         }
2869
2870         cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2871                                                  &identity.account_name.string,
2872                                                  &identity.domain_name.string);
2873
2874         identity.parameter_control =
2875                 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2876                 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2877         identity.logon_id_low = 0;
2878         identity.logon_id_high = 0;
2879         identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2880
2881         if (interactive) {
2882                 netlogon_creds_client_authenticator(creds, &a);
2883
2884                 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
2885                         ZERO_STRUCT(pinfo.lmpassword.hash);
2886                 }
2887                 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
2888
2889                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
2890                         netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
2891                         netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
2892                 } else {
2893                         netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
2894                         netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
2895                 }
2896
2897                 pinfo.identity_info = identity;
2898                 logon.password = &pinfo;
2899
2900                 r.in.logon_level = NetlogonInteractiveInformation;
2901         } else {
2902                 generate_random_buffer(ninfo.challenge,
2903                                        sizeof(ninfo.challenge));
2904                 chal = data_blob_const(ninfo.challenge,
2905                                        sizeof(ninfo.challenge));
2906
2907                 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2908                                                         cli_credentials_get_domain(test_credentials));
2909
2910                 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2911                                                            &flags,
2912                                                            chal,
2913                                                            names_blob,
2914                                                            &lm_resp, &nt_resp,
2915                                                            NULL, NULL);
2916                 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2917
2918                 ninfo.lm.data = lm_resp.data;
2919                 ninfo.lm.length = lm_resp.length;
2920
2921                 ninfo.nt.data = nt_resp.data;
2922                 ninfo.nt.length = nt_resp.length;
2923
2924                 ninfo.identity_info = identity;
2925                 logon.network = &ninfo;
2926
2927                 r.in.logon_level = NetlogonNetworkInformation;
2928         }
2929
2930         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2931         r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2932         r.in.logon = &logon;
2933         r.in.flags = &samlogon_flags;
2934         r.out.flags = &samlogon_flags;
2935         r.out.validation = &validation;
2936         r.out.authoritative = &authoritative;
2937
2938         torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
2939
2940         r.in.validation_level = 6;
2941
2942         torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
2943                 "netr_LogonSamLogonEx failed");
2944         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
2945                 r.in.validation_level = 3;
2946                 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
2947                         "netr_LogonSamLogonEx failed");
2948         }
2949         if (!NT_STATUS_IS_OK(r.out.result)) {
2950                 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
2951                 return true;
2952         } else {
2953                 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
2954         }
2955
2956         return true;
2957 }
2958
2959 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2960                                      struct dcerpc_pipe *p,
2961                                      struct cli_credentials *machine_creds,
2962                                      const char *acct_name,
2963                                      const char *password,
2964                                      NTSTATUS expected_samlogon_result,
2965                                      bool interactive)
2966 {
2967         bool ret = true;
2968         struct cli_credentials *test_credentials;
2969
2970         test_credentials = cli_credentials_init(tctx);
2971
2972         cli_credentials_set_workstation(test_credentials,
2973                                         cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2974         cli_credentials_set_domain(test_credentials,
2975                                    cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2976         cli_credentials_set_username(test_credentials,
2977                                      acct_name, CRED_SPECIFIED);
2978         cli_credentials_set_password(test_credentials,
2979                                      password, CRED_SPECIFIED);
2980
2981         torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
2982                 interactive ? "interactive" : "network", acct_name, password);
2983
2984         if (!test_SamLogon(tctx, p, test_credentials,
2985                             expected_samlogon_result, interactive)) {
2986                 torture_warning(tctx, "new password did not work\n");
2987                 ret = false;
2988         }
2989
2990         return ret;
2991 }
2992
2993 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2994                                    struct dcerpc_pipe *np,
2995                                    struct torture_context *tctx,
2996                                    struct policy_handle *handle,
2997                                    uint16_t level,
2998                                    uint32_t fields_present,
2999                                    uint8_t password_expired,
3000                                    bool *matched_expected_error,
3001                                    bool use_setinfo2,
3002                                    const char *acct_name,
3003                                    char **password,
3004                                    struct cli_credentials *machine_creds,
3005                                    bool use_queryinfo2,
3006                                    NTTIME *pwdlastset,
3007                                    NTSTATUS expected_samlogon_result)
3008 {
3009         const char *fields = NULL;
3010         bool ret = true;
3011         struct dcerpc_binding_handle *b = p->binding_handle;
3012
3013         switch (level) {
3014         case 21:
3015         case 23:
3016         case 25:
3017                 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3018                                          fields_present);
3019                 break;
3020         default:
3021                 break;
3022         }
3023
3024         torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3025                 "(password_expired: %d) %s\n",
3026                 use_setinfo2 ? "2":"", level, password_expired,
3027                 fields ? fields : "");
3028
3029         if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3030                                        fields_present,
3031                                        password,
3032                                        password_expired,
3033                                        use_setinfo2,
3034                                        matched_expected_error)) {
3035                 ret = false;
3036         }
3037
3038         if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3039                                            use_queryinfo2,
3040                                            pwdlastset)) {
3041                 ret = false;
3042         }
3043
3044         if (*matched_expected_error == true) {
3045                 return ret;
3046         }
3047
3048         if (!test_SamLogon_with_creds(tctx, np,
3049                                       machine_creds,
3050                                       acct_name,
3051                                       *password,
3052                                       expected_samlogon_result,
3053                                       false)) {
3054                 ret = false;
3055         }
3056
3057         return ret;
3058 }
3059
3060 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3061                                          struct cli_credentials *credentials,
3062                                          struct dcerpc_pipe **p)
3063 {
3064         struct dcerpc_binding *b;
3065
3066         torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3067                 "failed to get rpc binding");
3068
3069         /* We have to use schannel, otherwise the SamLogonEx fails
3070          * with INTERNAL_ERROR */
3071
3072         b->flags &= ~DCERPC_AUTH_OPTIONS;
3073         b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
3074
3075         torture_assert_ntstatus_ok(tctx,
3076                 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3077                                       credentials, tctx->ev, tctx->lp_ctx),
3078                 "failed to bind to netlogon");
3079
3080         return true;
3081 }
3082
3083 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3084                                         struct torture_context *tctx,
3085                                         uint32_t acct_flags,
3086                                         const char *acct_name,
3087                                         struct policy_handle *handle,
3088                                         char **password,
3089                                         struct cli_credentials *machine_credentials)
3090 {
3091         int s = 0, q = 0, f = 0, l = 0, z = 0;
3092         bool ret = true;
3093         int delay = 50000;
3094         bool set_levels[] = { false, true };
3095         bool query_levels[] = { false, true };
3096         uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3097         uint32_t nonzeros[] = { 1, 24 };
3098         uint32_t fields_present[] = {
3099                 0,
3100                 SAMR_FIELD_EXPIRED_FLAG,
3101                 SAMR_FIELD_LAST_PWD_CHANGE,
3102                 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3103                 SAMR_FIELD_COMMENT,
3104                 SAMR_FIELD_NT_PASSWORD_PRESENT,
3105                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3106                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3107                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3108                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3109                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3110                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3111         };
3112         struct dcerpc_pipe *np = NULL;
3113
3114         if (torture_setting_bool(tctx, "samba3", false)) {
3115                 delay = 999999;
3116                 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3117                         delay);
3118         }
3119
3120         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3121
3122         /* set to 1 to enable testing for all possible opcode
3123            (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3124            combinations */
3125 #if 0
3126 #define TEST_ALL_LEVELS 1
3127 #define TEST_SET_LEVELS 1
3128 #define TEST_QUERY_LEVELS 1
3129 #endif
3130 #ifdef TEST_ALL_LEVELS
3131         for (l=0; l<ARRAY_SIZE(levels); l++) {
3132 #else
3133         for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3134 #endif
3135         for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3136         for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3137 #ifdef TEST_SET_LEVELS
3138         for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3139 #endif
3140 #ifdef TEST_QUERY_LEVELS
3141         for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3142 #endif
3143                 NTTIME pwdlastset_old = 0;
3144                 NTTIME pwdlastset_new = 0;
3145                 bool matched_expected_error = false;
3146                 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3147
3148                 torture_comment(tctx, "------------------------------\n"
3149                                 "Testing pwdLastSet attribute for flags: 0x%08x "
3150                                 "(s: %d (l: %d), q: %d)\n",
3151                                 acct_flags, s, levels[l], q);
3152
3153                 switch (levels[l]) {
3154                 case 21:
3155                 case 23:
3156                 case 25:
3157                         if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3158                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3159                                 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3160                         }
3161                         break;
3162                 }
3163
3164
3165                 /* set #1 */
3166
3167                 /* set a password and force password change (pwdlastset 0) by
3168                  * setting the password expired flag to a non-0 value */
3169
3170                 if (!test_SetPassword_level(p, np, tctx, handle,
3171                                             levels[l],
3172                                             fields_present[f],
3173                                             nonzeros[z],
3174                                             &matched_expected_error,
3175                                             set_levels[s],
3176                                             acct_name,
3177                                             password,
3178                                             machine_credentials,
3179                                             query_levels[q],
3180                                             &pwdlastset_new,
3181                                             expected_samlogon_result)) {
3182                         ret = false;
3183                 }
3184
3185                 if (matched_expected_error == true) {
3186                         /* skipping on expected failure */
3187                         continue;
3188                 }
3189
3190                 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3191                  * set without the SAMR_FIELD_EXPIRED_FLAG */
3192
3193                 switch (levels[l]) {
3194                 case 21:
3195                 case 23:
3196                 case 25:
3197                         if ((pwdlastset_new != 0) &&
3198                             !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3199                                 torture_comment(tctx, "not considering a non-0 "
3200                                         "pwdLastSet as a an error as the "
3201                                         "SAMR_FIELD_EXPIRED_FLAG has not "
3202                                         "been set\n");
3203                                 break;
3204                         }
3205                         break;
3206                 default:
3207                         if (pwdlastset_new != 0) {
3208                                 torture_warning(tctx, "pwdLastSet test failed: "
3209                                         "expected pwdLastSet 0 but got %lld\n",
3210                                         pwdlastset_old);
3211                                 ret = false;
3212                         }
3213                         break;
3214                 }
3215
3216                 switch (levels[l]) {
3217                 case 21:
3218                 case 23:
3219                 case 25:
3220                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3221                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3222                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3223                              (pwdlastset_old >= pwdlastset_new)) {
3224                                 torture_warning(tctx, "pwdlastset not increasing\n");
3225                                 ret = false;
3226                         }
3227                         break;
3228                 }
3229
3230                 pwdlastset_old = pwdlastset_new;
3231
3232                 usleep(delay);
3233
3234                 /* set #2 */
3235
3236                 /* set a password, pwdlastset needs to get updated (increased
3237                  * value), password_expired value used here is 0 */
3238
3239                 if (!test_SetPassword_level(p, np, tctx, handle,
3240                                             levels[l],
3241                                             fields_present[f],
3242                                             0,
3243                                             &matched_expected_error,
3244                                             set_levels[s],
3245                                             acct_name,
3246                                             password,
3247                                             machine_credentials,
3248                                             query_levels[q],
3249                                             &pwdlastset_new,
3250                                             expected_samlogon_result)) {
3251                         ret = false;
3252                 }
3253
3254                 /* when a password has been changed, pwdlastset must not be 0 afterwards
3255                  * and must be larger then the old value */
3256
3257                 switch (levels[l]) {
3258                 case 21:
3259                 case 23:
3260                 case 25:
3261                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3262                          * password has been changed, old and new pwdlastset
3263                          * need to be the same value */
3264
3265                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3266                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3267                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3268                         {
3269                                 torture_assert_int_equal(tctx, pwdlastset_old,
3270                                         pwdlastset_new, "pwdlastset must be equal");
3271                                 break;
3272                         }
3273                         break;
3274                 default:
3275                         if (pwdlastset_old >= pwdlastset_new) {
3276                                 torture_warning(tctx, "pwdLastSet test failed: "
3277                                         "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3278                                         pwdlastset_old, pwdlastset_new);
3279                                 ret = false;
3280                         }
3281                         if (pwdlastset_new == 0) {
3282                                 torture_warning(tctx, "pwdLastSet test failed: "
3283                                         "expected non-0 pwdlastset, got: %lld\n",
3284                                         pwdlastset_new);
3285                                 ret = false;
3286                         }
3287                         break;
3288                 }
3289
3290                 switch (levels[l]) {
3291                 case 21:
3292                 case 23:
3293                 case 25:
3294                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3295                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3296                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3297                              (pwdlastset_old >= pwdlastset_new)) {
3298                                 torture_warning(tctx, "pwdlastset not increasing\n");
3299                                 ret = false;
3300                         }
3301                         break;
3302                 }
3303
3304                 pwdlastset_old = pwdlastset_new;
3305
3306                 usleep(delay);
3307
3308                 /* set #2b */
3309
3310                 /* set a password, pwdlastset needs to get updated (increased
3311                  * value), password_expired value used here is 0 */
3312
3313                 if (!test_SetPassword_level(p, np, tctx, handle,
3314                                             levels[l],
3315                                             fields_present[f],
3316                                             0,
3317                                             &matched_expected_error,
3318                                             set_levels[s],
3319                                             acct_name,
3320                                             password,
3321                                             machine_credentials,
3322                                             query_levels[q],
3323                                             &pwdlastset_new,
3324                                             expected_samlogon_result)) {
3325                         ret = false;
3326                 }
3327
3328                 /* when a password has been changed, pwdlastset must not be 0 afterwards
3329                  * and must be larger then the old value */
3330
3331                 switch (levels[l]) {
3332                 case 21:
3333                 case 23:
3334                 case 25:
3335
3336                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3337                          * password has been changed, old and new pwdlastset
3338                          * need to be the same value */
3339
3340                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3341                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3342                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3343                         {
3344                                 torture_assert_int_equal(tctx, pwdlastset_old,
3345                                         pwdlastset_new, "pwdlastset must be equal");
3346                                 break;
3347                         }
3348                         break;
3349                 default:
3350                         if (pwdlastset_old >= pwdlastset_new) {
3351                                 torture_warning(tctx, "pwdLastSet test failed: "
3352                                         "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
3353                                         pwdlastset_old, pwdlastset_new);
3354                                 ret = false;
3355                         }
3356                         if (pwdlastset_new == 0) {
3357                                 torture_warning(tctx, "pwdLastSet test failed: "
3358                                         "expected non-0 pwdlastset, got: %lld\n",
3359                                         pwdlastset_new);
3360                                 ret = false;
3361                         }
3362                         break;
3363                 }
3364
3365                 switch (levels[l]) {
3366                 case 21:
3367                 case 23:
3368                 case 25:
3369                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3370                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3371                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3372                              (pwdlastset_old >= pwdlastset_new)) {
3373                                 torture_warning(tctx, "pwdlastset not increasing\n");
3374                                 ret = false;
3375                         }
3376                         break;
3377                 }
3378
3379                 pwdlastset_old = pwdlastset_new;
3380
3381                 usleep(delay);
3382
3383                 /* set #3 */
3384
3385                 /* set a password and force password change (pwdlastset 0) by
3386                  * setting the password expired flag to a non-0 value */
3387
3388                 if (!test_SetPassword_level(p, np, tctx, handle,
3389                                             levels[l],
3390                                             fields_present[f],
3391                                             nonzeros[z],
3392                                             &matched_expected_error,
3393                                             set_levels[s],
3394                                             acct_name,
3395                                             password,
3396                                             machine_credentials,
3397                                             query_levels[q],
3398                                             &pwdlastset_new,
3399                                             expected_samlogon_result)) {
3400                         ret = false;
3401                 }
3402
3403                 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3404                  * set without the SAMR_FIELD_EXPIRED_FLAG */
3405
3406                 switch (levels[l]) {
3407                 case 21:
3408                 case 23:
3409                 case 25:
3410                         if ((pwdlastset_new != 0) &&
3411                             !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3412                                 torture_comment(tctx, "not considering a non-0 "
3413                                         "pwdLastSet as a an error as the "
3414                                         "SAMR_FIELD_EXPIRED_FLAG has not "
3415                                         "been set\n");
3416                                 break;
3417                         }
3418
3419                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3420                          * password has been changed, old and new pwdlastset
3421                          * need to be the same value */
3422
3423                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3424                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3425                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3426                         {
3427                                 torture_assert_int_equal(tctx, pwdlastset_old,
3428                                         pwdlastset_new, "pwdlastset must be equal");
3429                                 break;
3430                         }
3431                         break;
3432                 default:
3433                         if (pwdlastset_new != 0) {
3434                                 torture_warning(tctx, "pwdLastSet test failed: "
3435                                         "expected pwdLastSet 0, got %lld\n",
3436                                         pwdlastset_old);
3437                                 ret = false;
3438                         }
3439                         break;
3440                 }
3441
3442                 switch (levels[l]) {
3443                 case 21:
3444                 case 23:
3445                 case 25:
3446                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3447                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3448                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3449                              (pwdlastset_old >= pwdlastset_new)) {
3450                                 torture_warning(tctx, "pwdlastset not increasing\n");
3451                                 ret = false;
3452                         }
3453                         break;
3454                 }
3455
3456                 /* if the level we are testing does not have a fields_present
3457                  * field, skip all fields present tests by setting f to to
3458                  * arraysize */
3459                 switch (levels[l]) {
3460                 case 18:
3461                 case 24:
3462                 case 26:
3463                         f = ARRAY_SIZE(fields_present);
3464                         break;
3465                 }
3466
3467 #ifdef TEST_QUERY_LEVELS
3468         }
3469 #endif
3470 #ifdef TEST_SET_LEVELS
3471         }
3472 #endif
3473         } /* fields present */
3474         } /* nonzeros */
3475         } /* levels */
3476
3477 #undef TEST_SET_LEVELS
3478 #undef TEST_QUERY_LEVELS
3479
3480         talloc_free(np);
3481
3482         return ret;
3483 }
3484
3485 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3486                                            struct torture_context *tctx,
3487                                            struct policy_handle *handle,
3488                                            uint32_t *badpwdcount)
3489 {
3490         union samr_UserInfo *info;
3491         struct samr_QueryUserInfo r;
3492
3493         r.in.user_handle = handle;
3494         r.in.level = 3;
3495         r.out.info = &info;
3496
3497         torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3498
3499         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3500                 "failed to query userinfo");
3501         torture_assert_ntstatus_ok(tctx, r.out.result,
3502                 "failed to query userinfo");
3503
3504         *badpwdcount = info->info3.bad_password_count;
3505
3506         torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3507
3508         return true;
3509 }
3510
3511 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3512                                         struct torture_context *tctx,
3513                                         struct policy_handle *user_handle,
3514                                         uint32_t acct_flags)
3515 {
3516         struct samr_SetUserInfo r;
3517         union samr_UserInfo user_info;
3518
3519         torture_comment(tctx, "Testing SetUserInfo level 16\n");
3520
3521         user_info.info16.acct_flags = acct_flags;
3522
3523         r.in.user_handle = user_handle;
3524         r.in.level = 16;
3525         r.in.info = &user_info;
3526
3527         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3528                 "failed to set account flags");
3529         torture_assert_ntstatus_ok(tctx, r.out.result,
3530                 "failed to set account flags");
3531
3532         return true;
3533 }
3534
3535 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3536                                    struct torture_context *tctx,
3537                                    struct policy_handle *user_handle,
3538                                    uint32_t acct_flags,
3539                                    char **password)
3540 {
3541         struct dcerpc_binding_handle *b = p->binding_handle;
3542
3543         torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3544                 "failed to set password");
3545
3546         torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3547
3548         torture_assert(tctx,
3549                        test_SetUserInfo_acct_flags(b, tctx, user_handle,
3550                                                    acct_flags & ~ACB_DISABLED),
3551                        "failed to enable user");
3552
3553         torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3554                 "failed to set password");
3555
3556         return true;
3557 }
3558
3559 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3560                                struct torture_context *tctx,
3561                                struct policy_handle *domain_handle,
3562                                enum samr_DomainInfoClass level,
3563                                union samr_DomainInfo *info)
3564 {
3565         struct samr_SetDomainInfo r;
3566
3567         r.in.domain_handle = domain_handle;
3568         r.in.level = level;
3569         r.in.info = info;
3570
3571         torture_assert_ntstatus_ok(tctx,
3572                                    dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3573                                    "failed to set domain info");
3574         torture_assert_ntstatus_ok(tctx, r.out.result,
3575                                    "failed to set domain info");
3576
3577         return true;
3578 }
3579
3580 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3581                                         struct torture_context *tctx,
3582                                         struct policy_handle *domain_handle,
3583                                         enum samr_DomainInfoClass level,
3584                                         union samr_DomainInfo *info,
3585                                         NTSTATUS expected)
3586 {
3587         struct samr_SetDomainInfo r;
3588
3589         r.in.domain_handle = domain_handle;
3590         r.in.level = level;
3591         r.in.info = info;
3592
3593         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3594                 "SetDomainInfo failed");
3595         torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3596
3597         return true;
3598 }
3599
3600 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3601                                         struct torture_context *tctx,
3602                                         struct policy_handle *domain_handle,
3603                                         enum samr_DomainInfoClass level,
3604                                         union samr_DomainInfo **q_info)
3605 {
3606         struct samr_QueryDomainInfo2 r;
3607
3608         r.in.domain_handle = domain_handle;
3609         r.in.level = level;
3610         r.out.info = q_info;
3611
3612         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3613                 "failed to query domain info");
3614         torture_assert_ntstatus_ok(tctx, r.out.result,
3615                 "failed to query domain info");
3616
3617         return true;
3618 }
3619
3620 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3621                                       struct dcerpc_pipe *np,
3622                                       struct torture_context *tctx,
3623                                       uint32_t acct_flags,
3624                                       const char *acct_name,
3625                                       struct policy_handle *domain_handle,
3626                                       struct policy_handle *user_handle,
3627                                       char **password,
3628                                       struct cli_credentials *machine_credentials,
3629                                       const char *comment,
3630                                       bool disable,
3631                                       bool interactive,
3632                                       NTSTATUS expected_success_status,
3633                                       struct samr_DomInfo1 *info1,
3634                                       struct samr_DomInfo12 *info12)
3635 {
3636         union samr_DomainInfo info;
3637         char **passwords;
3638         int i;
3639         uint32_t badpwdcount, tmp;
3640         uint32_t password_history_length = 12;
3641         uint32_t lockout_threshold = 15;
3642         struct dcerpc_binding_handle *b = p->binding_handle;
3643
3644         torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3645
3646         torture_assert(tctx, password_history_length < lockout_threshold,
3647                 "password history length needs to be smaller than account lockout threshold for this test");
3648
3649
3650         /* set policies */
3651
3652         info.info1 = *info1;
3653         info.info1.password_history_length = password_history_length;
3654
3655         torture_assert(tctx,
3656                        test_SetDomainInfo(b, tctx, domain_handle,
3657                                           DomainPasswordInformation, &info),
3658                        "failed to set password history length");
3659
3660         info.info12 = *info12;
3661         info.info12.lockout_threshold = lockout_threshold;
3662
3663         torture_assert(tctx,
3664                        test_SetDomainInfo(b, tctx, domain_handle,
3665                                           DomainLockoutInformation, &info),
3666                        "failed to set lockout threshold");
3667
3668         /* reset bad pwd count */
3669
3670         torture_assert(tctx,
3671                 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3672
3673
3674         /* enable or disable account */
3675         if (disable) {
3676                 torture_assert(tctx,
3677                                test_SetUserInfo_acct_flags(b, tctx, user_handle,
3678                                                 acct_flags | ACB_DISABLED),
3679                                "failed to disable user");
3680         } else {
3681                 torture_assert(tctx,
3682                                test_SetUserInfo_acct_flags(b, tctx, user_handle,
3683                                                 acct_flags & ~ACB_DISABLED),
3684                                "failed to enable user");
3685         }
3686
3687
3688         /* setup password history */
3689
3690         passwords = talloc_array(tctx, char *, password_history_length);
3691
3692         for (i=0; i < password_history_length; i++) {
3693
3694                 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3695                         "failed to set password");
3696                 passwords[i] = talloc_strdup(tctx, *password);
3697
3698                 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3699                                               acct_name, passwords[i],
3700                                               expected_success_status, interactive)) {
3701                         torture_fail(tctx, "failed to auth with latest password");
3702                 }
3703
3704                 torture_assert(tctx,
3705                         test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3706
3707                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3708         }
3709
3710
3711         /* test with wrong password */
3712
3713         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3714                                       acct_name, "random_crap",
3715                                       NT_STATUS_WRONG_PASSWORD, interactive)) {
3716                 torture_fail(tctx, "succeeded to authenticate with wrong password");
3717         }
3718
3719         torture_assert(tctx,
3720                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3721
3722         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3723
3724
3725         /* test with latest good password */
3726
3727         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3728                                       passwords[password_history_length-1],
3729                                       expected_success_status, interactive)) {
3730                 torture_fail(tctx, "succeeded to authenticate with wrong password");
3731         }
3732
3733         torture_assert(tctx,
3734                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3735
3736         if (disable) {
3737                 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3738         } else {
3739                 /* only enabled accounts get the bad pwd count reset upon
3740                  * successful logon */
3741                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3742         }
3743
3744         tmp = badpwdcount;
3745
3746
3747         /* test password history */
3748
3749         for (i=0; i < password_history_length; i++) {
3750
3751                 torture_comment(tctx, "Testing bad password count behavior with "
3752                                       "password #%d of #%d\n", i, password_history_length);
3753
3754                 /* - network samlogon will succeed auth and not
3755                  *   increase badpwdcount for 2 last entries
3756                  * - interactive samlogon only for the last one */
3757
3758                 if (i == password_history_length - 1 ||
3759                     (i == password_history_length - 2 && !interactive)) {
3760
3761                         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3762                                                       acct_name, passwords[i],
3763                                                       expected_success_status, interactive)) {
3764                                 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3765                         }
3766
3767                         torture_assert(tctx,
3768                                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3769
3770                         if (disable) {
3771                                 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3772                                 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3773                         } else {
3774                                 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3775                                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3776                         }
3777
3778                         tmp = badpwdcount;
3779
3780                         continue;
3781                 }
3782
3783                 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3784                                               acct_name, passwords[i],
3785                                               NT_STATUS_WRONG_PASSWORD, interactive)) {
3786                         torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3787                 }
3788
3789                 torture_assert(tctx,
3790                         test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3791
3792                 /* - network samlogon will fail auth but not increase
3793                  *   badpwdcount for 3rd last entry
3794                  * - interactive samlogon for 3rd and 2nd last entry */
3795
3796                 if (i == password_history_length - 3 ||
3797                     (i == password_history_length - 2 && interactive)) {
3798                         /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3799                         torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3800                 } else {
3801                         /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3802                         torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3803                 }
3804
3805                 tmp = badpwdcount;
3806         }
3807
3808         return true;
3809 }
3810
3811 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3812                                            struct torture_context *tctx,
3813                                            uint32_t acct_flags,
3814                                            const char *acct_name,
3815                                            struct policy_handle *domain_handle,
3816                                            struct policy_handle *user_handle,
3817                                            char **password,
3818                                            struct cli_credentials *machine_credentials)
3819 {
3820         union samr_DomainInfo *q_info, s_info;
3821         struct samr_DomInfo1 info1, _info1;
3822         struct samr_DomInfo12 info12, _info12;
3823         bool ret = true;
3824         struct dcerpc_binding_handle *b = p->binding_handle;
3825         struct dcerpc_pipe *np;
3826         int i;
3827
3828         struct {
3829                 const char *comment;
3830                 bool disabled;
3831                 bool interactive;
3832                 NTSTATUS expected_success_status;
3833         } creds[] = {
3834                 {
3835                         .comment                = "network logon (disabled account)",
3836                         .disabled               = true,
3837                         .interactive            = false,
3838                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3839                 },
3840                 {
3841                         .comment                = "network logon (enabled account)",
3842                         .disabled               = false,
3843                         .interactive            = false,
3844                         .expected_success_status= NT_STATUS_OK
3845                 },
3846                 {
3847                         .comment                = "interactive logon (disabled account)",
3848                         .disabled               = true,
3849                         .interactive            = true,
3850                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3851                 },
3852                 {
3853                         .comment                = "interactive logon (enabled account)",
3854                         .disabled               = false,
3855                         .interactive            = true,
3856                         .expected_success_status= NT_STATUS_OK
3857                 },
3858         };
3859
3860         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3861
3862         /* backup old policies */
3863
3864         torture_assert(tctx,
3865                 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3866                                             DomainPasswordInformation, &q_info),
3867                 "failed to query domain info level 1");
3868
3869         info1 = q_info->info1;
3870         _info1 = info1;
3871
3872         torture_assert(tctx,
3873                 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3874                                             DomainLockoutInformation, &q_info),
3875                 "failed to query domain info level 12");
3876
3877         info12 = q_info->info12;
3878         _info12 = info12;
3879
3880         /* run tests */
3881
3882         for (i=0; i < ARRAY_SIZE(creds); i++) {
3883
3884                 /* skip trust tests for now */
3885                 if (acct_flags & ACB_WSTRUST ||
3886                     acct_flags & ACB_SVRTRUST ||
3887                     acct_flags & ACB_DOMTRUST) {
3888                         continue;
3889                 }
3890
3891                 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
3892                                                  domain_handle, user_handle, password,
3893                                                  machine_credentials,
3894                                                  creds[i].comment,
3895                                                  creds[i].disabled,
3896                                                  creds[i].interactive,
3897                                                  creds[i].expected_success_status,
3898                                                  &_info1, &_info12);
3899                 if (!ret) {
3900                         torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
3901                 } else {
3902                         torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
3903                 }
3904         }
3905
3906         /* restore policies */
3907
3908         s_info.info1 = info1;
3909
3910         torture_assert(tctx,
3911                        test_SetDomainInfo(b, tctx, domain_handle,
3912                                           DomainPasswordInformation, &s_info),
3913                        "failed to set password information");
3914
3915         s_info.info12 = info12;
3916
3917         torture_assert(tctx,
3918                        test_SetDomainInfo(b, tctx, domain_handle,
3919                                           DomainLockoutInformation, &s_info),
3920                        "failed to set lockout information");
3921
3922         return ret;
3923 }
3924
3925 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3926                                           struct torture_context *tctx,
3927                                           struct policy_handle *handle,
3928                                           uint32_t *acct_flags)
3929 {
3930         union samr_UserInfo *info;
3931         struct samr_QueryUserInfo r;
3932
3933         r.in.user_handle = handle;
3934         r.in.level = 16;
3935         r.out.info = &info;
3936
3937         torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3938
3939         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3940                 "failed to query userinfo");
3941         torture_assert_ntstatus_ok(tctx, r.out.result,
3942                 "failed to query userinfo");
3943
3944         *acct_flags = info->info16.acct_flags;
3945
3946         torture_comment(tctx, "  (acct_flags: 0x%08x)\n", *acct_flags);
3947
3948         return true;
3949 }
3950
3951 static bool test_Password_lockout(struct dcerpc_pipe *p,
3952                                   struct dcerpc_pipe *np,
3953                                   struct torture_context *tctx,
3954                                   uint32_t acct_flags,
3955                                   const char *acct_name,
3956                                   struct policy_handle *domain_handle,
3957                                   struct policy_handle *user_handle,
3958                                   char **password,
3959                                   struct cli_credentials *machine_credentials,
3960                                   const char *comment,
3961                                   bool disable,
3962                                   bool interactive,
3963                                   NTSTATUS expected_success_status,
3964                                   struct samr_DomInfo1 *info1,
3965                                   struct samr_DomInfo12 *info12)
3966 {
3967         union samr_DomainInfo info;
3968         uint32_t badpwdcount;
3969         uint32_t password_history_length = 1;
3970         uint64_t lockout_threshold = 1;
3971         uint32_t lockout_seconds = 5;
3972         uint64_t delta_time_factor = 10 * 1000 * 1000;
3973         struct dcerpc_binding_handle *b = p->binding_handle;
3974
3975         torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
3976
3977         /* set policies */
3978
3979         info.info1 = *info1;
3980
3981         torture_comment(tctx, "setting password history length.\n");
3982         info.info1.password_history_length = password_history_length;
3983
3984         torture_assert(tctx,
3985                        test_SetDomainInfo(b, tctx, domain_handle,
3986                                           DomainPasswordInformation, &info),
3987                        "failed to set password history length");
3988
3989         info.info12 = *info12;
3990         info.info12.lockout_threshold = lockout_threshold;
3991
3992         /* set lockout duration < lockout window: should fail */
3993         info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3994         info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
3995
3996         torture_assert(tctx,
3997                 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
3998                                             DomainLockoutInformation, &info,
3999                                             NT_STATUS_INVALID_PARAMETER),
4000                 "setting lockout duration < lockout window gave unexpected result");
4001
4002         info.info12.lockout_duration = 0;
4003         info.info12.lockout_window = 0;
4004
4005         torture_assert(tctx,
4006                        test_SetDomainInfo(b, tctx, domain_handle,
4007                                           DomainLockoutInformation, &info),
4008                        "failed to set lockout window and duration to 0");
4009
4010
4011         /* set lockout duration of 5 seconds */
4012         info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4013         info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4014
4015         torture_assert(tctx,
4016                        test_SetDomainInfo(b, tctx, domain_handle,
4017                                           DomainLockoutInformation, &info),
4018                        "failed to set lockout window and duration to 5 seconds");
4019
4020         /* reset bad pwd count */
4021
4022         torture_assert(tctx,
4023                 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4024
4025
4026         /* enable or disable account */
4027
4028         if (disable) {
4029                 torture_assert(tctx,
4030                                test_SetUserInfo_acct_flags(b, tctx, user_handle,
4031                                                 acct_flags | ACB_DISABLED),
4032                                "failed to disable user");
4033         } else {
4034                 torture_assert(tctx,
4035                                test_SetUserInfo_acct_flags(b, tctx, user_handle,
4036                                                 acct_flags & ~ACB_DISABLED),
4037                                "failed to enable user");
4038         }
4039
4040
4041         /* test logon with right password */
4042
4043         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4044                                       acct_name, *password,
4045                                       expected_success_status, interactive)) {
4046                 torture_fail(tctx, "failed to auth with latest password");
4047         }
4048
4049         torture_assert(tctx,
4050                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4051         torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4052
4053
4054         /* test with wrong password ==> lockout */
4055
4056         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4057                                       acct_name, "random_crap",
4058                                       NT_STATUS_WRONG_PASSWORD, interactive)) {
4059                 torture_fail(tctx, "succeeded to authenticate with wrong password");
4060         }
4061
4062         torture_assert(tctx,
4063                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4064         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4065
4066         torture_assert(tctx,
4067                 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4068         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4069                                  "expected account to be locked");
4070
4071
4072         /* test with good password */
4073
4074         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4075                                      *password,
4076                                      NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4077         {
4078                 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4079         }
4080
4081         /* bad pwd count should not get updated */
4082         torture_assert(tctx,
4083                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4084         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4085
4086         /* curiously, windows does _not_ set the autlock flag */
4087         torture_assert(tctx,
4088                 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4089         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4090                                  "expected account to be locked");
4091
4092
4093         /* with bad password */
4094
4095         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4096                                       acct_name, "random_crap2",
4097                                       NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4098         {
4099                 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4100         }
4101
4102         /* bad pwd count should not get updated */
4103         torture_assert(tctx,
4104                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4105         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4106
4107         /* curiously, windows does _not_ set the autlock flag */
4108         torture_assert(tctx,
4109                 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4110         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4111                                  "expected account to be locked");
4112
4113
4114         /* let lockout duration expire ==> unlock */
4115
4116         torture_comment(tctx, "let lockout duration expire...\n");
4117         sleep(lockout_seconds + 1);
4118
4119         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4120                                      *password,
4121                                      expected_success_status, interactive))
4122         {
4123                 torture_fail(tctx, "failed to authenticate after lockout expired");
4124         }
4125
4126         torture_assert(tctx,
4127                 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4128         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4129                                  "expected account not to be locked");
4130
4131         return true;
4132 }
4133
4134 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4135                                        struct torture_context *tctx,
4136                                        uint32_t acct_flags,
4137                                        const char *acct_name,
4138                                        struct policy_handle *domain_handle,
4139                                        struct policy_handle *user_handle,
4140                                        char **password,
4141                                        struct cli_credentials *machine_credentials)
4142 {
4143         union samr_DomainInfo *q_info, s_info;
4144         struct samr_DomInfo1 info1, _info1;
4145         struct samr_DomInfo12 info12, _info12;
4146         bool ret = true;
4147         struct dcerpc_binding_handle *b = p->binding_handle;
4148         struct dcerpc_pipe *np;
4149         int i;
4150
4151         struct {
4152                 const char *comment;
4153                 bool disabled;
4154                 bool interactive;
4155                 NTSTATUS expected_success_status;
4156         } creds[] = {
4157                 {
4158                         .comment                = "network logon (disabled account)",
4159                         .disabled               = true,
4160                         .interactive            = false,
4161                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4162                 },
4163                 {
4164                         .comment                = "network logon (enabled account)",
4165                         .disabled               = false,
4166                         .interactive            = false,
4167                         .expected_success_status= NT_STATUS_OK
4168                 },
4169                 {
4170                         .comment                = "interactive logon (disabled account)",
4171                         .disabled               = true,
4172                         .interactive            = true,
4173                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4174                 },
4175                 {
4176                         .comment                = "interactive logon (enabled account)",
4177                         .disabled               = false,
4178                         .interactive            = true,
4179                         .expected_success_status= NT_STATUS_OK
4180                 },
4181         };
4182
4183         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4184
4185         /* backup old policies */
4186
4187         torture_assert(tctx,
4188                 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4189                                             DomainPasswordInformation, &q_info),
4190                 "failed to query domain info level 1");
4191
4192         info1 = q_info->info1;
4193         _info1 = info1;
4194
4195         torture_assert(tctx,
4196                 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4197                                             DomainLockoutInformation, &q_info),
4198                 "failed to query domain info level 12");
4199
4200         info12 = q_info->info12;
4201         _info12 = info12;
4202
4203         /* run tests */
4204
4205         for (i=0; i < ARRAY_SIZE(creds); i++) {
4206
4207                 /* skip trust tests for now */
4208                 if (acct_flags & ACB_WSTRUST ||
4209                     acct_flags & ACB_SVRTRUST ||
4210                     acct_flags & ACB_DOMTRUST) {
4211                         continue;
4212                 }
4213
4214                 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4215                                              domain_handle, user_handle, password,
4216                                              machine_credentials,
4217                                              creds[i].comment,
4218                                              creds[i].disabled,
4219                                              creds[i].interactive,
4220                                              creds[i].expected_success_status,
4221                                              &_info1, &_info12);
4222                 if (!ret) {
4223                         torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4224                 } else {
4225                         torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4226                 }
4227         }
4228
4229         /* restore policies */
4230
4231         s_info.info1 = info1;
4232
4233         torture_assert(tctx,
4234                        test_SetDomainInfo(b, tctx, domain_handle,
4235                                           DomainPasswordInformation, &s_info),
4236                        "failed to set password information");
4237
4238         s_info.info12 = info12;
4239
4240         torture_assert(tctx,
4241                        test_SetDomainInfo(b, tctx, domain_handle,
4242                                           DomainLockoutInformation, &s_info),
4243                        "failed to set lockout information");
4244
4245         return ret;
4246 }
4247
4248 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4249                                        struct dcerpc_pipe *lp,
4250                                        struct torture_context *tctx,
4251                                        struct policy_handle *domain_handle,
4252                                        struct policy_handle *lsa_handle,
4253                                        struct policy_handle *user_handle,
4254                                        const struct dom_sid *domain_sid,
4255                                        uint32_t rid,
4256                                        struct cli_credentials *machine_credentials)
4257 {
4258         bool ret = true;
4259         struct dcerpc_binding_handle *b = p->binding_handle;
4260         struct dcerpc_binding_handle *lb = lp->binding_handle;
4261
4262         struct policy_handle lsa_acct_handle;
4263         struct dom_sid *user_sid;
4264
4265         user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4266
4267         {
4268                 struct lsa_EnumAccountRights r;
4269                 struct lsa_RightSet rights;
4270
4271                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4272
4273                 r.in.handle = lsa_handle;
4274                 r.in.sid = user_sid;
4275                 r.out.rights = &rights;
4276
4277                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4278                         "lsa_EnumAccountRights failed");
4279                 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4280                         "Expected enum rights for account to fail");
4281         }
4282
4283         {
4284                 struct lsa_RightSet rights;
4285                 struct lsa_StringLarge names[2];
4286                 struct lsa_AddAccountRights r;
4287
4288                 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4289
4290                 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4291                 init_lsa_StringLarge(&names[1], NULL);
4292
4293                 rights.count = 1;
4294                 rights.names = names;
4295
4296                 r.in.handle = lsa_handle;
4297                 r.in.sid = user_sid;
4298                 r.in.rights = &rights;
4299
4300                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4301                         "lsa_AddAccountRights failed");
4302                 torture_assert_ntstatus_ok(tctx, r.out.result,
4303                         "Failed to add privileges");
4304         }
4305
4306         {
4307                 struct lsa_EnumAccounts r;
4308                 uint32_t resume_handle = 0;
4309                 struct lsa_SidArray lsa_sid_array;
4310                 int i;
4311                 bool found_sid = false;
4312
4313                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4314
4315                 r.in.handle = lsa_handle;
4316                 r.in.num_entries = 0x1000;
4317                 r.in.resume_handle = &resume_handle;
4318                 r.out.sids = &lsa_sid_array;
4319                 r.out.resume_handle = &resume_handle;
4320
4321                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4322                         "lsa_EnumAccounts failed");
4323                 torture_assert_ntstatus_ok(tctx, r.out.result,
4324                         "Failed to enum accounts");
4325
4326                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4327                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4328                                 found_sid = true;
4329                         }
4330                 }
4331
4332                 torture_assert(tctx, found_sid,
4333                         "failed to list privileged account");
4334         }
4335
4336         {
4337                 struct lsa_EnumAccountRights r;
4338                 struct lsa_RightSet user_rights;
4339
4340                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4341
4342                 r.in.handle = lsa_handle;
4343                 r.in.sid = user_sid;
4344                 r.out.rights = &user_rights;
4345
4346                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4347                         "lsa_EnumAccountRights failed");
4348                 torture_assert_ntstatus_ok(tctx, r.out.result,
4349                         "Failed to enum rights for account");
4350
4351                 if (user_rights.count < 1) {
4352                         torture_warning(tctx, "failed to find newly added rights");
4353                         return false;
4354                 }
4355         }
4356
4357         {
4358                 struct lsa_OpenAccount r;
4359
4360                 torture_comment(tctx, "Testing LSA OpenAccount\n");
4361
4362                 r.in.handle = lsa_handle;
4363                 r.in.sid = user_sid;
4364                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4365                 r.out.acct_handle = &lsa_acct_handle;
4366
4367                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4368                         "lsa_OpenAccount failed");
4369                 torture_assert_ntstatus_ok(tctx, r.out.result,
4370                         "Failed to open lsa account");
4371         }
4372
4373         {
4374                 struct lsa_GetSystemAccessAccount r;
4375                 uint32_t access_mask;
4376
4377                 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4378
4379                 r.in.handle = &lsa_acct_handle;
4380                 r.out.access_mask = &access_mask;
4381
4382                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4383                         "lsa_GetSystemAccessAccount failed");
4384                 torture_assert_ntstatus_ok(tctx, r.out.result,
4385                         "Failed to get lsa system access account");
4386         }
4387
4388         {
4389                 struct lsa_Close r;
4390
4391                 torture_comment(tctx, "Testing LSA Close\n");
4392
4393                 r.in.handle = &lsa_acct_handle;
4394                 r.out.handle = &lsa_acct_handle;
4395
4396                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4397                         "lsa_Close failed");
4398                 torture_assert_ntstatus_ok(tctx, r.out.result,
4399                         "Failed to close lsa");
4400         }
4401
4402         {
4403                 struct samr_DeleteUser r;
4404
4405                 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4406
4407                 r.in.user_handle = user_handle;
4408                 r.out.user_handle = user_handle;
4409
4410                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4411                         "DeleteUser failed");
4412                 torture_assert_ntstatus_ok(tctx, r.out.result,
4413                         "DeleteUser failed");
4414         }
4415
4416         {
4417                 struct lsa_EnumAccounts r;
4418                 uint32_t resume_handle = 0;
4419                 struct lsa_SidArray lsa_sid_array;
4420                 int i;
4421                 bool found_sid = false;
4422
4423                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4424
4425                 r.in.handle = lsa_handle;
4426                 r.in.num_entries = 0x1000;
4427                 r.in.resume_handle = &resume_handle;
4428                 r.out.sids = &lsa_sid_array;
4429                 r.out.resume_handle = &resume_handle;
4430
4431                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4432                         "lsa_EnumAccounts failed");
4433                 torture_assert_ntstatus_ok(tctx, r.out.result,
4434                         "Failed to enum accounts");
4435
4436                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4437                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4438                                 found_sid = true;
4439                         }
4440                 }
4441
4442                 torture_assert(tctx, found_sid,
4443                         "failed to list privileged account");
4444         }
4445
4446         {
4447                 struct lsa_EnumAccountRights r;
4448                 struct lsa_RightSet user_rights;
4449
4450                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4451
4452                 r.in.handle = lsa_handle;
4453                 r.in.sid = user_sid;
4454                 r.out.rights = &user_rights;
4455
4456                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4457                         "lsa_EnumAccountRights failed");
4458                 torture_assert_ntstatus_ok(tctx, r.out.result,
4459                         "Failed to enum rights for account");
4460
4461                 if (user_rights.count < 1) {
4462                         torture_warning(tctx, "failed to find newly added rights");
4463                         return false;
4464                 }
4465         }
4466
4467         {
4468                 struct lsa_OpenAccount r;
4469
4470                 torture_comment(tctx, "Testing LSA OpenAccount\n");
4471
4472                 r.in.handle = lsa_handle;
4473                 r.in.sid = user_sid;
4474                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4475                 r.out.acct_handle = &lsa_acct_handle;
4476
4477                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4478                         "lsa_OpenAccount failed");
4479                 torture_assert_ntstatus_ok(tctx, r.out.result,
4480                         "Failed to open lsa account");
4481         }
4482
4483         {
4484                 struct lsa_GetSystemAccessAccount r;
4485                 uint32_t access_mask;
4486
4487                 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4488
4489                 r.in.handle = &lsa_acct_handle;
4490                 r.out.access_mask = &access_mask;
4491
4492                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4493                         "lsa_GetSystemAccessAccount failed");
4494                 torture_assert_ntstatus_ok(tctx, r.out.result,
4495                         "Failed to get lsa system access account");
4496         }
4497
4498         {
4499                 struct lsa_DeleteObject r;
4500
4501                 torture_comment(tctx, "Testing LSA DeleteObject\n");
4502
4503                 r.in.handle = &lsa_acct_handle;
4504                 r.out.handle = &lsa_acct_handle;
4505
4506                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4507                         "lsa_DeleteObject failed");
4508                 torture_assert_ntstatus_ok(tctx, r.out.result,
4509                         "Failed to delete object");
4510         }
4511
4512         {
4513                 struct lsa_EnumAccounts r;
4514                 uint32_t resume_handle = 0;
4515                 struct lsa_SidArray lsa_sid_array;
4516                 int i;
4517                 bool found_sid = false;
4518
4519                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4520
4521                 r.in.handle = lsa_handle;
4522                 r.in.num_entries = 0x1000;
4523                 r.in.resume_handle = &resume_handle;
4524                 r.out.sids = &lsa_sid_array;
4525                 r.out.resume_handle = &resume_handle;
4526
4527                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4528                         "lsa_EnumAccounts failed");
4529                 torture_assert_ntstatus_ok(tctx, r.out.result,
4530                         "Failed to enum accounts");
4531
4532                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4533                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4534                                 found_sid = true;
4535                         }
4536                 }
4537
4538                 torture_assert(tctx, !found_sid,
4539                         "should not have listed privileged account");
4540         }
4541
4542         {
4543                 struct lsa_EnumAccountRights r;
4544                 struct lsa_RightSet user_rights;
4545
4546                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4547
4548                 r.in.handle = lsa_handle;
4549                 r.in.sid = user_sid;
4550                 r.out.rights = &user_rights;
4551
4552                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4553                         "lsa_EnumAccountRights failed");
4554                 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4555                         "Failed to enum rights for account");
4556         }
4557
4558         return ret;
4559 }
4560
4561 static bool test_user_ops(struct dcerpc_pipe *p,
4562                           struct torture_context *tctx,
4563                           struct policy_handle *user_handle,
4564                           struct policy_handle *domain_handle,
4565                           const struct dom_sid *domain_sid,
4566                           uint32_t base_acct_flags,
4567                           const char *base_acct_name, enum torture_samr_choice which_ops,
4568                           struct cli_credentials *machine_credentials)
4569 {
4570         char *password = NULL;
4571         struct samr_QueryUserInfo q;
4572         union samr_UserInfo *info;
4573         NTSTATUS status;
4574         struct dcerpc_binding_handle *b = p->binding_handle;
4575
4576         bool ret = true;
4577         int i;
4578         uint32_t rid;
4579         const uint32_t password_fields[] = {
4580                 SAMR_FIELD_NT_PASSWORD_PRESENT,
4581                 SAMR_FIELD_LM_PASSWORD_PRESENT,
4582                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4583                 0
4584         };
4585
4586         status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4587         if (!NT_STATUS_IS_OK(status)) {
4588                 ret = false;
4589         }
4590
4591         switch (which_ops) {
4592         case TORTURE_SAMR_USER_ATTRIBUTES:
4593                 if (!test_QuerySecurity(b, tctx, user_handle)) {
4594                         ret = false;
4595                 }
4596
4597                 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4598                         ret = false;
4599                 }
4600
4601                 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4602                         ret = false;
4603                 }
4604
4605                 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4606                                       base_acct_name)) {
4607                         ret = false;
4608                 }
4609
4610                 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4611                         ret = false;
4612                 }
4613
4614                 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4615                         ret = false;
4616                 }
4617
4618                 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4619                         ret = false;
4620                 }
4621                 break;
4622         case TORTURE_SAMR_PASSWORDS:
4623                 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4624                         char simple_pass[9];
4625                         char *v = generate_random_str(tctx, 1);
4626
4627                         ZERO_STRUCT(simple_pass);
4628                         memset(simple_pass, *v, sizeof(simple_pass) - 1);
4629
4630                         torture_comment(tctx, "Testing machine account password policy rules\n");
4631
4632                         /* Workstation trust accounts don't seem to need to honour password quality policy */
4633                         if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4634                                 ret = false;
4635                         }
4636
4637                         if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4638                                 ret = false;
4639                         }
4640
4641                         /* reset again, to allow another 'user' password change */
4642                         if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4643                                 ret = false;
4644                         }
4645
4646                         /* Try a 'short' password */
4647                         if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4648                                 ret = false;
4649                         }
4650
4651                         /* Try a compleatly random password */
4652                         if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4653                                 ret = false;
4654                         }
4655                 }
4656
4657                 for (i = 0; password_fields[i]; i++) {
4658                         if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4659                                 ret = false;
4660                         }
4661
4662                         /* check it was set right */
4663                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4664                                 ret = false;
4665                         }
4666                 }
4667
4668                 for (i = 0; password_fields[i]; i++) {
4669                         if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4670                                 ret = false;
4671                         }
4672
4673                         /* check it was set right */
4674                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4675                                 ret = false;
4676                         }
4677                 }
4678
4679                 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4680                         ret = false;
4681                 }
4682
4683                 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4684                         ret = false;
4685                 }
4686
4687                 if (torture_setting_bool(tctx, "samba4", false)) {
4688                         torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
4689                 } else {
4690
4691                         if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4692                                 ret = false;
4693                         }
4694
4695                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4696                                 ret = false;
4697                         }
4698
4699                         for (i = 0; password_fields[i]; i++) {
4700
4701                                 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4702                                         /* we need to skip as that would break
4703                                          * the ChangePasswordUser3 verify */
4704                                         continue;
4705                                 }
4706
4707                                 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4708                                         ret = false;
4709                                 }
4710
4711                                 /* check it was set right */
4712                                 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4713                                         ret = false;
4714                                 }
4715                         }
4716                 }
4717
4718                 q.in.user_handle = user_handle;
4719                 q.in.level = 5;
4720                 q.out.info = &info;
4721
4722                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4723                         "QueryUserInfo failed");
4724                 if (!NT_STATUS_IS_OK(q.out.result)) {
4725                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4726                                q.in.level, nt_errstr(q.out.result));
4727                         ret = false;
4728                 } else {
4729                         uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4730                         if ((info->info5.acct_flags) != expected_flags) {
4731                                 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4732                                        info->info5.acct_flags,
4733                                        expected_flags);
4734                                 /* FIXME: GD */
4735                                 if (!torture_setting_bool(tctx, "samba3", false)) {
4736                                         ret = false;
4737                                 }
4738                         }
4739                         if (info->info5.rid != rid) {
4740                                 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4741                                        info->info5.rid, rid);
4742
4743                         }
4744                 }
4745
4746                 break;
4747
4748         case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4749
4750                 /* test last password change timestamp behaviour */
4751                 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4752                                                  base_acct_name,
4753                                                  user_handle, &password,
4754                                                  machine_credentials)) {
4755                         ret = false;
4756                 }
4757
4758                 if (ret == true) {
4759                         torture_comment(tctx, "pwdLastSet test succeeded\n");
4760                 } else {
4761                         torture_warning(tctx, "pwdLastSet test failed\n");
4762                 }
4763
4764                 break;
4765
4766         case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4767
4768                 /* test bad pwd count change behaviour */
4769                 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4770                                                     base_acct_name,
4771                                                     domain_handle,
4772                                                     user_handle, &password,
4773                                                     machine_credentials)) {
4774                         ret = false;
4775                 }
4776
4777                 if (ret == true) {
4778                         torture_comment(tctx, "badPwdCount test succeeded\n");
4779                 } else {
4780                         torture_warning(tctx, "badPwdCount test failed\n");
4781                 }
4782
4783                 break;
4784
4785         case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4786
4787                 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4788                                                 base_acct_name,
4789                                                 domain_handle,
4790                                                 user_handle, &password,
4791                                                 machine_credentials))
4792                 {
4793                         ret = false;
4794                 }
4795
4796                 if (ret == true) {
4797                         torture_comment(tctx, "lockout test succeeded\n");
4798                 } else {
4799                         torture_warning(tctx, "lockout test failed\n");
4800                 }
4801
4802                 break;
4803
4804
4805         case TORTURE_SAMR_USER_PRIVILEGES: {
4806
4807                 struct dcerpc_pipe *lp;
4808                 struct policy_handle *lsa_handle;
4809                 struct dcerpc_binding_handle *lb;
4810
4811                 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4812                 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4813                 lb = lp->binding_handle;
4814
4815                 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4816                         ret = false;
4817                 }
4818
4819                 if (!test_DeleteUser_with_privs(p, lp, tctx,
4820                                                 domain_handle, lsa_handle, user_handle,
4821                                                 domain_sid, rid,
4822                                                 machine_credentials)) {
4823                         ret = false;
4824                 }
4825
4826                 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4827                         ret = false;
4828                 }
4829
4830                 if (!ret) {
4831                         torture_warning(tctx, "privileged user delete test failed\n");
4832                 }
4833
4834                 break;
4835         }
4836         case TORTURE_SAMR_OTHER:
4837         case TORTURE_SAMR_MANY_ACCOUNTS:
4838         case TORTURE_SAMR_MANY_GROUPS:
4839         case TORTURE_SAMR_MANY_ALIASES:
4840                 /* We just need the account to exist */
4841                 break;
4842         }
4843         return ret;
4844 }
4845
4846 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4847                            struct torture_context *tctx,
4848                            struct policy_handle *alias_handle,
4849                            const struct dom_sid *domain_sid)
4850 {
4851         bool ret = true;
4852
4853         if (!torture_setting_bool(tctx, "samba3", false)) {
4854                 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4855                         ret = false;
4856                 }
4857         }
4858
4859         if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4860                 ret = false;
4861         }
4862
4863         if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4864                 ret = false;
4865         }
4866
4867         if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
4868                 ret = false;
4869         }
4870
4871         if (torture_setting_bool(tctx, "samba3", false) ||
4872             torture_setting_bool(tctx, "samba4", false)) {
4873                 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4874                 return ret;
4875         }
4876
4877         if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
4878                 ret = false;
4879         }
4880
4881         return ret;
4882 }
4883
4884
4885 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
4886                             struct torture_context *tctx,
4887                             struct policy_handle *user_handle)
4888 {
4889         struct samr_DeleteUser d;
4890         torture_comment(tctx, "Testing DeleteUser\n");
4891
4892         d.in.user_handle = user_handle;
4893         d.out.user_handle = user_handle;
4894
4895         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
4896                 "DeleteUser failed");
4897         torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
4898
4899         return true;
4900 }
4901
4902 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
4903                             struct torture_context *tctx,
4904                             struct policy_handle *handle, const char *name)
4905 {
4906         NTSTATUS status;
4907         struct samr_DeleteUser d;
4908         struct policy_handle user_handle;
4909         uint32_t rid;
4910
4911         status = test_LookupName(b, tctx, handle, name, &rid);
4912         if (!NT_STATUS_IS_OK(status)) {
4913                 goto failed;
4914         }
4915
4916         status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
4917         if (!NT_STATUS_IS_OK(status)) {
4918                 goto failed;
4919         }
4920
4921         d.in.user_handle = &user_handle;
4922         d.out.user_handle = &user_handle;
4923         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
4924                 "DeleteUser failed");
4925         if (!NT_STATUS_IS_OK(d.out.result)) {
4926                 status = d.out.result;
4927                 goto failed;
4928         }
4929
4930         return true;
4931
4932 failed:
4933         torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
4934         return false;
4935 }
4936
4937
4938 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
4939                                     struct torture_context *tctx,
4940                                     struct policy_handle *handle, const char *name)
4941 {
4942         NTSTATUS status;
4943         struct samr_OpenGroup r;
4944         struct samr_DeleteDomainGroup d;
4945         struct policy_handle group_handle;
4946         uint32_t rid;
4947
4948         status = test_LookupName(b, tctx, handle, name, &rid);
4949         if (!NT_STATUS_IS_OK(status)) {
4950                 goto failed;
4951         }
4952
4953         r.in.domain_handle = handle;
4954         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4955         r.in.rid = rid;
4956         r.out.group_handle = &group_handle;
4957         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
4958                 "OpenGroup failed");
4959         if (!NT_STATUS_IS_OK(r.out.result)) {
4960                 status = r.out.result;
4961                 goto failed;
4962         }
4963
4964         d.in.group_handle = &group_handle;
4965         d.out.group_handle = &group_handle;
4966         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
4967                 "DeleteDomainGroup failed");
4968         if (!NT_STATUS_IS_OK(d.out.result)) {
4969                 status = d.out.result;
4970                 goto failed;
4971         }
4972
4973         return true;
4974
4975 failed:
4976         torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
4977         return false;
4978 }
4979
4980
4981 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
4982                                     struct torture_context *tctx,
4983                                     struct policy_handle *domain_handle,
4984                                     const char *name)
4985 {
4986         NTSTATUS status;
4987         struct samr_OpenAlias r;
4988         struct samr_DeleteDomAlias d;
4989         struct policy_handle alias_handle;
4990         uint32_t rid;
4991
4992         torture_comment(tctx, "Testing DeleteAlias_byname\n");
4993
4994         status = test_LookupName(b, tctx, domain_handle, name, &rid);
4995         if (!NT_STATUS_IS_OK(status)) {
4996                 goto failed;
4997         }
4998
4999         r.in.domain_handle = domain_handle;
5000         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5001         r.in.rid = rid;
5002         r.out.alias_handle = &alias_handle;
5003         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5004                 "OpenAlias failed");
5005         if (!NT_STATUS_IS_OK(r.out.result)) {
5006                 status = r.out.result;
5007                 goto failed;
5008         }
5009
5010         d.in.alias_handle = &alias_handle;
5011         d.out.alias_handle = &alias_handle;
5012         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5013                 "DeleteDomAlias failed");
5014         if (!NT_STATUS_IS_OK(d.out.result)) {
5015                 status = d.out.result;
5016                 goto failed;
5017         }
5018
5019         return true;
5020
5021 failed:
5022         torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5023         return false;
5024 }
5025
5026 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5027                              struct torture_context *tctx,
5028                              struct policy_handle *alias_handle)
5029 {
5030         struct samr_DeleteDomAlias d;
5031         bool ret = true;
5032
5033         torture_comment(tctx, "Testing DeleteAlias\n");
5034
5035         d.in.alias_handle = alias_handle;
5036         d.out.alias_handle = alias_handle;
5037
5038         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5039                 "DeleteDomAlias failed");
5040         if (!NT_STATUS_IS_OK(d.out.result)) {
5041                 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5042                 ret = false;
5043         }
5044
5045         return ret;
5046 }
5047
5048 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5049                              struct torture_context *tctx,
5050                              struct policy_handle *domain_handle,
5051                              const char *alias_name,
5052                              struct policy_handle *alias_handle,
5053                              const struct dom_sid *domain_sid,
5054                              bool test_alias)
5055 {
5056         struct samr_CreateDomAlias r;
5057         struct lsa_String name;
5058         uint32_t rid;
5059         bool ret = true;
5060
5061         init_lsa_String(&name, alias_name);
5062         r.in.domain_handle = domain_handle;
5063         r.in.alias_name = &name;
5064         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5065         r.out.alias_handle = alias_handle;
5066         r.out.rid = &rid;
5067
5068         torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5069
5070         torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5071                 "CreateDomAlias failed");
5072
5073         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5074                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5075                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5076                         return true;
5077                 } else {
5078                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5079                                nt_errstr(r.out.result));
5080                         return false;
5081                 }
5082         }
5083
5084         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5085                 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5086                         return false;
5087                 }
5088                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5089                         "CreateDomAlias failed");
5090         }
5091
5092         if (!NT_STATUS_IS_OK(r.out.result)) {
5093                 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5094                 return false;
5095         }
5096
5097         if (!test_alias) {
5098                 return ret;
5099         }
5100
5101         if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5102                 ret = false;
5103         }
5104
5105         return ret;
5106 }
5107
5108 static bool test_ChangePassword(struct dcerpc_pipe *p,
5109                                 struct torture_context *tctx,
5110                                 const char *acct_name,
5111                                 struct policy_handle *domain_handle, char **password)
5112 {
5113         bool ret = true;
5114         struct dcerpc_binding_handle *b = p->binding_handle;
5115
5116         if (!*password) {
5117                 return false;
5118         }
5119
5120         if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5121                 ret = false;
5122         }
5123
5124         if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5125                 ret = false;
5126         }
5127
5128         if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5129                 ret = false;
5130         }
5131
5132         /* test what happens when setting the old password again */
5133         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5134                 ret = false;
5135         }
5136
5137         {
5138                 char simple_pass[9];
5139                 char *v = generate_random_str(tctx, 1);
5140
5141                 ZERO_STRUCT(simple_pass);
5142                 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5143
5144                 /* test what happens when picking a simple password */
5145                 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5146                         ret = false;
5147                 }
5148         }
5149
5150         /* set samr_SetDomainInfo level 1 with min_length 5 */
5151         {
5152                 struct samr_QueryDomainInfo r;
5153                 union samr_DomainInfo *info = NULL;
5154                 struct samr_SetDomainInfo s;
5155                 uint16_t len_old, len;
5156                 uint32_t pwd_prop_old;
5157                 int64_t min_pwd_age_old;
5158
5159                 len = 5;
5160
5161                 r.in.domain_handle = domain_handle;
5162                 r.in.level = 1;
5163                 r.out.info = &info;
5164
5165                 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5166                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5167                         "QueryDomainInfo failed");
5168                 if (!NT_STATUS_IS_OK(r.out.result)) {
5169                         return false;
5170                 }
5171
5172                 s.in.domain_handle = domain_handle;
5173                 s.in.level = 1;
5174                 s.in.info = info;
5175
5176                 /* remember the old min length, so we can reset it */
5177                 len_old = s.in.info->info1.min_password_length;
5178                 s.in.info->info1.min_password_length = len;
5179                 pwd_prop_old = s.in.info->info1.password_properties;
5180                 /* turn off password complexity checks for this test */
5181                 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5182
5183                 min_pwd_age_old = s.in.info->info1.min_password_age;
5184                 s.in.info->info1.min_password_age = 0;
5185
5186                 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5187                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5188                         "SetDomainInfo failed");
5189                 if (!NT_STATUS_IS_OK(s.out.result)) {
5190                         return false;
5191                 }
5192
5193                 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5194
5195                 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5196                         ret = false;
5197                 }
5198
5199                 s.in.info->info1.min_password_length = len_old;
5200                 s.in.info->info1.password_properties = pwd_prop_old;
5201                 s.in.info->info1.min_password_age = min_pwd_age_old;
5202
5203                 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5204                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5205                         "SetDomainInfo failed");
5206                 if (!NT_STATUS_IS_OK(s.out.result)) {
5207                         return false;
5208                 }
5209
5210         }
5211
5212         {
5213                 struct samr_OpenUser r;
5214                 struct samr_QueryUserInfo q;
5215                 union samr_UserInfo *info;
5216                 struct samr_LookupNames n;
5217                 struct policy_handle user_handle;
5218                 struct samr_Ids rids, types;
5219
5220                 n.in.domain_handle = domain_handle;
5221                 n.in.num_names = 1;
5222                 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5223                 n.in.names[0].string = acct_name;
5224                 n.out.rids = &rids;
5225                 n.out.types = &types;
5226
5227                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5228                         "LookupNames failed");
5229                 if (!NT_STATUS_IS_OK(n.out.result)) {
5230                         torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5231                         return false;
5232                 }
5233
5234                 r.in.domain_handle = domain_handle;
5235                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5236                 r.in.rid = n.out.rids->ids[0];
5237                 r.out.user_handle = &user_handle;
5238
5239                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5240                         "OpenUser failed");
5241                 if (!NT_STATUS_IS_OK(r.out.result)) {
5242                         torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5243                         return false;
5244                 }
5245
5246                 q.in.user_handle = &user_handle;
5247                 q.in.level = 5;
5248                 q.out.info = &info;
5249
5250                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5251                         "QueryUserInfo failed");
5252                 if (!NT_STATUS_IS_OK(q.out.result)) {
5253                         torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5254                         return false;
5255                 }
5256
5257                 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5258
5259                 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5260                                               info->info5.last_password_change, true)) {
5261                         ret = false;
5262                 }
5263         }
5264
5265         /* we change passwords twice - this has the effect of verifying
5266            they were changed correctly for the final call */
5267         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5268                 ret = false;
5269         }
5270
5271         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5272                 ret = false;
5273         }
5274
5275         return ret;
5276 }
5277
5278 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5279                             struct policy_handle *domain_handle,
5280                             const char *user_name,
5281                             struct policy_handle *user_handle_out,
5282                             struct dom_sid *domain_sid,
5283                             enum torture_samr_choice which_ops,
5284                             struct cli_credentials *machine_credentials,
5285                             bool test_user)
5286 {
5287
5288         TALLOC_CTX *user_ctx;
5289
5290         struct samr_CreateUser r;
5291         struct samr_QueryUserInfo q;
5292         union samr_UserInfo *info;
5293         struct samr_DeleteUser d;
5294         uint32_t rid;
5295
5296         /* This call creates a 'normal' account - check that it really does */
5297         const uint32_t acct_flags = ACB_NORMAL;
5298         struct lsa_String name;
5299         bool ret = true;
5300         struct dcerpc_binding_handle *b = p->binding_handle;
5301
5302         struct policy_handle user_handle;
5303         user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5304         init_lsa_String(&name, user_name);
5305
5306         r.in.domain_handle = domain_handle;
5307         r.in.account_name = &name;
5308         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5309         r.out.user_handle = &user_handle;
5310         r.out.rid = &rid;
5311
5312         torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5313
5314         torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5315                 "CreateUser failed");
5316
5317         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5318                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5319                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5320                         return true;
5321                 } else {
5322                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5323                                nt_errstr(r.out.result));
5324                         return false;
5325                 }
5326         }
5327
5328         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5329                 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5330                         talloc_free(user_ctx);
5331                         return false;
5332                 }
5333                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5334                         "CreateUser failed");
5335         }
5336
5337         if (!NT_STATUS_IS_OK(r.out.result)) {
5338                 talloc_free(user_ctx);
5339                 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5340                 return false;
5341         }
5342
5343         if (!test_user) {
5344                 if (user_handle_out) {
5345                         *user_handle_out = user_handle;
5346                 }
5347                 return ret;
5348         }
5349
5350         {
5351                 q.in.user_handle = &user_handle;
5352                 q.in.level = 16;
5353                 q.out.info = &info;
5354
5355                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5356                         "QueryUserInfo failed");
5357                 if (!NT_STATUS_IS_OK(q.out.result)) {
5358                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5359                                q.in.level, nt_errstr(q.out.result));
5360                         ret = false;
5361                 } else {
5362                         if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5363                                 torture_warning(tctx, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5364                                        info->info16.acct_flags,
5365                                        acct_flags);
5366                                 ret = false;
5367                         }
5368                 }
5369
5370                 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5371                                    domain_sid, acct_flags, name.string, which_ops,
5372                                    machine_credentials)) {
5373                         ret = false;
5374                 }
5375
5376                 if (user_handle_out) {
5377                         *user_handle_out = user_handle;
5378                 } else {
5379                         torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5380
5381                         d.in.user_handle = &user_handle;
5382                         d.out.user_handle = &user_handle;
5383
5384                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5385                                 "DeleteUser failed");
5386                         if (!NT_STATUS_IS_OK(d.out.result)) {
5387                                 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5388                                 ret = false;
5389                         }
5390                 }
5391
5392         }
5393
5394         talloc_free(user_ctx);
5395
5396         return ret;
5397 }
5398
5399
5400 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5401                              struct policy_handle *domain_handle,
5402                              struct dom_sid *domain_sid,
5403                              enum torture_samr_choice which_ops,
5404                              struct cli_credentials *machine_credentials)
5405 {
5406         struct samr_CreateUser2 r;
5407         struct samr_QueryUserInfo q;
5408         union samr_UserInfo *info;
5409         struct samr_DeleteUser d;
5410         struct policy_handle user_handle;
5411         uint32_t rid;
5412         struct lsa_String name;
5413         bool ret = true;
5414         int i;
5415         struct dcerpc_binding_handle *b = p->binding_handle;
5416
5417         struct {
5418                 uint32_t acct_flags;
5419                 const char *account_name;
5420                 NTSTATUS nt_status;
5421         } account_types[] = {
5422                 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5423                 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5424                 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5425                 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5426                 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5427                 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5428                 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5429                 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5430                 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5431                 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5432                 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5433                 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5434                 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5435                 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5436                 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5437         };
5438
5439         for (i = 0; account_types[i].account_name; i++) {
5440                 TALLOC_CTX *user_ctx;
5441                 uint32_t acct_flags = account_types[i].acct_flags;
5442                 uint32_t access_granted;
5443                 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5444                 init_lsa_String(&name, account_types[i].account_name);
5445
5446                 r.in.domain_handle = domain_handle;
5447                 r.in.account_name = &name;
5448                 r.in.acct_flags = acct_flags;
5449                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5450                 r.out.user_handle = &user_handle;
5451                 r.out.access_granted = &access_granted;
5452                 r.out.rid = &rid;
5453
5454                 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5455
5456                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5457                         "CreateUser2 failed");
5458
5459                 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5460                         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5461                                 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5462                                 continue;
5463                         } else {
5464                                 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5465                                        nt_errstr(r.out.result));
5466                                 ret = false;
5467                                 continue;
5468                         }
5469                 }
5470
5471                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5472                         if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5473                                 talloc_free(user_ctx);
5474                                 ret = false;
5475                                 continue;
5476                         }
5477                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5478                                 "CreateUser2 failed");
5479
5480                 }
5481                 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5482                         torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5483                                nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5484                         ret = false;
5485                 }
5486
5487                 if (NT_STATUS_IS_OK(r.out.result)) {
5488                         q.in.user_handle = &user_handle;
5489                         q.in.level = 5;
5490                         q.out.info = &info;
5491
5492                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5493                                 "QueryUserInfo failed");
5494                         if (!NT_STATUS_IS_OK(q.out.result)) {
5495                                 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5496                                        q.in.level, nt_errstr(q.out.result));
5497                                 ret = false;
5498                         } else {
5499                                 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5500                                 if (acct_flags == ACB_NORMAL) {
5501                                         expected_flags |= ACB_PW_EXPIRED;
5502                                 }
5503                                 if ((info->info5.acct_flags) != expected_flags) {
5504                                         torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5505                                                info->info5.acct_flags,
5506                                                expected_flags);
5507                                         ret = false;
5508                                 }
5509                                 switch (acct_flags) {
5510                                 case ACB_SVRTRUST:
5511                                         if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5512                                                 torture_warning(tctx, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5513                                                        DOMAIN_RID_DCS, info->info5.primary_gid);
5514                                                 ret = false;
5515                                         }
5516                                         break;
5517                                 case ACB_WSTRUST:
5518                                         if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5519                                                 torture_warning(tctx, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5520                                                        DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5521                                                 ret = false;
5522                                         }
5523                                         break;
5524                                 case ACB_NORMAL:
5525                                         if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5526                                                 torture_warning(tctx, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5527                                                        DOMAIN_RID_USERS, info->info5.primary_gid);
5528                                                 ret = false;
5529                                         }
5530                                         break;
5531                                 }
5532                         }
5533
5534                         if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5535                                            domain_sid, acct_flags, name.string, which_ops,
5536                                            machine_credentials)) {
5537                                 ret = false;
5538                         }
5539
5540                         if (!policy_handle_empty(&user_handle)) {
5541                                 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5542
5543                                 d.in.user_handle = &user_handle;
5544                                 d.out.user_handle = &user_handle;
5545
5546                                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5547                                         "DeleteUser failed");
5548                                 if (!NT_STATUS_IS_OK(d.out.result)) {
5549                                         torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5550                                         ret = false;
5551                                 }
5552                         }
5553                 }
5554                 talloc_free(user_ctx);
5555         }
5556
5557         return ret;
5558 }
5559
5560 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5561                                 struct torture_context *tctx,
5562                                 struct policy_handle *handle)
5563 {
5564         struct samr_QueryAliasInfo r;
5565         union samr_AliasInfo *info;
5566         uint16_t levels[] = {1, 2, 3};
5567         int i;
5568         bool ret = true;
5569
5570         for (i=0;i<ARRAY_SIZE(levels);i++) {
5571                 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5572
5573                 r.in.alias_handle = handle;
5574                 r.in.level = levels[i];
5575                 r.out.info = &info;
5576
5577                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5578                         "QueryAliasInfo failed");
5579                 if (!NT_STATUS_IS_OK(r.out.result)) {
5580                         torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5581                                levels[i], nt_errstr(r.out.result));
5582                         ret = false;
5583                 }
5584         }
5585
5586         return ret;
5587 }
5588
5589 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5590                                 struct torture_context *tctx,
5591                                 struct policy_handle *handle)
5592 {
5593         struct samr_QueryGroupInfo r;
5594         union samr_GroupInfo *info;
5595         uint16_t levels[] = {1, 2, 3, 4, 5};
5596         int i;
5597         bool ret = true;
5598
5599         for (i=0;i<ARRAY_SIZE(levels);i++) {
5600                 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5601
5602                 r.in.group_handle = handle;
5603                 r.in.level = levels[i];
5604                 r.out.info = &info;
5605
5606                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5607                         "QueryGroupInfo failed");
5608                 if (!NT_STATUS_IS_OK(r.out.result)) {
5609                         torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5610                                levels[i], nt_errstr(r.out.result));
5611                         ret = false;
5612                 }
5613         }
5614
5615         return ret;
5616 }
5617
5618 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5619                                   struct torture_context *tctx,
5620                                   struct policy_handle *handle)
5621 {
5622         struct samr_QueryGroupMember r;
5623         struct samr_RidTypeArray *rids = NULL;
5624         bool ret = true;
5625
5626         torture_comment(tctx, "Testing QueryGroupMember\n");
5627
5628         r.in.group_handle = handle;
5629         r.out.rids = &rids;
5630
5631         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5632                 "QueryGroupMember failed");
5633         if (!NT_STATUS_IS_OK(r.out.result)) {
5634                 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(r.out.result));
5635                 ret = false;
5636         }
5637
5638         return ret;
5639 }
5640
5641
5642 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5643                               struct torture_context *tctx,
5644                               struct policy_handle *handle)
5645 {
5646         struct samr_QueryGroupInfo r;
5647         union samr_GroupInfo *info;
5648         struct samr_SetGroupInfo s;
5649         uint16_t levels[] = {1, 2, 3, 4};
5650         uint16_t set_ok[] = {0, 1, 1, 1};
5651         int i;
5652         bool ret = true;
5653
5654         for (i=0;i<ARRAY_SIZE(levels);i++) {
5655                 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5656
5657                 r.in.group_handle = handle;
5658                 r.in.level = levels[i];
5659                 r.out.info = &info;
5660
5661                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5662                         "QueryGroupInfo failed");
5663                 if (!NT_STATUS_IS_OK(r.out.result)) {
5664                         torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5665                                levels[i], nt_errstr(r.out.result));
5666                         ret = false;
5667                 }
5668
5669                 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5670
5671                 s.in.group_handle = handle;
5672                 s.in.level = levels[i];
5673                 s.in.info = *r.out.info;
5674
5675 #if 0
5676                 /* disabled this, as it changes the name only from the point of view of samr,
5677                    but leaves the name from the point of view of w2k3 internals (and ldap). This means
5678                    the name is still reserved, so creating the old name fails, but deleting by the old name
5679                    also fails */
5680                 if (s.in.level == 2) {
5681                         init_lsa_String(&s.in.info->string, "NewName");
5682                 }
5683 #endif
5684
5685                 if (s.in.level == 4) {
5686                         init_lsa_String(&s.in.info->description, "test description");
5687                 }
5688
5689                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5690                         "SetGroupInfo failed");
5691                 if (set_ok[i]) {
5692                         if (!NT_STATUS_IS_OK(s.out.result)) {
5693                                 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5694                                        r.in.level, nt_errstr(s.out.result));
5695                                 ret = false;
5696                                 continue;
5697                         }
5698                 } else {
5699                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5700                                 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5701                                        r.in.level, nt_errstr(s.out.result));
5702                                 ret = false;
5703                                 continue;
5704                         }
5705                 }
5706         }
5707
5708         return ret;
5709 }
5710
5711 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5712                                struct torture_context *tctx,
5713                                struct policy_handle *handle)
5714 {
5715         struct samr_QueryUserInfo r;
5716         union samr_UserInfo *info;
5717         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5718                            11, 12, 13, 14, 16, 17, 20, 21};
5719         int i;
5720         bool ret = true;
5721
5722         for (i=0;i<ARRAY_SIZE(levels);i++) {
5723                 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5724
5725                 r.in.user_handle = handle;
5726                 r.in.level = levels[i];
5727                 r.out.info = &info;
5728
5729                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5730                         "QueryUserInfo failed");
5731                 if (!NT_STATUS_IS_OK(r.out.result)) {
5732                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5733                                levels[i], nt_errstr(r.out.result));
5734                         ret = false;
5735                 }
5736         }
5737
5738         return ret;
5739 }
5740
5741 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5742                                 struct torture_context *tctx,
5743                                 struct policy_handle *handle)
5744 {
5745         struct samr_QueryUserInfo2 r;
5746         union samr_UserInfo *info;
5747         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5748                            11, 12, 13, 14, 16, 17, 20, 21};
5749         int i;
5750         bool ret = true;
5751
5752         for (i=0;i<ARRAY_SIZE(levels);i++) {
5753                 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5754
5755                 r.in.user_handle = handle;
5756                 r.in.level = levels[i];
5757                 r.out.info = &info;
5758
5759                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5760                         "QueryUserInfo2 failed");
5761                 if (!NT_STATUS_IS_OK(r.out.result)) {
5762                         torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5763                                levels[i], nt_errstr(r.out.result));
5764                         ret = false;
5765                 }
5766         }
5767
5768         return ret;
5769 }
5770
5771 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5772                           struct torture_context *tctx,
5773                           struct policy_handle *handle, uint32_t rid)
5774 {
5775         struct samr_OpenUser r;
5776         struct policy_handle user_handle;
5777         bool ret = true;
5778
5779         torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5780
5781         r.in.domain_handle = handle;
5782         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5783         r.in.rid = rid;
5784         r.out.user_handle = &user_handle;
5785
5786         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5787                 "OpenUser failed");
5788         if (!NT_STATUS_IS_OK(r.out.result)) {
5789                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5790                 return false;
5791         }
5792
5793         if (!test_QuerySecurity(b, tctx, &user_handle)) {
5794                 ret = false;
5795         }
5796
5797         if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5798                 ret = false;
5799         }
5800
5801         if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5802                 ret = false;
5803         }
5804
5805         if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5806                 ret = false;
5807         }
5808
5809         if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5810                 ret = false;
5811         }
5812
5813         if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5814                 ret = false;
5815         }
5816
5817         return ret;
5818 }
5819
5820 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5821                            struct torture_context *tctx,
5822                            struct policy_handle *handle, uint32_t rid)
5823 {
5824         struct samr_OpenGroup r;
5825         struct policy_handle group_handle;
5826         bool ret = true;
5827
5828         torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5829
5830         r.in.domain_handle = handle;
5831         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5832         r.in.rid = rid;
5833         r.out.group_handle = &group_handle;
5834
5835         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5836                 "OpenGroup failed");
5837         if (!NT_STATUS_IS_OK(r.out.result)) {
5838                 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5839                 return false;
5840         }
5841
5842         if (!torture_setting_bool(tctx, "samba3", false)) {
5843                 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5844                         ret = false;
5845                 }
5846         }
5847
5848         if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5849                 ret = false;
5850         }
5851
5852         if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5853                 ret = false;
5854         }
5855
5856         if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5857                 ret = false;
5858         }
5859
5860         return ret;
5861 }
5862
5863 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5864                            struct torture_context *tctx,
5865                            struct policy_handle *handle, uint32_t rid)
5866 {
5867         struct samr_OpenAlias r;
5868         struct policy_handle alias_handle;
5869         bool ret = true;
5870
5871         torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5872
5873         r.in.domain_handle = handle;
5874         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5875         r.in.rid = rid;
5876         r.out.alias_handle = &alias_handle;
5877
5878         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5879                 "OpenAlias failed");
5880         if (!NT_STATUS_IS_OK(r.out.result)) {
5881                 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5882                 return false;
5883         }
5884
5885         if (!torture_setting_bool(tctx, "samba3", false)) {
5886                 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
5887                         ret = false;
5888                 }
5889         }
5890
5891         if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
5892                 ret = false;
5893         }
5894
5895         if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
5896                 ret = false;
5897         }
5898
5899         if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
5900                 ret = false;
5901         }
5902
5903         return ret;
5904 }
5905
5906 static bool check_mask(struct dcerpc_binding_handle *b,
5907                        struct torture_context *tctx,
5908                        struct policy_handle *handle, uint32_t rid,
5909                        uint32_t acct_flag_mask)
5910 {
5911         struct samr_OpenUser r;
5912         struct samr_QueryUserInfo q;
5913         union samr_UserInfo *info;
5914         struct policy_handle user_handle;
5915         bool ret = true;
5916
5917         torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5918
5919         r.in.domain_handle = handle;
5920         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5921         r.in.rid = rid;
5922         r.out.user_handle = &user_handle;
5923
5924         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5925                 "OpenUser failed");
5926         if (!NT_STATUS_IS_OK(r.out.result)) {
5927                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5928                 return false;
5929         }
5930
5931         q.in.user_handle = &user_handle;
5932         q.in.level = 16;
5933         q.out.info = &info;
5934
5935         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5936                 "QueryUserInfo failed");
5937         if (!NT_STATUS_IS_OK(q.out.result)) {
5938                 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
5939                        nt_errstr(q.out.result));
5940                 ret = false;
5941         } else {
5942                 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
5943                         torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
5944                                acct_flag_mask, info->info16.acct_flags, rid);
5945                         ret = false;
5946                 }
5947         }
5948
5949         if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5950                 ret = false;
5951         }
5952
5953         return ret;
5954 }
5955
5956 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
5957                                      struct torture_context *tctx,
5958                                      struct policy_handle *handle)
5959 {
5960         struct samr_EnumDomainUsers r;
5961         uint32_t mask, resume_handle=0;
5962         int i, mask_idx;
5963         bool ret = true;
5964         struct samr_LookupNames n;
5965         struct samr_LookupRids  lr ;
5966         struct lsa_Strings names;
5967         struct samr_Ids rids, types;
5968         struct samr_SamArray *sam = NULL;
5969         uint32_t num_entries = 0;
5970
5971         uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
5972                             ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
5973                             ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
5974                             ACB_PWNOEXP, 0};
5975
5976         torture_comment(tctx, "Testing EnumDomainUsers\n");
5977
5978         for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
5979                 r.in.domain_handle = handle;
5980                 r.in.resume_handle = &resume_handle;
5981                 r.in.acct_flags = mask = masks[mask_idx];
5982                 r.in.max_size = (uint32_t)-1;
5983                 r.out.resume_handle = &resume_handle;
5984                 r.out.num_entries = &num_entries;
5985                 r.out.sam = &sam;
5986
5987                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
5988                         "EnumDomainUsers failed");
5989                 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
5990                     !NT_STATUS_IS_OK(r.out.result)) {
5991                         torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
5992                         return false;
5993                 }
5994
5995                 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
5996
5997                 if (sam->count == 0) {
5998                         continue;
5999                 }
6000
6001                 for (i=0;i<sam->count;i++) {
6002                         if (mask) {
6003                                 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6004                                         ret = false;
6005                                 }
6006                         } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6007                                 ret = false;
6008                         }
6009                 }
6010         }
6011
6012         torture_comment(tctx, "Testing LookupNames\n");
6013         n.in.domain_handle = handle;
6014         n.in.num_names = sam->count;
6015         n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6016         n.out.rids = &rids;
6017         n.out.types = &types;
6018         for (i=0;i<sam->count;i++) {
6019                 n.in.names[i].string = sam->entries[i].name.string;
6020         }
6021         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6022                 "LookupNames failed");
6023         if (!NT_STATUS_IS_OK(n.out.result)) {
6024                 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6025                 ret = false;
6026         }
6027
6028
6029         torture_comment(tctx, "Testing LookupRids\n");
6030         lr.in.domain_handle = handle;
6031         lr.in.num_rids = sam->count;
6032         lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6033         lr.out.names = &names;
6034         lr.out.types = &types;
6035         for (i=0;i<sam->count;i++) {
6036                 lr.in.rids[i] = sam->entries[i].idx;
6037         }
6038         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6039                 "LookupRids failed");
6040         torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6041
6042         return ret;
6043 }
6044
6045 /*
6046   try blasting the server with a bunch of sync requests
6047 */
6048 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6049                                        struct policy_handle *handle)
6050 {
6051         struct samr_EnumDomainUsers r;
6052         uint32_t resume_handle=0;
6053         int i;
6054 #define ASYNC_COUNT 100
6055         struct tevent_req *req[ASYNC_COUNT];
6056
6057         if (!torture_setting_bool(tctx, "dangerous", false)) {
6058                 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6059         }
6060
6061         torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6062
6063         r.in.domain_handle = handle;
6064         r.in.resume_handle = &resume_handle;
6065         r.in.acct_flags = 0;
6066         r.in.max_size = (uint32_t)-1;
6067         r.out.resume_handle = &resume_handle;
6068
6069         for (i=0;i<ASYNC_COUNT;i++) {
6070                 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6071         }
6072
6073         for (i=0;i<ASYNC_COUNT;i++) {
6074                 tevent_req_poll(req[i], tctx->ev);
6075                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6076                         talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6077                                i, nt_errstr(r.out.result)));
6078         }
6079
6080         torture_comment(tctx, "%d async requests OK\n", i);
6081
6082         return true;
6083 }
6084
6085 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6086                                       struct torture_context *tctx,
6087                                       struct policy_handle *handle)
6088 {
6089         struct samr_EnumDomainGroups r;
6090         uint32_t resume_handle=0;
6091         struct samr_SamArray *sam = NULL;
6092         uint32_t num_entries = 0;
6093         int i;
6094         bool ret = true;
6095         bool universal_group_found = false;
6096
6097         torture_comment(tctx, "Testing EnumDomainGroups\n");
6098
6099         r.in.domain_handle = handle;
6100         r.in.resume_handle = &resume_handle;
6101         r.in.max_size = (uint32_t)-1;
6102         r.out.resume_handle = &resume_handle;
6103         r.out.num_entries = &num_entries;
6104         r.out.sam = &sam;
6105
6106         torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6107                 "EnumDomainGroups failed");
6108         if (!NT_STATUS_IS_OK(r.out.result)) {
6109                 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6110                 return false;
6111         }
6112
6113         if (!sam) {
6114                 return false;
6115         }
6116
6117         for (i=0;i<sam->count;i++) {
6118                 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6119                         ret = false;
6120                 }
6121                 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6122                                                  "Enterprise Admins") == 0)) {
6123                         universal_group_found = true;
6124                 }
6125         }
6126
6127         /* when we are running this on s4 we should get back at least the
6128          * "Enterprise Admins" universal group. If we don't get a group entry
6129          * at all we probably are performing the test on the builtin domain.
6130          * So ignore this case. */
6131         if (torture_setting_bool(tctx, "samba4", false)) {
6132                 if ((sam->count > 0) && (!universal_group_found)) {
6133                         ret = false;
6134                 }
6135         }
6136
6137         return ret;
6138 }
6139
6140 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6141                                        struct torture_context *tctx,
6142                                        struct policy_handle *handle)
6143 {
6144         struct samr_EnumDomainAliases r;
6145         uint32_t resume_handle=0;
6146         struct samr_SamArray *sam = NULL;
6147         uint32_t num_entries = 0;
6148         int i;
6149         bool ret = true;
6150
6151         torture_comment(tctx, "Testing EnumDomainAliases\n");
6152
6153         r.in.domain_handle = handle;
6154         r.in.resume_handle = &resume_handle;
6155         r.in.max_size = (uint32_t)-1;
6156         r.out.sam = &sam;
6157         r.out.num_entries = &num_entries;
6158         r.out.resume_handle = &resume_handle;
6159
6160         torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6161                 "EnumDomainAliases failed");
6162         if (!NT_STATUS_IS_OK(r.out.result)) {
6163                 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6164                 return false;
6165         }
6166
6167         if (!sam) {
6168                 return false;
6169         }
6170
6171         for (i=0;i<sam->count;i++) {
6172                 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6173                         ret = false;
6174                 }
6175         }
6176
6177         return ret;
6178 }
6179
6180 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6181                                             struct torture_context *tctx,
6182                                             struct policy_handle *handle)
6183 {
6184         struct samr_GetDisplayEnumerationIndex r;
6185         bool ret = true;
6186         uint16_t levels[] = {1, 2, 3, 4, 5};
6187         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6188         struct lsa_String name;
6189         uint32_t idx = 0;
6190         int i;
6191
6192         for (i=0;i<ARRAY_SIZE(levels);i++) {
6193                 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6194
6195                 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6196
6197                 r.in.domain_handle = handle;
6198                 r.in.level = levels[i];
6199                 r.in.name = &name;
6200                 r.out.idx = &idx;
6201
6202                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6203                         "GetDisplayEnumerationIndex failed");
6204
6205                 if (ok_lvl[i] &&
6206                     !NT_STATUS_IS_OK(r.out.result) &&
6207                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6208                         torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6209                                levels[i], nt_errstr(r.out.result));
6210                         ret = false;
6211                 }
6212
6213                 init_lsa_String(&name, "zzzzzzzz");
6214
6215                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6216                         "GetDisplayEnumerationIndex failed");
6217
6218                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6219                         torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6220                                levels[i], nt_errstr(r.out.result));
6221                         ret = false;
6222                 }
6223         }
6224
6225         return ret;
6226 }
6227
6228 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6229                                              struct torture_context *tctx,
6230                                              struct policy_handle *handle)
6231 {
6232         struct samr_GetDisplayEnumerationIndex2 r;
6233         bool ret = true;
6234         uint16_t levels[] = {1, 2, 3, 4, 5};
6235         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6236         struct lsa_String name;
6237         uint32_t idx = 0;
6238         int i;
6239
6240         for (i=0;i<ARRAY_SIZE(levels);i++) {
6241                 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6242
6243                 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6244
6245                 r.in.domain_handle = handle;
6246                 r.in.level = levels[i];
6247                 r.in.name = &name;
6248                 r.out.idx = &idx;
6249
6250                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6251                         "GetDisplayEnumerationIndex2 failed");
6252                 if (ok_lvl[i] &&
6253                     !NT_STATUS_IS_OK(r.out.result) &&
6254                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6255                         torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6256                                levels[i], nt_errstr(r.out.result));
6257                         ret = false;
6258                 }
6259
6260                 init_lsa_String(&name, "zzzzzzzz");
6261
6262                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6263                         "GetDisplayEnumerationIndex2 failed");
6264                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6265                         torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6266                                levels[i], nt_errstr(r.out.result));
6267                         ret = false;
6268                 }
6269         }
6270
6271         return ret;
6272 }
6273
6274 #define STRING_EQUAL_QUERY(s1, s2, user)                                        \
6275         if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6276                 /* odd, but valid */                                            \
6277         } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6278                         torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6279                                #s1, user.string,  s1.string, s2.string, __location__);   \
6280                         ret = false; \
6281         }
6282 #define INT_EQUAL_QUERY(s1, s2, user)           \
6283                 if (s1 != s2) { \
6284                         torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6285                                #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6286                         ret = false; \
6287                 }
6288
6289 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6290                                        struct torture_context *tctx,
6291                                        struct samr_QueryDisplayInfo *querydisplayinfo,
6292                                        bool *seen_testuser)
6293 {
6294         struct samr_OpenUser r;
6295         struct samr_QueryUserInfo q;
6296         union samr_UserInfo *info;
6297         struct policy_handle user_handle;
6298         int i, ret = true;
6299         r.in.domain_handle = querydisplayinfo->in.domain_handle;
6300         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6301         for (i = 0; ; i++) {
6302                 switch (querydisplayinfo->in.level) {
6303                 case 1:
6304                         if (i >= querydisplayinfo->out.info->info1.count) {
6305                                 return ret;
6306                         }
6307                         r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6308                         break;
6309                 case 2:
6310                         if (i >= querydisplayinfo->out.info->info2.count) {
6311                                 return ret;
6312                         }
6313                         r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6314                         break;
6315                 case 3:
6316                         /* Groups */
6317                 case 4:
6318                 case 5:
6319                         /* Not interested in validating just the account name */
6320                         return true;
6321                 }
6322
6323                 r.out.user_handle = &user_handle;
6324
6325                 switch (querydisplayinfo->in.level) {
6326                 case 1:
6327                 case 2:
6328                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6329                                 "OpenUser failed");
6330                         if (!NT_STATUS_IS_OK(r.out.result)) {
6331                                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6332                                 return false;
6333                         }
6334                 }
6335
6336                 q.in.user_handle = &user_handle;
6337                 q.in.level = 21;
6338                 q.out.info = &info;
6339                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6340                         "QueryUserInfo failed");
6341                 if (!NT_STATUS_IS_OK(r.out.result)) {
6342                         torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6343                         return false;
6344                 }
6345
6346                 switch (querydisplayinfo->in.level) {
6347                 case 1:
6348                         if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6349                                 *seen_testuser = true;
6350                         }
6351                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6352                                            info->info21.full_name, info->info21.account_name);
6353                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6354                                            info->info21.account_name, info->info21.account_name);
6355                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6356                                            info->info21.description, info->info21.account_name);
6357                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6358                                         info->info21.rid, info->info21.account_name);
6359                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6360                                         info->info21.acct_flags, info->info21.account_name);
6361
6362                         break;
6363                 case 2:
6364                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6365                                            info->info21.account_name, info->info21.account_name);
6366                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6367                                            info->info21.description, info->info21.account_name);
6368                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6369                                         info->info21.rid, info->info21.account_name);
6370                         INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6371                                         info->info21.acct_flags, info->info21.account_name);
6372
6373                         if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6374                                 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6375                                        info->info21.account_name.string);
6376                         }
6377
6378                         if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6379                                 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6380                                        info->info21.account_name.string,
6381                                        querydisplayinfo->out.info->info2.entries[i].acct_flags,
6382                                        info->info21.acct_flags);
6383                                 return false;
6384                         }
6385
6386                         break;
6387                 }
6388
6389                 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6390                         return false;
6391                 }
6392         }
6393         return ret;
6394 }
6395
6396 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6397                                   struct torture_context *tctx,
6398                                   struct policy_handle *handle)
6399 {
6400         struct samr_QueryDisplayInfo r;
6401         struct samr_QueryDomainInfo dom_info;
6402         union samr_DomainInfo *info = NULL;
6403         bool ret = true;
6404         uint16_t levels[] = {1, 2, 3, 4, 5};
6405         int i;
6406         bool seen_testuser = false;
6407         uint32_t total_size;
6408         uint32_t returned_size;
6409         union samr_DispInfo disp_info;
6410
6411
6412         for (i=0;i<ARRAY_SIZE(levels);i++) {
6413                 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6414
6415                 r.in.start_idx = 0;
6416                 r.out.result = STATUS_MORE_ENTRIES;
6417                 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6418                         r.in.domain_handle = handle;
6419                         r.in.level = levels[i];
6420                         r.in.max_entries = 2;
6421                         r.in.buf_size = (uint32_t)-1;
6422                         r.out.total_size = &total_size;
6423                         r.out.returned_size = &returned_size;
6424                         r.out.info = &disp_info;
6425
6426                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6427                                 "QueryDisplayInfo failed");
6428                         if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6429                                 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6430                                        levels[i], nt_errstr(r.out.result));
6431                                 ret = false;
6432                         }
6433                         switch (r.in.level) {
6434                         case 1:
6435                                 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6436                                         ret = false;
6437                                 }
6438                                 r.in.start_idx += r.out.info->info1.count;
6439                                 break;
6440                         case 2:
6441                                 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6442                                         ret = false;
6443                                 }
6444                                 r.in.start_idx += r.out.info->info2.count;
6445                                 break;
6446                         case 3:
6447                                 r.in.start_idx += r.out.info->info3.count;
6448                                 break;
6449                         case 4:
6450                                 r.in.start_idx += r.out.info->info4.count;
6451                                 break;
6452                         case 5:
6453                                 r.in.start_idx += r.out.info->info5.count;
6454                                 break;
6455                         }
6456                 }
6457                 dom_info.in.domain_handle = handle;
6458                 dom_info.in.level = 2;
6459                 dom_info.out.info = &info;
6460
6461                 /* Check number of users returned is correct */
6462                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6463                         "QueryDomainInfo failed");
6464                 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6465                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6466                                r.in.level, nt_errstr(dom_info.out.result));
6467                         ret = false;
6468                         break;
6469                 }
6470                 switch (r.in.level) {
6471                 case 1:
6472                 case 4:
6473                         if (info->general.num_users < r.in.start_idx) {
6474                                 /* On AD deployments this numbers don't match
6475                                  * since QueryDisplayInfo returns universal and
6476                                  * global groups, QueryDomainInfo only global
6477                                  * ones. */
6478                                 if (torture_setting_bool(tctx, "samba3", false)) {
6479                                         torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6480                                                r.in.start_idx, info->general.num_groups,
6481                                                info->general.domain_name.string);
6482                                         ret = false;
6483                                 }
6484                         }
6485                         if (!seen_testuser) {
6486                                 struct policy_handle user_handle;
6487                                 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6488                                         torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6489                                                info->general.domain_name.string);
6490                                         ret = false;
6491                                         test_samr_handle_Close(b, tctx, &user_handle);
6492                                 }
6493                         }
6494                         break;
6495                 case 3:
6496                 case 5:
6497                         if (info->general.num_groups != r.in.start_idx) {
6498                                 /* On AD deployments this numbers don't match
6499                                  * since QueryDisplayInfo returns universal and
6500                                  * global groups, QueryDomainInfo only global
6501                                  * ones. */
6502                                 if (torture_setting_bool(tctx, "samba3", false)) {
6503                                         torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6504                                                r.in.start_idx, info->general.num_groups,
6505                                                info->general.domain_name.string);
6506                                         ret = false;
6507                                 }
6508                         }
6509
6510                         break;
6511                 }
6512
6513         }
6514
6515         return ret;
6516 }
6517
6518 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6519                                    struct torture_context *tctx,
6520                                    struct policy_handle *handle)
6521 {
6522         struct samr_QueryDisplayInfo2 r;
6523         bool ret = true;
6524         uint16_t levels[] = {1, 2, 3, 4, 5};
6525         int i;
6526         uint32_t total_size;
6527         uint32_t returned_size;
6528         union samr_DispInfo info;
6529
6530         for (i=0;i<ARRAY_SIZE(levels);i++) {
6531                 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6532
6533                 r.in.domain_handle = handle;
6534                 r.in.level = levels[i];
6535                 r.in.start_idx = 0;
6536                 r.in.max_entries = 1000;
6537                 r.in.buf_size = (uint32_t)-1;
6538                 r.out.total_size = &total_size;
6539                 r.out.returned_size = &returned_size;
6540                 r.out.info = &info;
6541
6542                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6543                         "QueryDisplayInfo2 failed");
6544                 if (!NT_STATUS_IS_OK(r.out.result)) {
6545                         torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6546                                levels[i], nt_errstr(r.out.result));
6547                         ret = false;
6548                 }
6549         }
6550
6551         return ret;
6552 }
6553
6554 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6555                                    struct torture_context *tctx,
6556                                    struct policy_handle *handle)
6557 {
6558         struct samr_QueryDisplayInfo3 r;
6559         bool ret = true;
6560         uint16_t levels[] = {1, 2, 3, 4, 5};
6561         int i;
6562         uint32_t total_size;
6563         uint32_t returned_size;
6564         union samr_DispInfo info;
6565
6566         for (i=0;i<ARRAY_SIZE(levels);i++) {
6567                 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6568
6569                 r.in.domain_handle = handle;
6570                 r.in.level = levels[i];
6571                 r.in.start_idx = 0;
6572                 r.in.max_entries = 1000;
6573                 r.in.buf_size = (uint32_t)-1;
6574                 r.out.total_size = &total_size;
6575                 r.out.returned_size = &returned_size;
6576                 r.out.info = &info;
6577
6578                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6579                         "QueryDisplayInfo3 failed");
6580                 if (!NT_STATUS_IS_OK(r.out.result)) {
6581                         torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6582                                levels[i], nt_errstr(r.out.result));
6583                         ret = false;
6584                 }
6585         }
6586
6587         return ret;
6588 }
6589
6590
6591 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6592                                            struct torture_context *tctx,
6593                                            struct policy_handle *handle)
6594 {
6595         struct samr_QueryDisplayInfo r;
6596         bool ret = true;
6597         uint32_t total_size;
6598         uint32_t returned_size;
6599         union samr_DispInfo info;
6600
6601         torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6602
6603         r.in.domain_handle = handle;
6604         r.in.level = 1;
6605         r.in.start_idx = 0;
6606         r.in.max_entries = 1;
6607         r.in.buf_size = (uint32_t)-1;
6608         r.out.total_size = &total_size;
6609         r.out.returned_size = &returned_size;
6610         r.out.info = &info;
6611
6612         do {
6613                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6614                         "QueryDisplayInfo failed");
6615                 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6616                         if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6617                                 torture_warning(tctx, "expected idx %d but got %d\n",
6618                                        r.in.start_idx + 1,
6619                                        r.out.info->info1.entries[0].idx);
6620                                 break;
6621                         }
6622                 }
6623                 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6624                     !NT_STATUS_IS_OK(r.out.result)) {
6625                         torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6626                                r.in.level, nt_errstr(r.out.result));
6627                         ret = false;
6628                         break;
6629                 }
6630                 r.in.start_idx++;
6631         } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6632                   NT_STATUS_IS_OK(r.out.result)) &&
6633                  *r.out.returned_size != 0);
6634
6635         return ret;
6636 }
6637
6638 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6639                                  struct torture_context *tctx,
6640                                  struct policy_handle *handle)
6641 {
6642         struct samr_QueryDomainInfo r;
6643         union samr_DomainInfo *info = NULL;
6644         struct samr_SetDomainInfo s;
6645         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6646         uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1,  0,  1,  0};
6647         int i;
6648         bool ret = true;
6649         struct dcerpc_binding_handle *b = p->binding_handle;
6650         const char *domain_comment = talloc_asprintf(tctx,
6651                                   "Tortured by Samba4 RPC-SAMR: %s",
6652                                   timestring(tctx, time(NULL)));
6653
6654         s.in.domain_handle = handle;
6655         s.in.level = 4;
6656         s.in.info = talloc(tctx, union samr_DomainInfo);
6657
6658         s.in.info->oem.oem_information.string = domain_comment;
6659         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6660                 "SetDomainInfo failed");
6661         if (!NT_STATUS_IS_OK(s.out.result)) {
6662                 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6663                        s.in.level, nt_errstr(s.out.result));
6664                 return false;
6665         }
6666
6667         for (i=0;i<ARRAY_SIZE(levels);i++) {
6668                 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6669
6670                 r.in.domain_handle = handle;
6671                 r.in.level = levels[i];
6672                 r.out.info = &info;
6673
6674                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6675                         "QueryDomainInfo failed");
6676                 if (!NT_STATUS_IS_OK(r.out.result)) {
6677                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6678                                r.in.level, nt_errstr(r.out.result));
6679                         ret = false;
6680                         continue;
6681                 }
6682
6683                 switch (levels[i]) {
6684                 case 2:
6685                         if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6686                                 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6687                                        levels[i], info->general.oem_information.string, domain_comment);
6688                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6689                                         ret = false;
6690                                 }
6691                         }
6692                         if (!info->general.primary.string) {
6693                                 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6694                                        levels[i]);
6695                                 ret = false;
6696                         } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6697                                 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6698                                         torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6699                                                levels[i], info->general.primary.string, dcerpc_server_name(p));
6700                                 }
6701                         }
6702                         break;
6703                 case 4:
6704                         if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6705                                 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6706                                        levels[i], info->oem.oem_information.string, domain_comment);
6707                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6708                                         ret = false;
6709                                 }
6710                         }
6711                         break;
6712                 case 6:
6713                         if (!info->info6.primary.string) {
6714                                 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6715                                        levels[i]);
6716                                 ret = false;
6717                         }
6718                         break;
6719                 case 11:
6720                         if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6721                                 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6722                                        levels[i], info->general2.general.oem_information.string, domain_comment);
6723                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6724                                         ret = false;
6725                                 }
6726                         }
6727                         break;
6728                 }
6729
6730                 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6731
6732                 s.in.domain_handle = handle;
6733                 s.in.level = levels[i];
6734                 s.in.info = info;
6735
6736                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6737                         "SetDomainInfo failed");
6738                 if (set_ok[i]) {
6739                         if (!NT_STATUS_IS_OK(s.out.result)) {
6740                                 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6741                                        r.in.level, nt_errstr(s.out.result));
6742                                 ret = false;
6743                                 continue;
6744                         }
6745                 } else {
6746                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6747                                 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6748                                        r.in.level, nt_errstr(s.out.result));
6749                                 ret = false;
6750                                 continue;
6751                         }
6752                 }
6753
6754                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6755                         "QueryDomainInfo failed");
6756                 if (!NT_STATUS_IS_OK(r.out.result)) {
6757                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6758                                r.in.level, nt_errstr(r.out.result));
6759                         ret = false;
6760                         continue;
6761                 }
6762         }
6763
6764         return ret;
6765 }
6766
6767
6768 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6769                                   struct torture_context *tctx,
6770                                   struct policy_handle *handle)
6771 {
6772         struct samr_QueryDomainInfo2 r;
6773         union samr_DomainInfo *info = NULL;
6774         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6775         int i;
6776         bool ret = true;
6777
6778         for (i=0;i<ARRAY_SIZE(levels);i++) {
6779                 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6780
6781                 r.in.domain_handle = handle;
6782                 r.in.level = levels[i];
6783                 r.out.info = &info;
6784
6785                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6786                         "QueryDomainInfo2 failed");
6787                 if (!NT_STATUS_IS_OK(r.out.result)) {
6788                         torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6789                                r.in.level, nt_errstr(r.out.result));
6790                         ret = false;
6791                         continue;
6792                 }
6793         }
6794
6795         return true;
6796 }
6797
6798 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6799    set of group names. */
6800 static bool test_GroupList(struct dcerpc_binding_handle *b,
6801                            struct torture_context *tctx,
6802                            struct policy_handle *handle)
6803 {
6804         struct samr_EnumDomainGroups q1;
6805         struct samr_QueryDisplayInfo q2;
6806         NTSTATUS status;
6807         uint32_t resume_handle=0;
6808         struct samr_SamArray *sam = NULL;
6809         uint32_t num_entries = 0;
6810         int i;
6811         bool ret = true;
6812         uint32_t total_size;
6813         uint32_t returned_size;
6814         union samr_DispInfo info;
6815
6816         int num_names = 0;
6817         const char **names = NULL;
6818
6819         torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6820
6821         q1.in.domain_handle = handle;
6822         q1.in.resume_handle = &resume_handle;
6823         q1.in.max_size = 5;
6824         q1.out.resume_handle = &resume_handle;
6825         q1.out.num_entries = &num_entries;
6826         q1.out.sam = &sam;
6827
6828         status = STATUS_MORE_ENTRIES;
6829         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6830                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6831                         "EnumDomainGroups failed");
6832                 status = q1.out.result;
6833
6834                 if (!NT_STATUS_IS_OK(status) &&
6835                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6836                         break;
6837
6838                 for (i=0; i<*q1.out.num_entries; i++) {
6839                         add_string_to_array(tctx,
6840                                             sam->entries[i].name.string,
6841                                             &names, &num_names);
6842                 }
6843         }
6844
6845         torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6846
6847         torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6848
6849         q2.in.domain_handle = handle;
6850         q2.in.level = 5;
6851         q2.in.start_idx = 0;
6852         q2.in.max_entries = 5;
6853         q2.in.buf_size = (uint32_t)-1;
6854         q2.out.total_size = &total_size;
6855         q2.out.returned_size = &returned_size;
6856         q2.out.info = &info;
6857
6858         status = STATUS_MORE_ENTRIES;
6859         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6860                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
6861                         "QueryDisplayInfo failed");
6862                 status = q2.out.result;
6863                 if (!NT_STATUS_IS_OK(status) &&
6864                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6865                         break;
6866
6867                 for (i=0; i<q2.out.info->info5.count; i++) {
6868                         int j;
6869                         const char *name = q2.out.info->info5.entries[i].account_name.string;
6870                         bool found = false;
6871                         for (j=0; j<num_names; j++) {
6872                                 if (names[j] == NULL)
6873                                         continue;
6874                                 if (strequal(names[j], name)) {
6875                                         names[j] = NULL;
6876                                         found = true;
6877                                         break;
6878                                 }
6879                         }
6880
6881                         if (!found) {
6882                                 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
6883                                        name);
6884                                 ret = false;
6885                         }
6886                 }
6887                 q2.in.start_idx += q2.out.info->info5.count;
6888         }
6889
6890         if (!NT_STATUS_IS_OK(status)) {
6891                 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
6892                        nt_errstr(status));
6893                 ret = false;
6894         }
6895
6896         for (i=0; i<num_names; i++) {
6897                 if (names[i] != NULL) {
6898                         torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
6899                                names[i]);
6900                         ret = false;
6901                 }
6902         }
6903
6904         return ret;
6905 }
6906
6907 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
6908                                    struct torture_context *tctx,
6909                                    struct policy_handle *group_handle)
6910 {
6911         struct samr_DeleteDomainGroup d;
6912
6913         torture_comment(tctx, "Testing DeleteDomainGroup\n");
6914
6915         d.in.group_handle = group_handle;
6916         d.out.group_handle = group_handle;
6917
6918         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
6919                 "DeleteDomainGroup failed");
6920         torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
6921
6922         return true;
6923 }
6924
6925 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
6926                                             struct torture_context *tctx,
6927                                             struct policy_handle *domain_handle)
6928 {
6929         struct samr_TestPrivateFunctionsDomain r;
6930         bool ret = true;
6931
6932         torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
6933
6934         r.in.domain_handle = domain_handle;
6935
6936         torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
6937                 "TestPrivateFunctionsDomain failed");
6938         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
6939
6940         return ret;
6941 }
6942
6943 static bool test_RidToSid(struct dcerpc_binding_handle *b,
6944                           struct torture_context *tctx,
6945                           struct dom_sid *domain_sid,
6946                           struct policy_handle *domain_handle)
6947 {
6948         struct samr_RidToSid r;
6949         bool ret = true;
6950         struct dom_sid *calc_sid, *out_sid;
6951         int rids[] = { 0, 42, 512, 10200 };
6952         int i;
6953
6954         for (i=0;i<ARRAY_SIZE(rids);i++) {
6955                 torture_comment(tctx, "Testing RidToSid\n");
6956
6957                 calc_sid = dom_sid_dup(tctx, domain_sid);
6958                 r.in.domain_handle = domain_handle;
6959                 r.in.rid = rids[i];
6960                 r.out.sid = &out_sid;
6961
6962                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
6963                         "RidToSid failed");
6964                 if (!NT_STATUS_IS_OK(r.out.result)) {
6965                         torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
6966                         ret = false;
6967                 } else {
6968                         calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
6969
6970                         if (!dom_sid_equal(calc_sid, out_sid)) {
6971                                 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
6972                                        dom_sid_string(tctx, out_sid),
6973                                        dom_sid_string(tctx, calc_sid));
6974                                 ret = false;
6975                         }
6976                 }
6977         }
6978
6979         return ret;
6980 }
6981
6982 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
6983                                        struct torture_context *tctx,
6984                                        struct policy_handle *domain_handle)
6985 {
6986         struct samr_GetBootKeyInformation r;
6987         bool ret = true;
6988         uint32_t unknown = 0;
6989         NTSTATUS status;
6990
6991         torture_comment(tctx, "Testing GetBootKeyInformation\n");
6992
6993         r.in.domain_handle = domain_handle;
6994         r.out.unknown = &unknown;
6995
6996         status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
6997         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
6998                 status = r.out.result;
6999         }
7000         if (!NT_STATUS_IS_OK(status)) {
7001                 /* w2k3 seems to fail this sometimes and pass it sometimes */
7002                 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7003         }
7004
7005         return ret;
7006 }
7007
7008 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7009                                 struct torture_context *tctx,
7010                                 struct policy_handle *domain_handle,
7011                                 struct policy_handle *group_handle)
7012 {
7013         NTSTATUS status;
7014         struct samr_AddGroupMember r;
7015         struct samr_DeleteGroupMember d;
7016         struct samr_QueryGroupMember q;
7017         struct samr_RidTypeArray *rids = NULL;
7018         struct samr_SetMemberAttributesOfGroup s;
7019         uint32_t rid;
7020         bool found_member = false;
7021         int i;
7022
7023         status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7024         torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7025
7026         r.in.group_handle = group_handle;
7027         r.in.rid = rid;
7028         r.in.flags = 0; /* ??? */
7029
7030         torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7031
7032         d.in.group_handle = group_handle;
7033         d.in.rid = rid;
7034
7035         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7036                 "DeleteGroupMember failed");
7037         torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7038
7039         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7040                 "AddGroupMember failed");
7041         torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7042
7043         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7044                 "AddGroupMember failed");
7045         torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7046
7047         if (torture_setting_bool(tctx, "samba4", false) ||
7048             torture_setting_bool(tctx, "samba3", false)) {
7049                 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7050         } else {
7051                 /* this one is quite strange. I am using random inputs in the
7052                    hope of triggering an error that might give us a clue */
7053
7054                 s.in.group_handle = group_handle;
7055                 s.in.unknown1 = random();
7056                 s.in.unknown2 = random();
7057
7058                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7059                         "SetMemberAttributesOfGroup failed");
7060                 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7061         }
7062
7063         q.in.group_handle = group_handle;
7064         q.out.rids = &rids;
7065
7066         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7067                 "QueryGroupMember failed");
7068         torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7069         torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7070
7071         for (i=0; i < rids->count; i++) {
7072                 if (rids->rids[i] == rid) {
7073                         found_member = true;
7074                 }
7075         }
7076
7077         torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7078
7079         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7080                 "DeleteGroupMember failed");
7081         torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7082
7083         rids = NULL;
7084         found_member = false;
7085
7086         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7087                 "QueryGroupMember failed");
7088         torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7089         torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7090
7091         for (i=0; i < rids->count; i++) {
7092                 if (rids->rids[i] == rid) {
7093                         found_member = true;
7094                 }
7095         }
7096
7097         torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7098
7099         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7100                 "AddGroupMember failed");
7101         torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7102
7103         return true;
7104 }
7105
7106
7107 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7108                                    struct torture_context *tctx,
7109                                    struct policy_handle *domain_handle,
7110                                    const char *group_name,
7111                                    struct policy_handle *group_handle,
7112                                    struct dom_sid *domain_sid,
7113                                    bool test_group)
7114 {
7115         struct samr_CreateDomainGroup r;
7116         uint32_t rid;
7117         struct lsa_String name;
7118         bool ret = true;
7119
7120         init_lsa_String(&name, group_name);
7121
7122         r.in.domain_handle = domain_handle;
7123         r.in.name = &name;
7124         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7125         r.out.group_handle = group_handle;
7126         r.out.rid = &rid;
7127
7128         torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7129
7130         torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7131                 "CreateDomainGroup failed");
7132
7133         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7134                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7135                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7136                         return true;
7137                 } else {
7138                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7139                                nt_errstr(r.out.result));
7140                         return false;
7141                 }
7142         }
7143
7144         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7145                 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7146                         torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7147                                nt_errstr(r.out.result));
7148                         return false;
7149                 }
7150                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7151                         "CreateDomainGroup failed");
7152         }
7153         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7154                 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7155
7156                         torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7157                                nt_errstr(r.out.result));
7158                         return false;
7159                 }
7160                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7161                         "CreateDomainGroup failed");
7162         }
7163         torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7164
7165         if (!test_group) {
7166                 return ret;
7167         }
7168
7169         if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7170                 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7171                 ret = false;
7172         }
7173
7174         if (!test_SetGroupInfo(b, tctx, group_handle)) {
7175                 ret = false;
7176         }
7177
7178         return ret;
7179 }
7180
7181
7182 /*
7183   its not totally clear what this does. It seems to accept any sid you like.
7184 */
7185 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7186                                                struct torture_context *tctx,
7187                                                struct policy_handle *domain_handle)
7188 {
7189         struct samr_RemoveMemberFromForeignDomain r;
7190
7191         r.in.domain_handle = domain_handle;
7192         r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7193
7194         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7195                 "RemoveMemberFromForeignDomain failed");
7196         torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7197
7198         return true;
7199 }
7200
7201 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7202                                  struct torture_context *tctx,
7203                                  struct policy_handle *domain_handle,
7204                                  uint32_t *total_num_entries_p)
7205 {
7206         NTSTATUS status;
7207         struct samr_EnumDomainUsers r;
7208         uint32_t resume_handle = 0;
7209         uint32_t num_entries = 0;
7210         uint32_t total_num_entries = 0;
7211         struct samr_SamArray *sam;
7212
7213         r.in.domain_handle = domain_handle;
7214         r.in.acct_flags = 0;
7215         r.in.max_size = (uint32_t)-1;
7216         r.in.resume_handle = &resume_handle;
7217
7218         r.out.sam = &sam;
7219         r.out.num_entries = &num_entries;
7220         r.out.resume_handle = &resume_handle;
7221
7222         torture_comment(tctx, "Testing EnumDomainUsers\n");
7223
7224         do {
7225                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7226                         "EnumDomainUsers failed");
7227                 if (NT_STATUS_IS_ERR(r.out.result)) {
7228                         torture_assert_ntstatus_ok(tctx, r.out.result,
7229                                 "failed to enumerate users");
7230                 }
7231
7232                 total_num_entries += num_entries;
7233         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7234
7235         if (total_num_entries_p) {
7236                 *total_num_entries_p = total_num_entries;
7237         }
7238
7239         return true;
7240 }
7241
7242 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7243                                   struct torture_context *tctx,
7244                                   struct policy_handle *domain_handle,
7245                                   uint32_t *total_num_entries_p)
7246 {
7247         NTSTATUS status;
7248         struct samr_EnumDomainGroups r;
7249         uint32_t resume_handle = 0;
7250         uint32_t num_entries = 0;
7251         uint32_t total_num_entries = 0;
7252         struct samr_SamArray *sam;
7253
7254         r.in.domain_handle = domain_handle;
7255         r.in.max_size = (uint32_t)-1;
7256         r.in.resume_handle = &resume_handle;
7257
7258         r.out.sam = &sam;
7259         r.out.num_entries = &num_entries;
7260         r.out.resume_handle = &resume_handle;
7261
7262         torture_comment(tctx, "Testing EnumDomainGroups\n");
7263
7264         do {
7265                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7266                         "EnumDomainGroups failed");
7267                 if (NT_STATUS_IS_ERR(r.out.result)) {
7268                         torture_assert_ntstatus_ok(tctx, r.out.result,
7269                                 "failed to enumerate groups");
7270                 }
7271
7272                 total_num_entries += num_entries;
7273         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7274
7275         if (total_num_entries_p) {
7276                 *total_num_entries_p = total_num_entries;
7277         }
7278
7279         return true;
7280 }
7281
7282 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7283                                    struct torture_context *tctx,
7284                                    struct policy_handle *domain_handle,
7285                                    uint32_t *total_num_entries_p)
7286 {
7287         NTSTATUS status;
7288         struct samr_EnumDomainAliases r;
7289         uint32_t resume_handle = 0;
7290         uint32_t num_entries = 0;
7291         uint32_t total_num_entries = 0;
7292         struct samr_SamArray *sam;
7293
7294         r.in.domain_handle = domain_handle;
7295         r.in.max_size = (uint32_t)-1;
7296         r.in.resume_handle = &resume_handle;
7297
7298         r.out.sam = &sam;
7299         r.out.num_entries = &num_entries;
7300         r.out.resume_handle = &resume_handle;
7301
7302         torture_comment(tctx, "Testing EnumDomainAliases\n");
7303
7304         do {
7305                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7306                         "EnumDomainAliases failed");
7307                 if (NT_STATUS_IS_ERR(r.out.result)) {
7308                         torture_assert_ntstatus_ok(tctx, r.out.result,
7309                                 "failed to enumerate aliases");
7310                 }
7311
7312                 total_num_entries += num_entries;
7313         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7314
7315         if (total_num_entries_p) {
7316                 *total_num_entries_p = total_num_entries;
7317         }
7318
7319         return true;
7320 }
7321
7322 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7323                                         struct torture_context *tctx,
7324                                         struct policy_handle *handle,
7325                                         uint16_t level,
7326                                         uint32_t *total_num_entries_p)
7327 {
7328         NTSTATUS status;
7329         struct samr_QueryDisplayInfo r;
7330         uint32_t total_num_entries = 0;
7331
7332         r.in.domain_handle = handle;
7333         r.in.level = level;
7334         r.in.start_idx = 0;
7335         r.in.max_entries = (uint32_t)-1;
7336         r.in.buf_size = (uint32_t)-1;
7337
7338         torture_comment(tctx, "Testing QueryDisplayInfo\n");
7339
7340         do {
7341                 uint32_t total_size;
7342                 uint32_t returned_size;
7343                 union samr_DispInfo info;
7344
7345                 r.out.total_size = &total_size;
7346                 r.out.returned_size = &returned_size;
7347                 r.out.info = &info;
7348
7349                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7350                         "failed to query displayinfo");
7351                 if (NT_STATUS_IS_ERR(r.out.result)) {
7352                         torture_assert_ntstatus_ok(tctx, r.out.result,
7353                                 "failed to query displayinfo");
7354                 }
7355
7356                 if (*r.out.returned_size == 0) {
7357                         break;
7358                 }
7359
7360                 switch (r.in.level) {
7361                 case 1:
7362                         total_num_entries += info.info1.count;
7363                         r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7364                         break;
7365                 case 2:
7366                         total_num_entries += info.info2.count;
7367                         r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7368                         break;
7369                 case 3:
7370                         total_num_entries += info.info3.count;
7371                         r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7372                         break;
7373                 case 4:
7374                         total_num_entries += info.info4.count;
7375                         r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7376                         break;
7377                 case 5:
7378                         total_num_entries += info.info5.count;
7379                         r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7380                         break;
7381                 default:
7382                         return false;
7383                 }
7384
7385         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7386
7387         if (total_num_entries_p) {
7388                 *total_num_entries_p = total_num_entries;
7389         }
7390
7391         return true;
7392 }
7393
7394 static bool test_ManyObjects(struct dcerpc_pipe *p,
7395                              struct torture_context *tctx,
7396                              struct policy_handle *domain_handle,
7397                              struct dom_sid *domain_sid,
7398                              struct torture_samr_context *ctx)
7399 {
7400         uint32_t num_total = ctx->num_objects_large_dc;
7401         uint32_t num_enum = 0;
7402         uint32_t num_disp = 0;
7403         uint32_t num_created = 0;
7404         uint32_t num_anounced = 0;
7405         bool ret = true;
7406         uint32_t i;
7407         struct dcerpc_binding_handle *b = p->binding_handle;
7408
7409         struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7410
7411         /* query */
7412
7413         {
7414                 struct samr_QueryDomainInfo2 r;
7415                 union samr_DomainInfo *info;
7416                 r.in.domain_handle = domain_handle;
7417                 r.in.level = 2;
7418                 r.out.info = &info;
7419
7420                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7421                         "QueryDomainInfo2 failed");
7422                 torture_assert_ntstatus_ok(tctx, r.out.result,
7423                         "failed to query domain info");
7424
7425                 switch (ctx->choice) {
7426                 case TORTURE_SAMR_MANY_ACCOUNTS:
7427                         num_anounced = info->general.num_users;
7428                         break;
7429                 case TORTURE_SAMR_MANY_GROUPS:
7430                         num_anounced = info->general.num_groups;
7431                         break;
7432                 case TORTURE_SAMR_MANY_ALIASES:
7433                         num_anounced = info->general.num_aliases;
7434                         break;
7435                 default:
7436                         return false;
7437                 }
7438         }
7439
7440         /* create */
7441
7442         for (i=0; i < num_total; i++) {
7443
7444                 const char *name = NULL;
7445
7446                 switch (ctx->choice) {
7447                 case TORTURE_SAMR_MANY_ACCOUNTS:
7448                         name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7449                         ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
7450                         break;
7451                 case TORTURE_SAMR_MANY_GROUPS:
7452                         name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7453                         ret &= test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false);
7454                         break;
7455                 case TORTURE_SAMR_MANY_ALIASES:
7456                         name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7457                         ret &= test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false);
7458                         break;
7459                 default:
7460                         return false;
7461                 }
7462                 if (!policy_handle_empty(&handles[i])) {
7463                         num_created++;
7464                 }
7465         }
7466
7467         /* enum */
7468
7469         switch (ctx->choice) {
7470         case TORTURE_SAMR_MANY_ACCOUNTS:
7471                 ret &= test_EnumDomainUsers(b, tctx, domain_handle, &num_enum);
7472                 break;
7473         case TORTURE_SAMR_MANY_GROUPS:
7474                 ret &= test_EnumDomainGroups(b, tctx, domain_handle, &num_enum);
7475                 break;
7476         case TORTURE_SAMR_MANY_ALIASES:
7477                 ret &= test_EnumDomainAliases(b, tctx, domain_handle, &num_enum);
7478                 break;
7479         default:
7480                 return false;
7481         }
7482
7483         /* dispinfo */
7484
7485         switch (ctx->choice) {
7486         case TORTURE_SAMR_MANY_ACCOUNTS:
7487                 ret &= test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp);
7488                 break;
7489         case TORTURE_SAMR_MANY_GROUPS:
7490                 ret &= test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp);
7491                 break;
7492         case TORTURE_SAMR_MANY_ALIASES:
7493                 /* no aliases in dispinfo */
7494                 break;
7495         default:
7496                 return false;
7497         }
7498
7499         /* close or delete */
7500
7501         for (i=0; i < num_total; i++) {
7502
7503                 if (policy_handle_empty(&handles[i])) {
7504                         continue;
7505                 }
7506
7507                 if (torture_setting_bool(tctx, "samba3", false)) {
7508                         ret &= test_samr_handle_Close(b, tctx, &handles[i]);
7509                 } else {
7510                         switch (ctx->choice) {
7511                         case TORTURE_SAMR_MANY_ACCOUNTS:
7512                                 ret &= test_DeleteUser(b, tctx, &handles[i]);
7513                                 break;
7514                         case TORTURE_SAMR_MANY_GROUPS:
7515                                 ret &= test_DeleteDomainGroup(b, tctx, &handles[i]);
7516                                 break;
7517                         case TORTURE_SAMR_MANY_ALIASES:
7518                                 ret &= test_DeleteAlias(b, tctx, &handles[i]);
7519                                 break;
7520                         default:
7521                                 return false;
7522                         }
7523                 }
7524         }
7525
7526         talloc_free(handles);
7527
7528         if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7529                 torture_comment(tctx,
7530                                 "unexpected number of results (%u) returned in enum call, expected %u\n",
7531                                 num_enum, num_anounced + num_created);
7532
7533                 torture_comment(tctx,
7534                                 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7535                                 num_disp, num_anounced + num_created);
7536         }
7537         return ret;
7538 }
7539
7540 static bool test_Connect(struct dcerpc_binding_handle *b,
7541                          struct torture_context *tctx,
7542                          struct policy_handle *handle);
7543
7544 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7545                             struct torture_samr_context *ctx, struct dom_sid *sid)
7546 {
7547         struct samr_OpenDomain r;
7548         struct policy_handle domain_handle;
7549         struct policy_handle alias_handle;
7550         struct policy_handle user_handle;
7551         struct policy_handle group_handle;
7552         bool ret = true;
7553         struct dcerpc_binding_handle *b = p->binding_handle;
7554
7555         ZERO_STRUCT(alias_handle);
7556         ZERO_STRUCT(user_handle);
7557         ZERO_STRUCT(group_handle);
7558         ZERO_STRUCT(domain_handle);
7559
7560         torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7561
7562         r.in.connect_handle = &ctx->handle;
7563         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7564         r.in.sid = sid;
7565         r.out.domain_handle = &domain_handle;
7566
7567         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7568                 "OpenDomain failed");
7569         torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7570
7571         /* run the domain tests with the main handle closed - this tests
7572            the servers reference counting */
7573         torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7574
7575         switch (ctx->choice) {
7576         case TORTURE_SAMR_PASSWORDS:
7577         case TORTURE_SAMR_USER_PRIVILEGES:
7578                 if (!torture_setting_bool(tctx, "samba3", false)) {
7579                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7580                 }
7581                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7582                 if (!ret) {
7583                         torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7584                 }
7585                 break;
7586         case TORTURE_SAMR_USER_ATTRIBUTES:
7587                 if (!torture_setting_bool(tctx, "samba3", false)) {
7588                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7589                 }
7590                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7591                 /* This test needs 'complex' users to validate */
7592                 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7593                 if (!ret) {
7594                         torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7595                 }
7596                 break;
7597         case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7598         case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7599         case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7600                 if (!torture_setting_bool(tctx, "samba3", false)) {
7601                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7602                 }
7603                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7604                 if (!ret) {
7605                         torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7606                 }
7607                 break;
7608         case TORTURE_SAMR_MANY_ACCOUNTS:
7609         case TORTURE_SAMR_MANY_GROUPS:
7610         case TORTURE_SAMR_MANY_ALIASES:
7611                 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7612                 if (!ret) {
7613                         torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7614                 }
7615                 break;
7616         case TORTURE_SAMR_OTHER:
7617                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7618                 if (!ret) {
7619                         torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7620                 }
7621                 if (!torture_setting_bool(tctx, "samba3", false)) {
7622                         ret &= test_QuerySecurity(b, tctx, &domain_handle);
7623                 }
7624                 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7625                 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7626                 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7627                 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7628                 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7629                 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7630                 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7631                 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7632                 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7633                 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7634                 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7635                 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7636                 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7637
7638                 if (torture_setting_bool(tctx, "samba4", false)) {
7639                         torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7640                 } else {
7641                         ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7642                         ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7643                 }
7644                 ret &= test_GroupList(b, tctx, &domain_handle);
7645                 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7646                 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7647                 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7648                 if (!ret) {
7649                         torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7650                 }
7651                 break;
7652         }
7653
7654         if (!policy_handle_empty(&user_handle) &&
7655             !test_DeleteUser(b, tctx, &user_handle)) {
7656                 ret = false;
7657         }
7658
7659         if (!policy_handle_empty(&alias_handle) &&
7660             !test_DeleteAlias(b, tctx, &alias_handle)) {
7661                 ret = false;
7662         }
7663
7664         if (!policy_handle_empty(&group_handle) &&
7665             !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7666                 ret = false;
7667         }
7668
7669         torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7670
7671         torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7672         /* reconnect the main handle */
7673
7674         if (!ret) {
7675                 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7676         }
7677
7678         return ret;
7679 }
7680
7681 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7682                               struct torture_samr_context *ctx, const char *domain)
7683 {
7684         struct samr_LookupDomain r;
7685         struct dom_sid2 *sid = NULL;
7686         struct lsa_String n1;
7687         struct lsa_String n2;
7688         bool ret = true;
7689         struct dcerpc_binding_handle *b = p->binding_handle;
7690
7691         torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7692
7693         /* check for correct error codes */
7694         r.in.connect_handle = &ctx->handle;
7695         r.in.domain_name = &n2;
7696         r.out.sid = &sid;
7697         n2.string = NULL;
7698
7699         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7700                 "LookupDomain failed");
7701         torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7702
7703         init_lsa_String(&n2, "xxNODOMAINxx");
7704
7705         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7706                 "LookupDomain failed");
7707         torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7708
7709         r.in.connect_handle = &ctx->handle;
7710
7711         init_lsa_String(&n1, domain);
7712         r.in.domain_name = &n1;
7713
7714         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7715                 "LookupDomain failed");
7716         torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7717
7718         if (!test_GetDomPwInfo(p, tctx, &n1)) {
7719                 ret = false;
7720         }
7721
7722         if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7723                 ret = false;
7724         }
7725
7726         return ret;
7727 }
7728
7729
7730 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7731                              struct torture_samr_context *ctx)
7732 {
7733         struct samr_EnumDomains r;
7734         uint32_t resume_handle = 0;
7735         uint32_t num_entries = 0;
7736         struct samr_SamArray *sam = NULL;
7737         int i;
7738         bool ret = true;
7739         struct dcerpc_binding_handle *b = p->binding_handle;
7740
7741         r.in.connect_handle = &ctx->handle;
7742         r.in.resume_handle = &resume_handle;
7743         r.in.buf_size = (uint32_t)-1;
7744         r.out.resume_handle = &resume_handle;
7745         r.out.num_entries = &num_entries;
7746         r.out.sam = &sam;
7747
7748         torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7749                 "EnumDomains failed");
7750         torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7751
7752         if (!*r.out.sam) {
7753                 return false;
7754         }
7755
7756         for (i=0;i<sam->count;i++) {
7757                 if (!test_LookupDomain(p, tctx, ctx,
7758                                        sam->entries[i].name.string)) {
7759                         ret = false;
7760                 }
7761         }
7762
7763         torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7764                 "EnumDomains failed");
7765         torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7766
7767         return ret;
7768 }
7769
7770
7771 static bool test_Connect(struct dcerpc_binding_handle *b,
7772                          struct torture_context *tctx,
7773                          struct policy_handle *handle)
7774 {
7775         struct samr_Connect r;
7776         struct samr_Connect2 r2;
7777         struct samr_Connect3 r3;
7778         struct samr_Connect4 r4;
7779         struct samr_Connect5 r5;
7780         union samr_ConnectInfo info;
7781         struct policy_handle h;
7782         uint32_t level_out = 0;
7783         bool ret = true, got_handle = false;
7784
7785         torture_comment(tctx, "Testing samr_Connect\n");
7786
7787         r.in.system_name = 0;
7788         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7789         r.out.connect_handle = &h;
7790
7791         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7792                 "Connect failed");
7793         if (!NT_STATUS_IS_OK(r.out.result)) {
7794                 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7795                 ret = false;
7796         } else {
7797                 got_handle = true;
7798                 *handle = h;
7799         }
7800
7801         torture_comment(tctx, "Testing samr_Connect2\n");
7802
7803         r2.in.system_name = NULL;
7804         r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7805         r2.out.connect_handle = &h;
7806
7807         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7808                 "Connect2 failed");
7809         if (!NT_STATUS_IS_OK(r2.out.result)) {
7810                 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7811                 ret = false;
7812         } else {
7813                 if (got_handle) {
7814                         test_samr_handle_Close(b, tctx, handle);
7815                 }
7816                 got_handle = true;
7817                 *handle = h;
7818         }
7819
7820         torture_comment(tctx, "Testing samr_Connect3\n");
7821
7822         r3.in.system_name = NULL;
7823         r3.in.unknown = 0;
7824         r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7825         r3.out.connect_handle = &h;
7826
7827         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
7828                 "Connect3 failed");
7829         if (!NT_STATUS_IS_OK(r3.out.result)) {
7830                 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
7831                 ret = false;
7832         } else {
7833                 if (got_handle) {
7834                         test_samr_handle_Close(b, tctx, handle);
7835                 }
7836                 got_handle = true;
7837                 *handle = h;
7838         }
7839
7840         torture_comment(tctx, "Testing samr_Connect4\n");
7841
7842         r4.in.system_name = "";
7843         r4.in.client_version = 0;
7844         r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7845         r4.out.connect_handle = &h;
7846
7847         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
7848                 "Connect4 failed");
7849         if (!NT_STATUS_IS_OK(r4.out.result)) {
7850                 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
7851                 ret = false;
7852         } else {
7853                 if (got_handle) {
7854                         test_samr_handle_Close(b, tctx, handle);
7855                 }
7856                 got_handle = true;
7857                 *handle = h;
7858         }
7859
7860         torture_comment(tctx, "Testing samr_Connect5\n");
7861
7862         info.info1.client_version = 0;
7863         info.info1.unknown2 = 0;
7864
7865         r5.in.system_name = "";
7866         r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7867         r5.in.level_in = 1;
7868         r5.out.level_out = &level_out;
7869         r5.in.info_in = &info;
7870         r5.out.info_out = &info;
7871         r5.out.connect_handle = &h;
7872
7873         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
7874                 "Connect5 failed");
7875         if (!NT_STATUS_IS_OK(r5.out.result)) {
7876                 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
7877                 ret = false;
7878         } else {
7879                 if (got_handle) {
7880                         test_samr_handle_Close(b, tctx, handle);
7881                 }
7882                 got_handle = true;
7883                 *handle = h;
7884         }
7885
7886         return ret;
7887 }
7888
7889
7890 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
7891                                        struct torture_context *tctx)
7892 {
7893         struct samr_ValidatePassword r;
7894         union samr_ValidatePasswordReq req;
7895         union samr_ValidatePasswordRep *repp = NULL;
7896         NTSTATUS status;
7897         const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
7898         int i;
7899         struct dcerpc_binding_handle *b = p->binding_handle;
7900
7901         torture_comment(tctx, "Testing samr_ValidatePassword\n");
7902
7903         ZERO_STRUCT(r);
7904         r.in.level = NetValidatePasswordReset;
7905         r.in.req = &req;
7906         r.out.rep = &repp;
7907
7908         ZERO_STRUCT(req);
7909         req.req3.account.string = "non-existant-account-aklsdji";
7910
7911         for (i=0; passwords[i]; i++) {
7912                 req.req3.password.string = passwords[i];
7913
7914                 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
7915                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
7916                         torture_skip(tctx, "ValidatePassword not supported by server\n");
7917                 }
7918                 torture_assert_ntstatus_ok(tctx, status,
7919                                            "samr_ValidatePassword failed");
7920                 torture_assert_ntstatus_ok(tctx, r.out.result,
7921                                            "samr_ValidatePassword failed");
7922                 torture_comment(tctx, "Server %s password '%s' with code %i\n",
7923                                 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
7924                                 req.req3.password.string, repp->ctr3.status);
7925         }
7926
7927         return true;
7928 }
7929
7930 bool torture_rpc_samr(struct torture_context *torture)
7931 {
7932         NTSTATUS status;
7933         struct dcerpc_pipe *p;
7934         bool ret = true;
7935         struct torture_samr_context *ctx;
7936         struct dcerpc_binding_handle *b;
7937
7938         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7939         if (!NT_STATUS_IS_OK(status)) {
7940                 return false;
7941         }
7942         b = p->binding_handle;
7943
7944         ctx = talloc_zero(torture, struct torture_samr_context);
7945
7946         ctx->choice = TORTURE_SAMR_OTHER;
7947
7948         ret &= test_Connect(b, torture, &ctx->handle);
7949
7950         if (!torture_setting_bool(torture, "samba3", false)) {
7951                 ret &= test_QuerySecurity(b, torture, &ctx->handle);
7952         }
7953
7954         ret &= test_EnumDomains(p, torture, ctx);
7955
7956         ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
7957
7958         ret &= test_Shutdown(b, torture, &ctx->handle);
7959
7960         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7961
7962         return ret;
7963 }
7964
7965
7966 bool torture_rpc_samr_users(struct torture_context *torture)
7967 {
7968         NTSTATUS status;
7969         struct dcerpc_pipe *p;
7970         bool ret = true;
7971         struct torture_samr_context *ctx;
7972         struct dcerpc_binding_handle *b;
7973
7974         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7975         if (!NT_STATUS_IS_OK(status)) {
7976                 return false;
7977         }
7978         b = p->binding_handle;
7979
7980         ctx = talloc_zero(torture, struct torture_samr_context);
7981
7982         ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
7983
7984         ret &= test_Connect(b, torture, &ctx->handle);
7985
7986         if (!torture_setting_bool(torture, "samba3", false)) {
7987                 ret &= test_QuerySecurity(b, torture, &ctx->handle);
7988         }
7989
7990         ret &= test_EnumDomains(p, torture, ctx);
7991
7992         ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
7993
7994         ret &= test_Shutdown(b, torture, &ctx->handle);
7995
7996         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7997
7998         return ret;
7999 }
8000
8001
8002 bool torture_rpc_samr_passwords(struct torture_context *torture)
8003 {
8004         NTSTATUS status;
8005         struct dcerpc_pipe *p;
8006         bool ret = true;
8007         struct torture_samr_context *ctx;
8008         struct dcerpc_binding_handle *b;
8009
8010         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8011         if (!NT_STATUS_IS_OK(status)) {
8012                 return false;
8013         }
8014         b = p->binding_handle;
8015
8016         ctx = talloc_zero(torture, struct torture_samr_context);
8017
8018         ctx->choice = TORTURE_SAMR_PASSWORDS;
8019
8020         ret &= test_Connect(b, torture, &ctx->handle);
8021
8022         ret &= test_EnumDomains(p, torture, ctx);
8023
8024         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8025
8026         ret &= test_samr_ValidatePassword(p, torture);
8027
8028         return ret;
8029 }
8030
8031 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8032                                         struct dcerpc_pipe *p2,
8033                                         struct cli_credentials *machine_credentials)
8034 {
8035         NTSTATUS status;
8036         struct dcerpc_pipe *p;
8037         bool ret = true;
8038         struct torture_samr_context *ctx;
8039         struct dcerpc_binding_handle *b;
8040
8041         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8042         if (!NT_STATUS_IS_OK(status)) {
8043                 return false;
8044         }
8045         b = p->binding_handle;
8046
8047         ctx = talloc_zero(torture, struct torture_samr_context);
8048
8049         ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8050         ctx->machine_credentials = machine_credentials;
8051
8052         ret &= test_Connect(b, torture, &ctx->handle);
8053
8054         ret &= test_EnumDomains(p, torture, ctx);
8055
8056         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8057
8058         return ret;
8059 }
8060
8061 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8062 {
8063         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
8064         struct torture_rpc_tcase *tcase;
8065
8066         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8067                                                           &ndr_table_samr,
8068                                                           TEST_ACCOUNT_NAME_PWD);
8069
8070         torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8071                                          torture_rpc_samr_pwdlastset);
8072
8073         return suite;
8074 }
8075
8076 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8077                                                           struct dcerpc_pipe *p2,
8078                                                           struct cli_credentials *machine_credentials)
8079 {
8080         NTSTATUS status;
8081         struct dcerpc_pipe *p;
8082         bool ret = true;
8083         struct torture_samr_context *ctx;
8084         struct dcerpc_binding_handle *b;
8085
8086         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8087         if (!NT_STATUS_IS_OK(status)) {
8088                 return false;
8089         }
8090         b = p->binding_handle;
8091
8092         ctx = talloc_zero(torture, struct torture_samr_context);
8093
8094         ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8095         ctx->machine_credentials = machine_credentials;
8096
8097         ret &= test_Connect(b, torture, &ctx->handle);
8098
8099         ret &= test_EnumDomains(p, torture, ctx);
8100
8101         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8102
8103         return ret;
8104 }
8105
8106 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8107 {
8108         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
8109         struct torture_rpc_tcase *tcase;
8110
8111         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8112                                                           &ndr_table_samr,
8113                                                           TEST_ACCOUNT_NAME_PWD);
8114
8115         torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8116                                          torture_rpc_samr_users_privileges_delete_user);
8117
8118         return suite;
8119 }
8120
8121 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8122                                            struct dcerpc_pipe *p2,
8123                                            void *data)
8124 {
8125         NTSTATUS status;
8126         struct dcerpc_pipe *p;
8127         bool ret = true;
8128         struct torture_samr_context *ctx =
8129                 talloc_get_type_abort(data, struct torture_samr_context);
8130         struct dcerpc_binding_handle *b;
8131
8132         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8133         if (!NT_STATUS_IS_OK(status)) {
8134                 return false;
8135         }
8136         b = p->binding_handle;
8137
8138         ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8139         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8140                                                         ctx->num_objects_large_dc);
8141
8142         ret &= test_Connect(b, torture, &ctx->handle);
8143
8144         ret &= test_EnumDomains(p, torture, ctx);
8145
8146         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8147
8148         return ret;
8149 }
8150
8151 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8152                                          struct dcerpc_pipe *p2,
8153                                          void *data)
8154 {
8155         NTSTATUS status;
8156         struct dcerpc_pipe *p;
8157         bool ret = true;
8158         struct torture_samr_context *ctx =
8159                 talloc_get_type_abort(data, struct torture_samr_context);
8160         struct dcerpc_binding_handle *b;
8161
8162         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8163         if (!NT_STATUS_IS_OK(status)) {
8164                 return false;
8165         }
8166         b = p->binding_handle;
8167
8168         ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8169         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8170                                                         ctx->num_objects_large_dc);
8171
8172         ret &= test_Connect(b, torture, &ctx->handle);
8173
8174         ret &= test_EnumDomains(p, torture, ctx);
8175
8176         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8177
8178         return ret;
8179 }
8180
8181 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8182                                           struct dcerpc_pipe *p2,
8183                                           void *data)
8184 {
8185         NTSTATUS status;
8186         struct dcerpc_pipe *p;
8187         bool ret = true;
8188         struct torture_samr_context *ctx =
8189                 talloc_get_type_abort(data, struct torture_samr_context);
8190         struct dcerpc_binding_handle *b;
8191
8192         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8193         if (!NT_STATUS_IS_OK(status)) {
8194                 return false;
8195         }
8196         b = p->binding_handle;
8197
8198         ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8199         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8200                                                         ctx->num_objects_large_dc);
8201
8202         ret &= test_Connect(b, torture, &ctx->handle);
8203
8204         ret &= test_EnumDomains(p, torture, ctx);
8205
8206         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8207
8208         return ret;
8209 }
8210
8211 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8212 {
8213         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
8214         struct torture_rpc_tcase *tcase;
8215         struct torture_samr_context *ctx;
8216
8217         tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8218
8219         ctx = talloc_zero(suite, struct torture_samr_context);
8220         ctx->num_objects_large_dc = 150;
8221
8222         torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8223                                       torture_rpc_samr_many_aliases, ctx);
8224         torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8225                                       torture_rpc_samr_many_groups, ctx);
8226         torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8227                                       torture_rpc_samr_many_accounts, ctx);
8228
8229         return suite;
8230 }
8231
8232 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8233                                          struct dcerpc_pipe *p2,
8234                                          struct cli_credentials *machine_credentials)
8235 {
8236         NTSTATUS status;
8237         struct dcerpc_pipe *p;
8238         bool ret = true;
8239         struct torture_samr_context *ctx;
8240         struct dcerpc_binding_handle *b;
8241
8242         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8243         if (!NT_STATUS_IS_OK(status)) {
8244                 return false;
8245         }
8246         b = p->binding_handle;
8247
8248         ctx = talloc_zero(torture, struct torture_samr_context);
8249
8250         ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8251         ctx->machine_credentials = machine_credentials;
8252
8253         ret &= test_Connect(b, torture, &ctx->handle);
8254
8255         ret &= test_EnumDomains(p, torture, ctx);
8256
8257         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8258
8259         return ret;
8260 }
8261
8262 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8263 {
8264         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-BADPWDCOUNT");
8265         struct torture_rpc_tcase *tcase;
8266
8267         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8268                                                           &ndr_table_samr,
8269                                                           TEST_ACCOUNT_NAME_PWD);
8270
8271         torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8272                                          torture_rpc_samr_badpwdcount);
8273
8274         return suite;
8275 }
8276
8277 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8278                                      struct dcerpc_pipe *p2,
8279                                      struct cli_credentials *machine_credentials)
8280 {
8281         NTSTATUS status;
8282         struct dcerpc_pipe *p;
8283         bool ret = true;
8284         struct torture_samr_context *ctx;
8285         struct dcerpc_binding_handle *b;
8286
8287         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8288         if (!NT_STATUS_IS_OK(status)) {
8289                 return false;
8290         }
8291         b = p->binding_handle;
8292
8293         ctx = talloc_zero(torture, struct torture_samr_context);
8294
8295         ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8296         ctx->machine_credentials = machine_credentials;
8297
8298         ret &= test_Connect(b, torture, &ctx->handle);
8299
8300         ret &= test_EnumDomains(p, torture, ctx);
8301
8302         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8303
8304         return ret;
8305 }
8306
8307 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8308 {
8309         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-LOCKOUT");
8310         struct torture_rpc_tcase *tcase;
8311
8312         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8313                                                           &ndr_table_samr,
8314                                                           TEST_ACCOUNT_NAME_PWD);
8315
8316         torture_rpc_tcase_add_test_creds(tcase, "lockout",
8317                                          torture_rpc_samr_lockout);
8318
8319         return suite;
8320 }
8321
8322