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