s4:torture: create new test_SetDomainInfo_ntstatus()
[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
3491 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3492                                       struct dcerpc_pipe *np,
3493                                       struct torture_context *tctx,
3494                                       uint32_t acct_flags,
3495                                       const char *acct_name,
3496                                       struct policy_handle *domain_handle,
3497                                       struct policy_handle *user_handle,
3498                                       char **password,
3499                                       struct cli_credentials *machine_credentials,
3500                                       const char *comment,
3501                                       bool disable,
3502                                       bool interactive,
3503                                       NTSTATUS expected_success_status,
3504                                       struct samr_DomInfo1 *info1,
3505                                       struct samr_DomInfo12 *info12)
3506 {
3507         union samr_DomainInfo info;
3508         char **passwords;
3509         int i;
3510         uint32_t badpwdcount, tmp;
3511         uint32_t password_history_length = 12;
3512         uint32_t lockout_threshold = 15;
3513
3514         torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3515
3516         torture_assert(tctx, password_history_length < lockout_threshold,
3517                 "password history length needs to be smaller than account lockout threshold for this test");
3518
3519
3520         /* set policies */
3521
3522         info.info1 = *info1;
3523         info.info1.password_history_length = password_history_length;
3524
3525         torture_assert(tctx,
3526                        test_SetDomainInfo(p, tctx, domain_handle,
3527                                           DomainPasswordInformation, &info),
3528                        "failed to set password history length");
3529
3530         info.info12 = *info12;
3531         info.info12.lockout_threshold = lockout_threshold;
3532
3533         torture_assert(tctx,
3534                        test_SetDomainInfo(p, tctx, domain_handle,
3535                                           DomainLockoutInformation, &info),
3536                        "failed to set lockout threshold");
3537
3538         /* reset bad pwd count */
3539
3540         torture_assert(tctx,
3541                 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3542
3543
3544         /* enable or disable account */
3545         if (disable) {
3546                 torture_assert(tctx,
3547                                test_SetUserInfo_acct_flags(p, tctx, user_handle,
3548                                                 acct_flags | ACB_DISABLED),
3549                                "failed to disable user");
3550         } else {
3551                 torture_assert(tctx,
3552                                test_SetUserInfo_acct_flags(p, tctx, user_handle,
3553                                                 acct_flags & ~ACB_DISABLED),
3554                                "failed to enable user");
3555         }
3556
3557
3558         /* setup password history */
3559
3560         passwords = talloc_array(tctx, char *, password_history_length);
3561
3562         for (i=0; i < password_history_length; i++) {
3563
3564                 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3565                         "failed to set password");
3566                 passwords[i] = talloc_strdup(tctx, *password);
3567
3568                 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3569                                               acct_name, passwords[i],
3570                                               expected_success_status, interactive)) {
3571                         torture_fail(tctx, "failed to auth with latest password");
3572                 }
3573
3574                 torture_assert(tctx,
3575                         test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3576
3577                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3578         }
3579
3580
3581         /* test with wrong password */
3582
3583         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3584                                       acct_name, "random_crap",
3585                                       NT_STATUS_WRONG_PASSWORD, interactive)) {
3586                 torture_fail(tctx, "succeeded to authenticate with wrong password");
3587         }
3588
3589         torture_assert(tctx,
3590                 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3591
3592         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3593
3594
3595         /* test with latest good password */
3596
3597         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3598                                       passwords[password_history_length-1],
3599                                       expected_success_status, interactive)) {
3600                 torture_fail(tctx, "succeeded to authenticate with wrong password");
3601         }
3602
3603         torture_assert(tctx,
3604                 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3605
3606         if (disable) {
3607                 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3608         } else {
3609                 /* only enabled accounts get the bad pwd count reset upon
3610                  * successful logon */
3611                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3612         }
3613
3614         tmp = badpwdcount;
3615
3616
3617         /* test password history */
3618
3619         for (i=0; i < password_history_length; i++) {
3620
3621                 torture_comment(tctx, "Testing bad password count behavior with "
3622                                       "password #%d of #%d\n", i, password_history_length);
3623
3624                 /* - network samlogon will succeed auth and not
3625                  *   increase badpwdcount for 2 last entries
3626                  * - interactive samlogon only for the last one */
3627
3628                 if (i == password_history_length - 1 ||
3629                     (i == password_history_length - 2 && !interactive)) {
3630
3631                         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3632                                                       acct_name, passwords[i],
3633                                                       expected_success_status, interactive)) {
3634                                 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3635                         }
3636
3637                         torture_assert(tctx,
3638                                 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3639
3640                         if (disable) {
3641                                 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3642                                 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3643                         } else {
3644                                 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3645                                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3646                         }
3647
3648                         tmp = badpwdcount;
3649
3650                         continue;
3651                 }
3652
3653                 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3654                                               acct_name, passwords[i],
3655                                               NT_STATUS_WRONG_PASSWORD, interactive)) {
3656                         torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3657                 }
3658
3659                 torture_assert(tctx,
3660                         test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3661
3662                 /* - network samlogon will fail auth but not increase
3663                  *   badpwdcount for 3rd last entry
3664                  * - interactive samlogon for 3rd and 2nd last entry */
3665
3666                 if (i == password_history_length - 3 ||
3667                     (i == password_history_length - 2 && interactive)) {
3668                         /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3669                         torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3670                 } else {
3671                         /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3672                         torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3673                 }
3674
3675                 tmp = badpwdcount;
3676         }
3677
3678         return true;
3679 }
3680
3681 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3682                                            struct torture_context *tctx,
3683                                            uint32_t acct_flags,
3684                                            const char *acct_name,
3685                                            struct policy_handle *domain_handle,
3686                                            struct policy_handle *user_handle,
3687                                            char **password,
3688                                            struct cli_credentials *machine_credentials)
3689 {
3690         union samr_DomainInfo *q_info, s_info;
3691         struct samr_DomInfo1 info1, _info1;
3692         struct samr_DomInfo12 info12, _info12;
3693         bool ret = true;
3694         struct dcerpc_pipe *np;
3695         int i;
3696
3697         struct {
3698                 const char *comment;
3699                 bool disabled;
3700                 bool interactive;
3701                 NTSTATUS expected_success_status;
3702         } creds[] = {
3703                 {
3704                         .comment                = "network logon (disabled account)",
3705                         .disabled               = true,
3706                         .interactive            = false,
3707                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3708                 },
3709                 {
3710                         .comment                = "network logon (enabled account)",
3711                         .disabled               = false,
3712                         .interactive            = false,
3713                         .expected_success_status= NT_STATUS_OK
3714                 },
3715                 {
3716                         .comment                = "interactive logon (disabled account)",
3717                         .disabled               = true,
3718                         .interactive            = true,
3719                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3720                 },
3721                 {
3722                         .comment                = "interactive logon (enabled account)",
3723                         .disabled               = false,
3724                         .interactive            = true,
3725                         .expected_success_status= NT_STATUS_OK
3726                 },
3727         };
3728
3729         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3730
3731         /* backup old policies */
3732
3733         {
3734                 struct samr_QueryDomainInfo2 r;
3735
3736                 r.in.domain_handle = domain_handle;
3737                 r.in.level = DomainPasswordInformation;
3738                 r.out.info = &q_info;
3739
3740                 torture_assert_ntstatus_ok(tctx,
3741                         dcerpc_samr_QueryDomainInfo2(p, tctx, &r),
3742                         "failed to query domain info level 1");
3743
3744                 info1 = q_info->info1;
3745         }
3746
3747         {
3748                 struct samr_QueryDomainInfo2 r;
3749
3750                 r.in.domain_handle = domain_handle;
3751                 r.in.level = DomainLockoutInformation;
3752                 r.out.info = &q_info;
3753
3754                 torture_assert_ntstatus_ok(tctx,
3755                         dcerpc_samr_QueryDomainInfo2(p, tctx, &r),
3756                         "failed to query domain info level 12");
3757
3758                 info12 = q_info->info12;
3759         }
3760
3761         _info1 = info1;
3762         _info12 = info12;
3763
3764         /* run tests */
3765
3766         for (i=0; i < ARRAY_SIZE(creds); i++) {
3767
3768                 /* skip trust tests for now */
3769                 if (acct_flags & ACB_WSTRUST ||
3770                     acct_flags & ACB_SVRTRUST ||
3771                     acct_flags & ACB_DOMTRUST) {
3772                         continue;
3773                 }
3774
3775                 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
3776                                                  domain_handle, user_handle, password,
3777                                                  machine_credentials,
3778                                                  creds[i].comment,
3779                                                  creds[i].disabled,
3780                                                  creds[i].interactive,
3781                                                  creds[i].expected_success_status,
3782                                                  &_info1, &_info12);
3783                 if (!ret) {
3784                         torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
3785                 } else {
3786                         torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
3787                 }
3788         }
3789
3790         /* restore policies */
3791
3792         s_info.info1 = info1;
3793
3794         torture_assert(tctx,
3795                        test_SetDomainInfo(p, tctx, domain_handle,
3796                                           DomainPasswordInformation, &s_info),
3797                        "failed to set password information");
3798
3799         s_info.info12 = info12;
3800
3801         torture_assert(tctx,
3802                        test_SetDomainInfo(p, tctx, domain_handle,
3803                                           DomainLockoutInformation, &s_info),
3804                        "failed to set lockout information");
3805
3806         return ret;
3807 }
3808
3809 static bool test_QueryUserInfo_acct_flags(struct dcerpc_pipe *p,
3810                                           struct torture_context *tctx,
3811                                           struct policy_handle *handle,
3812                                           uint32_t *acct_flags)
3813 {
3814         union samr_UserInfo *info;
3815         struct samr_QueryUserInfo r;
3816
3817         r.in.user_handle = handle;
3818         r.in.level = 16;
3819         r.out.info = &info;
3820
3821         torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3822
3823         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo(p, tctx, &r),
3824                 "failed to query userinfo");
3825
3826         *acct_flags = info->info16.acct_flags;
3827
3828         torture_comment(tctx, "  (acct_flags: 0x%08x)\n", *acct_flags);
3829
3830         return true;
3831 }
3832
3833 static bool test_Password_lockout(struct dcerpc_pipe *p,
3834                                   struct dcerpc_pipe *np,
3835                                   struct torture_context *tctx,
3836                                   uint32_t acct_flags,
3837                                   const char *acct_name,
3838                                   struct policy_handle *domain_handle,
3839                                   struct policy_handle *user_handle,
3840                                   char **password,
3841                                   struct cli_credentials *machine_credentials,
3842                                   const char *comment,
3843                                   bool disable,
3844                                   bool interactive,
3845                                   NTSTATUS expected_success_status,
3846                                   struct samr_DomInfo1 *info1,
3847                                   struct samr_DomInfo12 *info12)
3848 {
3849         union samr_DomainInfo info;
3850         uint32_t badpwdcount;
3851         uint32_t password_history_length = 1;
3852         uint64_t lockout_threshold = 1;
3853         uint32_t lockout_seconds = 5;
3854         uint64_t delta_time_factor = 10 * 1000 * 1000;
3855
3856         torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
3857
3858         /* set policies */
3859
3860         info.info1 = *info1;
3861
3862         torture_comment(tctx, "setting password history lenght.\n");
3863         info.info1.password_history_length = password_history_length;
3864
3865         torture_assert(tctx,
3866                        test_SetDomainInfo(p, tctx, domain_handle,
3867                                           DomainPasswordInformation, &info),
3868                        "failed to set password history length");
3869
3870         info.info12 = *info12;
3871         info.info12.lockout_threshold = lockout_threshold;
3872
3873         /* set lockout duration < lockout window: should fail */
3874         info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3875         info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
3876
3877         torture_assert(tctx,
3878                 test_SetDomainInfo_ntstatus(p, tctx, domain_handle,
3879                                             DomainLockoutInformation, &info,
3880                                             NT_STATUS_INVALID_PARAMETER),
3881                 "setting lockout duration < lockout window gave unexpected result");
3882
3883         info.info12.lockout_duration = 0;
3884         info.info12.lockout_window = 0;
3885
3886         torture_assert(tctx,
3887                        test_SetDomainInfo(p, tctx, domain_handle,
3888                                           DomainLockoutInformation, &info),
3889                        "failed to set lockout window and duration to 0");
3890
3891
3892         /* set lockout duration of 5 seconds */
3893         info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3894         info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
3895
3896         torture_assert(tctx,
3897                        test_SetDomainInfo(p, tctx, domain_handle,
3898                                           DomainLockoutInformation, &info),
3899                        "failed to set lockout window and duration to 5 seconds");
3900
3901         /* reset bad pwd count */
3902
3903         torture_assert(tctx,
3904                 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3905
3906
3907         /* enable or disable account */
3908
3909         if (disable) {
3910                 torture_assert(tctx,
3911                                test_SetUserInfo_acct_flags(p, tctx, user_handle,
3912                                                 acct_flags | ACB_DISABLED),
3913                                "failed to disable user");
3914         } else {
3915                 torture_assert(tctx,
3916                                test_SetUserInfo_acct_flags(p, tctx, user_handle,
3917                                                 acct_flags & ~ACB_DISABLED),
3918                                "failed to enable user");
3919         }
3920
3921
3922         /* test logon with right password */
3923
3924         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3925                                       acct_name, *password,
3926                                       expected_success_status, interactive)) {
3927                 torture_fail(tctx, "failed to auth with latest password");
3928         }
3929
3930         torture_assert(tctx,
3931                 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3932         torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3933
3934
3935         /* test with wrong password ==> lockout */
3936
3937         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3938                                       acct_name, "random_crap",
3939                                       NT_STATUS_WRONG_PASSWORD, interactive)) {
3940                 torture_fail(tctx, "succeeded to authenticate with wrong password");
3941         }
3942
3943         torture_assert(tctx,
3944                 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3945         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3946
3947         torture_assert(tctx,
3948                 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3949         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3950                                  "expected account to be locked");
3951
3952
3953         /* test with good password */
3954
3955         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3956                                      *password,
3957                                      NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
3958         {
3959                 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
3960         }
3961
3962         /* bad pwd count should not get updated */
3963         torture_assert(tctx,
3964                 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3965         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3966
3967         /* curiously, windows does _not_ set the autlock flag */
3968         torture_assert(tctx,
3969                 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3970         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3971                                  "expected account to be locked");
3972
3973
3974         /* with bad password */
3975
3976         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3977                                       acct_name, "random_crap2",
3978                                       NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
3979         {
3980                 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
3981         }
3982
3983         /* bad pwd count should not get updated */
3984         torture_assert(tctx,
3985                 test_QueryUserInfo_badpwdcount(p, tctx, user_handle, &badpwdcount), "");
3986         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3987
3988         /* curiously, windows does _not_ set the autlock flag */
3989         torture_assert(tctx,
3990                 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
3991         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
3992                                  "expected account to be locked");
3993
3994
3995         /* let lockout duration expire ==> unlock */
3996
3997         torture_comment(tctx, "let lockout duration expire...\n");
3998         sleep(lockout_seconds + 1);
3999
4000         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4001                                      *password,
4002                                      expected_success_status, interactive))
4003         {
4004                 torture_fail(tctx, "failed to authenticate after lockout expired");
4005         }
4006
4007         torture_assert(tctx,
4008                 test_QueryUserInfo_acct_flags(p, tctx, user_handle, &acct_flags), "");
4009         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4010                                  "expected account not to be locked");
4011
4012         return true;
4013 }
4014
4015 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4016                                        struct torture_context *tctx,
4017                                        uint32_t acct_flags,
4018                                        const char *acct_name,
4019                                        struct policy_handle *domain_handle,
4020                                        struct policy_handle *user_handle,
4021                                        char **password,
4022                                        struct cli_credentials *machine_credentials)
4023 {
4024         union samr_DomainInfo *q_info, s_info;
4025         struct samr_DomInfo1 info1, _info1;
4026         struct samr_DomInfo12 info12, _info12;
4027         bool ret = true;
4028         struct dcerpc_pipe *np;
4029         int i;
4030
4031         struct {
4032                 const char *comment;
4033                 bool disabled;
4034                 bool interactive;
4035                 NTSTATUS expected_success_status;
4036         } creds[] = {
4037                 {
4038                         .comment                = "network logon (disabled account)",
4039                         .disabled               = true,
4040                         .interactive            = false,
4041                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4042                 },
4043                 {
4044                         .comment                = "network logon (enabled account)",
4045                         .disabled               = false,
4046                         .interactive            = false,
4047                         .expected_success_status= NT_STATUS_OK
4048                 },
4049                 {
4050                         .comment                = "interactive logon (disabled account)",
4051                         .disabled               = true,
4052                         .interactive            = true,
4053                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4054                 },
4055                 {
4056                         .comment                = "interactive logon (enabled account)",
4057                         .disabled               = false,
4058                         .interactive            = true,
4059                         .expected_success_status= NT_STATUS_OK
4060                 },
4061         };
4062
4063         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4064
4065         /* backup old policies */
4066
4067         {
4068                 struct samr_QueryDomainInfo2 r;
4069
4070                 r.in.domain_handle = domain_handle;
4071                 r.in.level = DomainPasswordInformation;
4072                 r.out.info = &q_info;
4073
4074                 torture_assert_ntstatus_ok(tctx,
4075                         dcerpc_samr_QueryDomainInfo2(p, tctx, &r),
4076                         "failed to query domain info level 1");
4077
4078                 info1 = q_info->info1;
4079         }
4080
4081         {
4082                 struct samr_QueryDomainInfo2 r;
4083
4084                 r.in.domain_handle = domain_handle;
4085                 r.in.level = DomainLockoutInformation;
4086                 r.out.info = &q_info;
4087
4088                 torture_assert_ntstatus_ok(tctx,
4089                         dcerpc_samr_QueryDomainInfo2(p, tctx, &r),
4090                         "failed to query domain info level 12");
4091
4092                 info12 = q_info->info12;
4093         }
4094
4095         _info1 = info1;
4096         _info12 = info12;
4097
4098         /* run tests */
4099
4100         for (i=0; i < ARRAY_SIZE(creds); i++) {
4101
4102                 /* skip trust tests for now */
4103                 if (acct_flags & ACB_WSTRUST ||
4104                     acct_flags & ACB_SVRTRUST ||
4105                     acct_flags & ACB_DOMTRUST) {
4106                         continue;
4107                 }
4108
4109                 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4110                                              domain_handle, user_handle, password,
4111                                              machine_credentials,
4112                                              creds[i].comment,
4113                                              creds[i].disabled,
4114                                              creds[i].interactive,
4115                                              creds[i].expected_success_status,
4116                                              &_info1, &_info12);
4117                 if (!ret) {
4118                         torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4119                 } else {
4120                         torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4121                 }
4122         }
4123
4124         /* restore policies */
4125
4126         s_info.info1 = info1;
4127
4128         torture_assert(tctx,
4129                        test_SetDomainInfo(p, tctx, domain_handle,
4130                                           DomainPasswordInformation, &s_info),
4131                        "failed to set password information");
4132
4133         s_info.info12 = info12;
4134
4135         torture_assert(tctx,
4136                        test_SetDomainInfo(p, tctx, domain_handle,
4137                                           DomainLockoutInformation, &s_info),
4138                        "failed to set lockout information");
4139
4140         return ret;
4141 }
4142
4143 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4144                                        struct dcerpc_pipe *lp,
4145                                        struct torture_context *tctx,
4146                                        struct policy_handle *domain_handle,
4147                                        struct policy_handle *lsa_handle,
4148                                        struct policy_handle *user_handle,
4149                                        const struct dom_sid *domain_sid,
4150                                        uint32_t rid,
4151                                        struct cli_credentials *machine_credentials)
4152 {
4153         NTSTATUS status;
4154         bool ret = true;
4155
4156         struct policy_handle lsa_acct_handle;
4157         struct dom_sid *user_sid;
4158
4159         user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4160
4161         {
4162                 struct lsa_EnumAccountRights r;
4163                 struct lsa_RightSet rights;
4164
4165                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4166
4167                 r.in.handle = lsa_handle;
4168                 r.in.sid = user_sid;
4169                 r.out.rights = &rights;
4170
4171                 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4172                 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4173                         "Expected enum rights for account to fail");
4174         }
4175
4176         {
4177                 struct lsa_RightSet rights;
4178                 struct lsa_StringLarge names[2];
4179                 struct lsa_AddAccountRights r;
4180
4181                 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4182
4183                 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4184                 init_lsa_StringLarge(&names[1], NULL);
4185
4186                 rights.count = 1;
4187                 rights.names = names;
4188
4189                 r.in.handle = lsa_handle;
4190                 r.in.sid = user_sid;
4191                 r.in.rights = &rights;
4192
4193                 status = dcerpc_lsa_AddAccountRights(lp, tctx, &r);
4194                 torture_assert_ntstatus_ok(tctx, status,
4195                         "Failed to add privileges");
4196         }
4197
4198         {
4199                 struct lsa_EnumAccounts r;
4200                 uint32_t resume_handle = 0;
4201                 struct lsa_SidArray lsa_sid_array;
4202                 int i;
4203                 bool found_sid = false;
4204
4205                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4206
4207                 r.in.handle = lsa_handle;
4208                 r.in.num_entries = 0x1000;
4209                 r.in.resume_handle = &resume_handle;
4210                 r.out.sids = &lsa_sid_array;
4211                 r.out.resume_handle = &resume_handle;
4212
4213                 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4214                 torture_assert_ntstatus_ok(tctx, status,
4215                         "Failed to enum accounts");
4216
4217                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4218                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4219                                 found_sid = true;
4220                         }
4221                 }
4222
4223                 torture_assert(tctx, found_sid,
4224                         "failed to list privileged account");
4225         }
4226
4227         {
4228                 struct lsa_EnumAccountRights r;
4229                 struct lsa_RightSet user_rights;
4230
4231                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4232
4233                 r.in.handle = lsa_handle;
4234                 r.in.sid = user_sid;
4235                 r.out.rights = &user_rights;
4236
4237                 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4238                 torture_assert_ntstatus_ok(tctx, status,
4239                         "Failed to enum rights for account");
4240
4241                 if (user_rights.count < 1) {
4242                         torture_warning(tctx, "failed to find newly added rights");
4243                         return false;
4244                 }
4245         }
4246
4247         {
4248                 struct lsa_OpenAccount r;
4249
4250                 torture_comment(tctx, "Testing LSA OpenAccount\n");
4251
4252                 r.in.handle = lsa_handle;
4253                 r.in.sid = user_sid;
4254                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4255                 r.out.acct_handle = &lsa_acct_handle;
4256
4257                 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
4258                 torture_assert_ntstatus_ok(tctx, status,
4259                         "Failed to open lsa account");
4260         }
4261
4262         {
4263                 struct lsa_GetSystemAccessAccount r;
4264                 uint32_t access_mask;
4265
4266                 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4267
4268                 r.in.handle = &lsa_acct_handle;
4269                 r.out.access_mask = &access_mask;
4270
4271                 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
4272                 torture_assert_ntstatus_ok(tctx, status,
4273                         "Failed to get lsa system access account");
4274         }
4275
4276         {
4277                 struct lsa_Close r;
4278
4279                 torture_comment(tctx, "Testing LSA Close\n");
4280
4281                 r.in.handle = &lsa_acct_handle;
4282                 r.out.handle = &lsa_acct_handle;
4283
4284                 status = dcerpc_lsa_Close(lp, tctx, &r);
4285                 torture_assert_ntstatus_ok(tctx, status,
4286                         "Failed to close lsa");
4287         }
4288
4289         {
4290                 struct samr_DeleteUser r;
4291
4292                 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4293
4294                 r.in.user_handle = user_handle;
4295                 r.out.user_handle = user_handle;
4296
4297                 status = dcerpc_samr_DeleteUser(p, tctx, &r);
4298                 torture_assert_ntstatus_ok(tctx, status, "Delete User failed");
4299         }
4300
4301         {
4302                 struct lsa_EnumAccounts r;
4303                 uint32_t resume_handle = 0;
4304                 struct lsa_SidArray lsa_sid_array;
4305                 int i;
4306                 bool found_sid = false;
4307
4308                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4309
4310                 r.in.handle = lsa_handle;
4311                 r.in.num_entries = 0x1000;
4312                 r.in.resume_handle = &resume_handle;
4313                 r.out.sids = &lsa_sid_array;
4314                 r.out.resume_handle = &resume_handle;
4315
4316                 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4317                 torture_assert_ntstatus_ok(tctx, status,
4318                         "Failed to enum accounts");
4319
4320                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4321                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4322                                 found_sid = true;
4323                         }
4324                 }
4325
4326                 torture_assert(tctx, found_sid,
4327                         "failed to list privileged account");
4328         }
4329
4330         {
4331                 struct lsa_EnumAccountRights r;
4332                 struct lsa_RightSet user_rights;
4333
4334                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4335
4336                 r.in.handle = lsa_handle;
4337                 r.in.sid = user_sid;
4338                 r.out.rights = &user_rights;
4339
4340                 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4341                 torture_assert_ntstatus_ok(tctx, status,
4342                         "Failed to enum rights for account");
4343
4344                 if (user_rights.count < 1) {
4345                         torture_warning(tctx, "failed to find newly added rights");
4346                         return false;
4347                 }
4348         }
4349
4350         {
4351                 struct lsa_OpenAccount r;
4352
4353                 torture_comment(tctx, "Testing LSA OpenAccount\n");
4354
4355                 r.in.handle = lsa_handle;
4356                 r.in.sid = user_sid;
4357                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4358                 r.out.acct_handle = &lsa_acct_handle;
4359
4360                 status = dcerpc_lsa_OpenAccount(lp, tctx, &r);
4361                 torture_assert_ntstatus_ok(tctx, status,
4362                         "Failed to open lsa account");
4363         }
4364
4365         {
4366                 struct lsa_GetSystemAccessAccount r;
4367                 uint32_t access_mask;
4368
4369                 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4370
4371                 r.in.handle = &lsa_acct_handle;
4372                 r.out.access_mask = &access_mask;
4373
4374                 status = dcerpc_lsa_GetSystemAccessAccount(lp, tctx, &r);
4375                 torture_assert_ntstatus_ok(tctx, status,
4376                         "Failed to get lsa system access account");
4377         }
4378
4379         {
4380                 struct lsa_DeleteObject r;
4381
4382                 torture_comment(tctx, "Testing LSA DeleteObject\n");
4383
4384                 r.in.handle = &lsa_acct_handle;
4385                 r.out.handle = &lsa_acct_handle;
4386
4387                 status = dcerpc_lsa_DeleteObject(lp, tctx, &r);
4388                 torture_assert_ntstatus_ok(tctx, status,
4389                         "Failed to delete object");
4390         }
4391
4392         {
4393                 struct lsa_EnumAccounts r;
4394                 uint32_t resume_handle = 0;
4395                 struct lsa_SidArray lsa_sid_array;
4396                 int i;
4397                 bool found_sid = false;
4398
4399                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4400
4401                 r.in.handle = lsa_handle;
4402                 r.in.num_entries = 0x1000;
4403                 r.in.resume_handle = &resume_handle;
4404                 r.out.sids = &lsa_sid_array;
4405                 r.out.resume_handle = &resume_handle;
4406
4407                 status = dcerpc_lsa_EnumAccounts(lp, tctx, &r);
4408                 torture_assert_ntstatus_ok(tctx, status,
4409                         "Failed to enum accounts");
4410
4411                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4412                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4413                                 found_sid = true;
4414                         }
4415                 }
4416
4417                 torture_assert(tctx, !found_sid,
4418                         "should not have listed privileged account");
4419         }
4420
4421         {
4422                 struct lsa_EnumAccountRights r;
4423                 struct lsa_RightSet user_rights;
4424
4425                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4426
4427                 r.in.handle = lsa_handle;
4428                 r.in.sid = user_sid;
4429                 r.out.rights = &user_rights;
4430
4431                 status = dcerpc_lsa_EnumAccountRights(lp, tctx, &r);
4432                 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4433                         "Failed to enum rights for account");
4434         }
4435
4436         return ret;
4437 }
4438
4439 static bool test_user_ops(struct dcerpc_pipe *p,
4440                           struct torture_context *tctx,
4441                           struct policy_handle *user_handle,
4442                           struct policy_handle *domain_handle,
4443                           const struct dom_sid *domain_sid,
4444                           uint32_t base_acct_flags,
4445                           const char *base_acct_name, enum torture_samr_choice which_ops,
4446                           struct cli_credentials *machine_credentials)
4447 {
4448         char *password = NULL;
4449         struct samr_QueryUserInfo q;
4450         union samr_UserInfo *info;
4451         NTSTATUS status;
4452
4453         bool ret = true;
4454         int i;
4455         uint32_t rid;
4456         const uint32_t password_fields[] = {
4457                 SAMR_FIELD_NT_PASSWORD_PRESENT,
4458                 SAMR_FIELD_LM_PASSWORD_PRESENT,
4459                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4460                 0
4461         };
4462
4463         status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
4464         if (!NT_STATUS_IS_OK(status)) {
4465                 ret = false;
4466         }
4467
4468         switch (which_ops) {
4469         case TORTURE_SAMR_USER_ATTRIBUTES:
4470                 if (!test_QuerySecurity(p, tctx, user_handle)) {
4471                         ret = false;
4472                 }
4473
4474                 if (!test_QueryUserInfo(p, tctx, user_handle)) {
4475                         ret = false;
4476                 }
4477
4478                 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
4479                         ret = false;
4480                 }
4481
4482                 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
4483                                       base_acct_name)) {
4484                         ret = false;
4485                 }
4486
4487                 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
4488                         ret = false;
4489                 }
4490
4491                 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
4492                         ret = false;
4493                 }
4494
4495                 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4496                         ret = false;
4497                 }
4498                 break;
4499         case TORTURE_SAMR_PASSWORDS:
4500                 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4501                         char simple_pass[9];
4502                         char *v = generate_random_str(tctx, 1);
4503
4504                         ZERO_STRUCT(simple_pass);
4505                         memset(simple_pass, *v, sizeof(simple_pass) - 1);
4506
4507                         torture_comment(tctx, "Testing machine account password policy rules\n");
4508
4509                         /* Workstation trust accounts don't seem to need to honour password quality policy */
4510                         if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4511                                 ret = false;
4512                         }
4513
4514                         if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4515                                 ret = false;
4516                         }
4517
4518                         /* reset again, to allow another 'user' password change */
4519                         if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4520                                 ret = false;
4521                         }
4522
4523                         /* Try a 'short' password */
4524                         if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4525                                 ret = false;
4526                         }
4527
4528                         /* Try a compleatly random password */
4529                         if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4530                                 ret = false;
4531                         }
4532                 }
4533
4534                 for (i = 0; password_fields[i]; i++) {
4535                         if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4536                                 ret = false;
4537                         }
4538
4539                         /* check it was set right */
4540                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4541                                 ret = false;
4542                         }
4543                 }
4544
4545                 for (i = 0; password_fields[i]; i++) {
4546                         if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4547                                 ret = false;
4548                         }
4549
4550                         /* check it was set right */
4551                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4552                                 ret = false;
4553                         }
4554                 }
4555
4556                 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4557                         ret = false;
4558                 }
4559
4560                 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4561                         ret = false;
4562                 }
4563
4564                 if (torture_setting_bool(tctx, "samba4", false)) {
4565                         torture_comment(tctx, "skipping Set Password level 18 and 21 against Samba4\n");
4566                 } else {
4567
4568                         if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4569                                 ret = false;
4570                         }
4571
4572                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4573                                 ret = false;
4574                         }
4575
4576                         for (i = 0; password_fields[i]; i++) {
4577
4578                                 if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4579                                         /* we need to skip as that would break
4580                                          * the ChangePasswordUser3 verify */
4581                                         continue;
4582                                 }
4583
4584                                 if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4585                                         ret = false;
4586                                 }
4587
4588                                 /* check it was set right */
4589                                 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4590                                         ret = false;
4591                                 }
4592                         }
4593                 }
4594
4595                 q.in.user_handle = user_handle;
4596                 q.in.level = 5;
4597                 q.out.info = &info;
4598
4599                 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
4600                 if (!NT_STATUS_IS_OK(status)) {
4601                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4602                                q.in.level, nt_errstr(status));
4603                         ret = false;
4604                 } else {
4605                         uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4606                         if ((info->info5.acct_flags) != expected_flags) {
4607                                 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4608                                        info->info5.acct_flags,
4609                                        expected_flags);
4610                                 /* FIXME: GD */
4611                                 if (!torture_setting_bool(tctx, "samba3", false)) {
4612                                         ret = false;
4613                                 }
4614                         }
4615                         if (info->info5.rid != rid) {
4616                                 torture_warning(tctx, "QuerUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4617                                        info->info5.rid, rid);
4618
4619                         }
4620                 }
4621
4622                 break;
4623
4624         case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4625
4626                 /* test last password change timestamp behaviour */
4627                 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4628                                                  base_acct_name,
4629                                                  user_handle, &password,
4630                                                  machine_credentials)) {
4631                         ret = false;
4632                 }
4633
4634                 if (ret == true) {
4635                         torture_comment(tctx, "pwdLastSet test succeeded\n");
4636                 } else {
4637                         torture_warning(tctx, "pwdLastSet test failed\n");
4638                 }
4639
4640                 break;
4641
4642         case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4643
4644                 /* test bad pwd count change behaviour */
4645                 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4646                                                     base_acct_name,
4647                                                     domain_handle,
4648                                                     user_handle, &password,
4649                                                     machine_credentials)) {
4650                         ret = false;
4651                 }
4652
4653                 if (ret == true) {
4654                         torture_comment(tctx, "badPwdCount test succeeded\n");
4655                 } else {
4656                         torture_warning(tctx, "badPwdCount test failed\n");
4657                 }
4658
4659                 break;
4660
4661         case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4662
4663                 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4664                                                 base_acct_name,
4665                                                 domain_handle,
4666                                                 user_handle, &password,
4667                                                 machine_credentials))
4668                 {
4669                         ret = false;
4670                 }
4671
4672                 if (ret == true) {
4673                         torture_comment(tctx, "lockout test succeeded\n");
4674                 } else {
4675                         torture_warning(tctx, "lockout test failed\n");
4676                 }
4677
4678                 break;
4679
4680
4681         case TORTURE_SAMR_USER_PRIVILEGES: {
4682
4683                 struct dcerpc_pipe *lp;
4684                 struct policy_handle *lsa_handle;
4685
4686                 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4687                 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4688
4689                 if (!test_lsa_OpenPolicy2(lp, tctx, &lsa_handle)) {
4690                         ret = false;
4691                 }
4692
4693                 if (!test_DeleteUser_with_privs(p, lp, tctx,
4694                                                 domain_handle, lsa_handle, user_handle,
4695                                                 domain_sid, rid,
4696                                                 machine_credentials)) {
4697                         ret = false;
4698                 }
4699
4700                 if (!test_lsa_Close(lp, tctx, lsa_handle)) {
4701                         ret = false;
4702                 }
4703
4704                 if (!ret) {
4705                         torture_warning(tctx, "privileged user delete test failed\n");
4706                 }
4707
4708                 break;
4709         }
4710         case TORTURE_SAMR_OTHER:
4711                 /* We just need the account to exist */
4712                 break;
4713         }
4714         return ret;
4715 }
4716
4717 static bool test_alias_ops(struct dcerpc_pipe *p, struct torture_context *tctx,
4718                            struct policy_handle *alias_handle,
4719                            const struct dom_sid *domain_sid)
4720 {
4721         bool ret = true;
4722
4723         if (!torture_setting_bool(tctx, "samba3", false)) {
4724                 if (!test_QuerySecurity(p, tctx, alias_handle)) {
4725                         ret = false;
4726                 }
4727         }
4728
4729         if (!test_QueryAliasInfo(p, tctx, alias_handle)) {
4730                 ret = false;
4731         }
4732
4733         if (!test_SetAliasInfo(p, tctx, alias_handle)) {
4734                 ret = false;
4735         }
4736
4737         if (!test_AddMemberToAlias(p, tctx, alias_handle, domain_sid)) {
4738                 ret = false;
4739         }
4740
4741         if (torture_setting_bool(tctx, "samba3", false) ||
4742             torture_setting_bool(tctx, "samba4", false)) {
4743                 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4744                 return ret;
4745         }
4746
4747         if (!test_AddMultipleMembersToAlias(p, tctx, alias_handle)) {
4748                 ret = false;
4749         }
4750
4751         return ret;
4752 }
4753
4754
4755 static bool test_DeleteUser(struct dcerpc_pipe *p, struct torture_context *tctx,
4756                                      struct policy_handle *user_handle)
4757 {
4758         struct samr_DeleteUser d;
4759         NTSTATUS status;
4760         torture_comment(tctx, "Testing DeleteUser\n");
4761
4762         d.in.user_handle = user_handle;
4763         d.out.user_handle = user_handle;
4764
4765         status = dcerpc_samr_DeleteUser(p, tctx, &d);
4766         torture_assert_ntstatus_ok(tctx, status, "DeleteUser");
4767
4768         return true;
4769 }
4770
4771 bool test_DeleteUser_byname(struct dcerpc_pipe *p,
4772                             struct torture_context *tctx,
4773                             struct policy_handle *handle, const char *name)
4774 {
4775         NTSTATUS status;
4776         struct samr_DeleteUser d;
4777         struct policy_handle user_handle;
4778         uint32_t rid;
4779
4780         status = test_LookupName(p, tctx, handle, name, &rid);
4781         if (!NT_STATUS_IS_OK(status)) {
4782                 goto failed;
4783         }
4784
4785         status = test_OpenUser_byname(p, tctx, handle, name, &user_handle);
4786         if (!NT_STATUS_IS_OK(status)) {
4787                 goto failed;
4788         }
4789
4790         d.in.user_handle = &user_handle;
4791         d.out.user_handle = &user_handle;
4792         status = dcerpc_samr_DeleteUser(p, tctx, &d);
4793         if (!NT_STATUS_IS_OK(status)) {
4794                 goto failed;
4795         }
4796
4797         return true;
4798
4799 failed:
4800         torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
4801         return false;
4802 }
4803
4804
4805 static bool test_DeleteGroup_byname(struct dcerpc_pipe *p,
4806                                     struct torture_context *tctx,
4807                                     struct policy_handle *handle, const char *name)
4808 {
4809         NTSTATUS status;
4810         struct samr_OpenGroup r;
4811         struct samr_DeleteDomainGroup d;
4812         struct policy_handle group_handle;
4813         uint32_t rid;
4814
4815         status = test_LookupName(p, tctx, handle, name, &rid);
4816         if (!NT_STATUS_IS_OK(status)) {
4817                 goto failed;
4818         }
4819
4820         r.in.domain_handle = handle;
4821         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4822         r.in.rid = rid;
4823         r.out.group_handle = &group_handle;
4824         status = dcerpc_samr_OpenGroup(p, tctx, &r);
4825         if (!NT_STATUS_IS_OK(status)) {
4826                 goto failed;
4827         }
4828
4829         d.in.group_handle = &group_handle;
4830         d.out.group_handle = &group_handle;
4831         status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
4832         if (!NT_STATUS_IS_OK(status)) {
4833                 goto failed;
4834         }
4835
4836         return true;
4837
4838 failed:
4839         torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
4840         return false;
4841 }
4842
4843
4844 static bool test_DeleteAlias_byname(struct dcerpc_pipe *p,
4845                                     struct torture_context *tctx,
4846                                     struct policy_handle *domain_handle,
4847                                     const char *name)
4848 {
4849         NTSTATUS status;
4850         struct samr_OpenAlias r;
4851         struct samr_DeleteDomAlias d;
4852         struct policy_handle alias_handle;
4853         uint32_t rid;
4854
4855         torture_comment(tctx, "testing DeleteAlias_byname\n");
4856
4857         status = test_LookupName(p, tctx, domain_handle, name, &rid);
4858         if (!NT_STATUS_IS_OK(status)) {
4859                 goto failed;
4860         }
4861
4862         r.in.domain_handle = domain_handle;
4863         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4864         r.in.rid = rid;
4865         r.out.alias_handle = &alias_handle;
4866         status = dcerpc_samr_OpenAlias(p, tctx, &r);
4867         if (!NT_STATUS_IS_OK(status)) {
4868                 goto failed;
4869         }
4870
4871         d.in.alias_handle = &alias_handle;
4872         d.out.alias_handle = &alias_handle;
4873         status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4874         if (!NT_STATUS_IS_OK(status)) {
4875                 goto failed;
4876         }
4877
4878         return true;
4879
4880 failed:
4881         torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
4882         return false;
4883 }
4884
4885 static bool test_DeleteAlias(struct dcerpc_pipe *p,
4886                              struct torture_context *tctx,
4887                              struct policy_handle *alias_handle)
4888 {
4889         struct samr_DeleteDomAlias d;
4890         NTSTATUS status;
4891         bool ret = true;
4892
4893         torture_comment(tctx, "Testing DeleteAlias\n");
4894
4895         d.in.alias_handle = alias_handle;
4896         d.out.alias_handle = alias_handle;
4897
4898         status = dcerpc_samr_DeleteDomAlias(p, tctx, &d);
4899         if (!NT_STATUS_IS_OK(status)) {
4900                 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(status));
4901                 ret = false;
4902         }
4903
4904         return ret;
4905 }
4906
4907 static bool test_CreateAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
4908                              struct policy_handle *domain_handle,
4909                              const char *alias_name,
4910                              struct policy_handle *alias_handle,
4911                              const struct dom_sid *domain_sid,
4912                              bool test_alias)
4913 {
4914         NTSTATUS status;
4915         struct samr_CreateDomAlias r;
4916         struct lsa_String name;
4917         uint32_t rid;
4918         bool ret = true;
4919
4920         init_lsa_String(&name, alias_name);
4921         r.in.domain_handle = domain_handle;
4922         r.in.alias_name = &name;
4923         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4924         r.out.alias_handle = alias_handle;
4925         r.out.rid = &rid;
4926
4927         torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
4928
4929         status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4930
4931         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
4932                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
4933                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
4934                         return true;
4935                 } else {
4936                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
4937                                nt_errstr(status));
4938                         return false;
4939                 }
4940         }
4941
4942         if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
4943                 if (!test_DeleteAlias_byname(p, tctx, domain_handle, r.in.alias_name->string)) {
4944                         return false;
4945                 }
4946                 status = dcerpc_samr_CreateDomAlias(p, tctx, &r);
4947         }
4948
4949         if (!NT_STATUS_IS_OK(status)) {
4950                 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(status));
4951                 return false;
4952         }
4953
4954         if (!test_alias) {
4955                 return ret;
4956         }
4957
4958         if (!test_alias_ops(p, tctx, alias_handle, domain_sid)) {
4959                 ret = false;
4960         }
4961
4962         return ret;
4963 }
4964
4965 static bool test_ChangePassword(struct dcerpc_pipe *p,
4966                                 struct torture_context *tctx,
4967                                 const char *acct_name,
4968                                 struct policy_handle *domain_handle, char **password)
4969 {
4970         bool ret = true;
4971
4972         if (!*password) {
4973                 return false;
4974         }
4975
4976         if (!test_ChangePasswordUser(p, tctx, acct_name, domain_handle, password)) {
4977                 ret = false;
4978         }
4979
4980         if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
4981                 ret = false;
4982         }
4983
4984         if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
4985                 ret = false;
4986         }
4987
4988         /* test what happens when setting the old password again */
4989         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
4990                 ret = false;
4991         }
4992
4993         {
4994                 char simple_pass[9];
4995                 char *v = generate_random_str(tctx, 1);
4996
4997                 ZERO_STRUCT(simple_pass);
4998                 memset(simple_pass, *v, sizeof(simple_pass) - 1);
4999
5000                 /* test what happens when picking a simple password */
5001                 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5002                         ret = false;
5003                 }
5004         }
5005
5006         /* set samr_SetDomainInfo level 1 with min_length 5 */
5007         {
5008                 struct samr_QueryDomainInfo r;
5009                 union samr_DomainInfo *info = NULL;
5010                 struct samr_SetDomainInfo s;
5011                 uint16_t len_old, len;
5012                 uint32_t pwd_prop_old;
5013                 int64_t min_pwd_age_old;
5014                 NTSTATUS status;
5015
5016                 len = 5;
5017
5018                 r.in.domain_handle = domain_handle;
5019                 r.in.level = 1;
5020                 r.out.info = &info;
5021
5022                 torture_comment(tctx, "testing samr_QueryDomainInfo level 1\n");
5023                 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
5024                 if (!NT_STATUS_IS_OK(status)) {
5025                         return false;
5026                 }
5027
5028                 s.in.domain_handle = domain_handle;
5029                 s.in.level = 1;
5030                 s.in.info = info;
5031
5032                 /* remember the old min length, so we can reset it */
5033                 len_old = s.in.info->info1.min_password_length;
5034                 s.in.info->info1.min_password_length = len;
5035                 pwd_prop_old = s.in.info->info1.password_properties;
5036                 /* turn off password complexity checks for this test */
5037                 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5038
5039                 min_pwd_age_old = s.in.info->info1.min_password_age;
5040                 s.in.info->info1.min_password_age = 0;
5041
5042                 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
5043                 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5044                 if (!NT_STATUS_IS_OK(status)) {
5045                         return false;
5046                 }
5047
5048                 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5049
5050                 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5051                         ret = false;
5052                 }
5053
5054                 s.in.info->info1.min_password_length = len_old;
5055                 s.in.info->info1.password_properties = pwd_prop_old;
5056                 s.in.info->info1.min_password_age = min_pwd_age_old;
5057
5058                 torture_comment(tctx, "testing samr_SetDomainInfo level 1\n");
5059                 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
5060                 if (!NT_STATUS_IS_OK(status)) {
5061                         return false;
5062                 }
5063
5064         }
5065
5066         {
5067                 NTSTATUS status;
5068                 struct samr_OpenUser r;
5069                 struct samr_QueryUserInfo q;
5070                 union samr_UserInfo *info;
5071                 struct samr_LookupNames n;
5072                 struct policy_handle user_handle;
5073                 struct samr_Ids rids, types;
5074
5075                 n.in.domain_handle = domain_handle;
5076                 n.in.num_names = 1;
5077                 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5078                 n.in.names[0].string = acct_name;
5079                 n.out.rids = &rids;
5080                 n.out.types = &types;
5081
5082                 status = dcerpc_samr_LookupNames(p, tctx, &n);
5083                 if (!NT_STATUS_IS_OK(status)) {
5084                         torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5085                         return false;
5086                 }
5087
5088                 r.in.domain_handle = domain_handle;
5089                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5090                 r.in.rid = n.out.rids->ids[0];
5091                 r.out.user_handle = &user_handle;
5092
5093                 status = dcerpc_samr_OpenUser(p, tctx, &r);
5094                 if (!NT_STATUS_IS_OK(status)) {
5095                         torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(status));
5096                         return false;
5097                 }
5098
5099                 q.in.user_handle = &user_handle;
5100                 q.in.level = 5;
5101                 q.out.info = &info;
5102
5103                 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5104                 if (!NT_STATUS_IS_OK(status)) {
5105                         torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(status));
5106                         return false;
5107                 }
5108
5109                 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5110
5111                 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5112                                               info->info5.last_password_change, true)) {
5113                         ret = false;
5114                 }
5115         }
5116
5117         /* we change passwords twice - this has the effect of verifying
5118            they were changed correctly for the final call */
5119         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5120                 ret = false;
5121         }
5122
5123         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5124                 ret = false;
5125         }
5126
5127         return ret;
5128 }
5129
5130 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5131                             struct policy_handle *domain_handle,
5132                             const char *user_name,
5133                             struct policy_handle *user_handle_out,
5134                             struct dom_sid *domain_sid,
5135                             enum torture_samr_choice which_ops,
5136                             struct cli_credentials *machine_credentials,
5137                             bool test_user)
5138 {
5139
5140         TALLOC_CTX *user_ctx;
5141
5142         NTSTATUS status;
5143         struct samr_CreateUser r;
5144         struct samr_QueryUserInfo q;
5145         union samr_UserInfo *info;
5146         struct samr_DeleteUser d;
5147         uint32_t rid;
5148
5149         /* This call creates a 'normal' account - check that it really does */
5150         const uint32_t acct_flags = ACB_NORMAL;
5151         struct lsa_String name;
5152         bool ret = true;
5153
5154         struct policy_handle user_handle;
5155         user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5156         init_lsa_String(&name, user_name);
5157
5158         r.in.domain_handle = domain_handle;
5159         r.in.account_name = &name;
5160         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5161         r.out.user_handle = &user_handle;
5162         r.out.rid = &rid;
5163
5164         torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5165
5166         status = dcerpc_samr_CreateUser(p, user_ctx, &r);
5167
5168         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5169                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5170                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5171                         return true;
5172                 } else {
5173                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5174                                nt_errstr(status));
5175                         return false;
5176                 }
5177         }
5178
5179         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5180                 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
5181                         talloc_free(user_ctx);
5182                         return false;
5183                 }
5184                 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
5185         }
5186
5187         if (!NT_STATUS_IS_OK(status)) {
5188                 talloc_free(user_ctx);
5189                 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(status));
5190                 return false;
5191         }
5192
5193         if (!test_user) {
5194                 if (user_handle_out) {
5195                         *user_handle_out = user_handle;
5196                 }
5197                 return ret;
5198         }
5199
5200         {
5201                 q.in.user_handle = &user_handle;
5202                 q.in.level = 16;
5203                 q.out.info = &info;
5204
5205                 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
5206                 if (!NT_STATUS_IS_OK(status)) {
5207                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5208                                q.in.level, nt_errstr(status));
5209                         ret = false;
5210                 } else {
5211                         if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5212                                 torture_warning(tctx, "QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5213                                        info->info16.acct_flags,
5214                                        acct_flags);
5215                                 ret = false;
5216                         }
5217                 }
5218
5219                 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5220                                    domain_sid, acct_flags, name.string, which_ops,
5221                                    machine_credentials)) {
5222                         ret = false;
5223                 }
5224
5225                 if (user_handle_out) {
5226                         *user_handle_out = user_handle;
5227                 } else {
5228                         torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5229
5230                         d.in.user_handle = &user_handle;
5231                         d.out.user_handle = &user_handle;
5232
5233                         status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
5234                         if (!NT_STATUS_IS_OK(status)) {
5235                                 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
5236                                 ret = false;
5237                         }
5238                 }
5239
5240         }
5241
5242         talloc_free(user_ctx);
5243
5244         return ret;
5245 }
5246
5247
5248 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5249                              struct policy_handle *domain_handle,
5250                              struct dom_sid *domain_sid,
5251                              enum torture_samr_choice which_ops,
5252                              struct cli_credentials *machine_credentials)
5253 {
5254         NTSTATUS status;
5255         struct samr_CreateUser2 r;
5256         struct samr_QueryUserInfo q;
5257         union samr_UserInfo *info;
5258         struct samr_DeleteUser d;
5259         struct policy_handle user_handle;
5260         uint32_t rid;
5261         struct lsa_String name;
5262         bool ret = true;
5263         int i;
5264
5265         struct {
5266                 uint32_t acct_flags;
5267                 const char *account_name;
5268                 NTSTATUS nt_status;
5269         } account_types[] = {
5270                 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5271                 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5272                 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5273                 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5274                 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5275                 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5276                 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5277                 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5278                 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5279                 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5280                 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5281                 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5282                 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5283                 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5284                 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5285         };
5286
5287         for (i = 0; account_types[i].account_name; i++) {
5288                 TALLOC_CTX *user_ctx;
5289                 uint32_t acct_flags = account_types[i].acct_flags;
5290                 uint32_t access_granted;
5291                 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5292                 init_lsa_String(&name, account_types[i].account_name);
5293
5294                 r.in.domain_handle = domain_handle;
5295                 r.in.account_name = &name;
5296                 r.in.acct_flags = acct_flags;
5297                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5298                 r.out.user_handle = &user_handle;
5299                 r.out.access_granted = &access_granted;
5300                 r.out.rid = &rid;
5301
5302                 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5303
5304                 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
5305
5306                 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5307                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
5308                                 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5309                                 continue;
5310                         } else {
5311                                 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5312                                        nt_errstr(status));
5313                                 ret = false;
5314                                 continue;
5315                         }
5316                 }
5317
5318                 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
5319                         if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
5320                                 talloc_free(user_ctx);
5321                                 ret = false;
5322                                 continue;
5323                         }
5324                         status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
5325
5326                 }
5327                 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
5328                         torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5329                                nt_errstr(status), nt_errstr(account_types[i].nt_status));
5330                         ret = false;
5331                 }
5332
5333                 if (NT_STATUS_IS_OK(status)) {
5334                         q.in.user_handle = &user_handle;
5335                         q.in.level = 5;
5336                         q.out.info = &info;
5337
5338                         status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
5339                         if (!NT_STATUS_IS_OK(status)) {
5340                                 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5341                                        q.in.level, nt_errstr(status));
5342                                 ret = false;
5343                         } else {
5344                                 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5345                                 if (acct_flags == ACB_NORMAL) {
5346                                         expected_flags |= ACB_PW_EXPIRED;
5347                                 }
5348                                 if ((info->info5.acct_flags) != expected_flags) {
5349                                         torture_warning(tctx, "QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5350                                                info->info5.acct_flags,
5351                                                expected_flags);
5352                                         ret = false;
5353                                 }
5354                                 switch (acct_flags) {
5355                                 case ACB_SVRTRUST:
5356                                         if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5357                                                 torture_warning(tctx, "QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5358                                                        DOMAIN_RID_DCS, info->info5.primary_gid);
5359                                                 ret = false;
5360                                         }
5361                                         break;
5362                                 case ACB_WSTRUST:
5363                                         if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5364                                                 torture_warning(tctx, "QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5365                                                        DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5366                                                 ret = false;
5367                                         }
5368                                         break;
5369                                 case ACB_NORMAL:
5370                                         if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5371                                                 torture_warning(tctx, "QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5372                                                        DOMAIN_RID_USERS, info->info5.primary_gid);
5373                                                 ret = false;
5374                                         }
5375                                         break;
5376                                 }
5377                         }
5378
5379                         if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5380                                            domain_sid, acct_flags, name.string, which_ops,
5381                                            machine_credentials)) {
5382                                 ret = false;
5383                         }
5384
5385                         if (!policy_handle_empty(&user_handle)) {
5386                                 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5387
5388                                 d.in.user_handle = &user_handle;
5389                                 d.out.user_handle = &user_handle;
5390
5391                                 status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
5392                                 if (!NT_STATUS_IS_OK(status)) {
5393                                         torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(status));
5394                                         ret = false;
5395                                 }
5396                         }
5397                 }
5398                 talloc_free(user_ctx);
5399         }
5400
5401         return ret;
5402 }
5403
5404 static bool test_QueryAliasInfo(struct dcerpc_pipe *p,
5405                                 struct torture_context *tctx,
5406                                 struct policy_handle *handle)
5407 {
5408         NTSTATUS status;
5409         struct samr_QueryAliasInfo r;
5410         union samr_AliasInfo *info;
5411         uint16_t levels[] = {1, 2, 3};
5412         int i;
5413         bool ret = true;
5414
5415         for (i=0;i<ARRAY_SIZE(levels);i++) {
5416                 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5417
5418                 r.in.alias_handle = handle;
5419                 r.in.level = levels[i];
5420                 r.out.info = &info;
5421
5422                 status = dcerpc_samr_QueryAliasInfo(p, tctx, &r);
5423                 if (!NT_STATUS_IS_OK(status)) {
5424                         torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5425                                levels[i], nt_errstr(status));
5426                         ret = false;
5427                 }
5428         }
5429
5430         return ret;
5431 }
5432
5433 static bool test_QueryGroupInfo(struct dcerpc_pipe *p,
5434                                 struct torture_context *tctx,
5435                                 struct policy_handle *handle)
5436 {
5437         NTSTATUS status;
5438         struct samr_QueryGroupInfo r;
5439         union samr_GroupInfo *info;
5440         uint16_t levels[] = {1, 2, 3, 4, 5};
5441         int i;
5442         bool ret = true;
5443
5444         for (i=0;i<ARRAY_SIZE(levels);i++) {
5445                 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5446
5447                 r.in.group_handle = handle;
5448                 r.in.level = levels[i];
5449                 r.out.info = &info;
5450
5451                 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
5452                 if (!NT_STATUS_IS_OK(status)) {
5453                         torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5454                                levels[i], nt_errstr(status));
5455                         ret = false;
5456                 }
5457         }
5458
5459         return ret;
5460 }
5461
5462 static bool test_QueryGroupMember(struct dcerpc_pipe *p,
5463                                   struct torture_context *tctx,
5464                                   struct policy_handle *handle)
5465 {
5466         NTSTATUS status;
5467         struct samr_QueryGroupMember r;
5468         struct samr_RidTypeArray *rids = NULL;
5469         bool ret = true;
5470
5471         torture_comment(tctx, "Testing QueryGroupMember\n");
5472
5473         r.in.group_handle = handle;
5474         r.out.rids = &rids;
5475
5476         status = dcerpc_samr_QueryGroupMember(p, tctx, &r);
5477         if (!NT_STATUS_IS_OK(status)) {
5478                 torture_warning(tctx, "QueryGroupInfo failed - %s\n", nt_errstr(status));
5479                 ret = false;
5480         }
5481
5482         return ret;
5483 }
5484
5485
5486 static bool test_SetGroupInfo(struct dcerpc_pipe *p,
5487                               struct torture_context *tctx,
5488                               struct policy_handle *handle)
5489 {
5490         NTSTATUS status;
5491         struct samr_QueryGroupInfo r;
5492         union samr_GroupInfo *info;
5493         struct samr_SetGroupInfo s;
5494         uint16_t levels[] = {1, 2, 3, 4};
5495         uint16_t set_ok[] = {0, 1, 1, 1};
5496         int i;
5497         bool ret = true;
5498
5499         for (i=0;i<ARRAY_SIZE(levels);i++) {
5500                 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5501
5502                 r.in.group_handle = handle;
5503                 r.in.level = levels[i];
5504                 r.out.info = &info;
5505
5506                 status = dcerpc_samr_QueryGroupInfo(p, tctx, &r);
5507                 if (!NT_STATUS_IS_OK(status)) {
5508                         torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5509                                levels[i], nt_errstr(status));
5510                         ret = false;
5511                 }
5512
5513                 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5514
5515                 s.in.group_handle = handle;
5516                 s.in.level = levels[i];
5517                 s.in.info = *r.out.info;
5518
5519 #if 0
5520                 /* disabled this, as it changes the name only from the point of view of samr,
5521                    but leaves the name from the point of view of w2k3 internals (and ldap). This means
5522                    the name is still reserved, so creating the old name fails, but deleting by the old name
5523                    also fails */
5524                 if (s.in.level == 2) {
5525                         init_lsa_String(&s.in.info->string, "NewName");
5526                 }
5527 #endif
5528
5529                 if (s.in.level == 4) {
5530                         init_lsa_String(&s.in.info->description, "test description");
5531                 }
5532
5533                 status = dcerpc_samr_SetGroupInfo(p, tctx, &s);
5534                 if (set_ok[i]) {
5535                         if (!NT_STATUS_IS_OK(status)) {
5536                                 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5537                                        r.in.level, nt_errstr(status));
5538                                 ret = false;
5539                                 continue;
5540                         }
5541                 } else {
5542                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
5543                                 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5544                                        r.in.level, nt_errstr(status));
5545                                 ret = false;
5546                                 continue;
5547                         }
5548                 }
5549         }
5550
5551         return ret;
5552 }
5553
5554 static bool test_QueryUserInfo(struct dcerpc_pipe *p,
5555                                struct torture_context *tctx,
5556                                struct policy_handle *handle)
5557 {
5558         NTSTATUS status;
5559         struct samr_QueryUserInfo r;
5560         union samr_UserInfo *info;
5561         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5562                            11, 12, 13, 14, 16, 17, 20, 21};
5563         int i;
5564         bool ret = true;
5565
5566         for (i=0;i<ARRAY_SIZE(levels);i++) {
5567                 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5568
5569                 r.in.user_handle = handle;
5570                 r.in.level = levels[i];
5571                 r.out.info = &info;
5572
5573                 status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
5574                 if (!NT_STATUS_IS_OK(status)) {
5575                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5576                                levels[i], nt_errstr(status));
5577                         ret = false;
5578                 }
5579         }
5580
5581         return ret;
5582 }
5583
5584 static bool test_QueryUserInfo2(struct dcerpc_pipe *p,
5585                                 struct torture_context *tctx,
5586                                 struct policy_handle *handle)
5587 {
5588         NTSTATUS status;
5589         struct samr_QueryUserInfo2 r;
5590         union samr_UserInfo *info;
5591         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5592                            11, 12, 13, 14, 16, 17, 20, 21};
5593         int i;
5594         bool ret = true;
5595
5596         for (i=0;i<ARRAY_SIZE(levels);i++) {
5597                 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5598
5599                 r.in.user_handle = handle;
5600                 r.in.level = levels[i];
5601                 r.out.info = &info;
5602
5603                 status = dcerpc_samr_QueryUserInfo2(p, tctx, &r);
5604                 if (!NT_STATUS_IS_OK(status)) {
5605                         torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5606                                levels[i], nt_errstr(status));
5607                         ret = false;
5608                 }
5609         }
5610
5611         return ret;
5612 }
5613
5614 static bool test_OpenUser(struct dcerpc_pipe *p,
5615                           struct torture_context *tctx,
5616                           struct policy_handle *handle, uint32_t rid)
5617 {
5618         NTSTATUS status;
5619         struct samr_OpenUser r;
5620         struct policy_handle user_handle;
5621         bool ret = true;
5622
5623         torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5624
5625         r.in.domain_handle = handle;
5626         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5627         r.in.rid = rid;
5628         r.out.user_handle = &user_handle;
5629
5630         status = dcerpc_samr_OpenUser(p, tctx, &r);
5631         if (!NT_STATUS_IS_OK(status)) {
5632                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
5633                 return false;
5634         }
5635
5636         if (!test_QuerySecurity(p, tctx, &user_handle)) {
5637                 ret = false;
5638         }
5639
5640         if (!test_QueryUserInfo(p, tctx, &user_handle)) {
5641                 ret = false;
5642         }
5643
5644         if (!test_QueryUserInfo2(p, tctx, &user_handle)) {
5645                 ret = false;
5646         }
5647
5648         if (!test_GetUserPwInfo(p, tctx, &user_handle)) {
5649                 ret = false;
5650         }
5651
5652         if (!test_GetGroupsForUser(p,tctx, &user_handle)) {
5653                 ret = false;
5654         }
5655
5656         if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5657                 ret = false;
5658         }
5659
5660         return ret;
5661 }
5662
5663 static bool test_OpenGroup(struct dcerpc_pipe *p,
5664                            struct torture_context *tctx,
5665                            struct policy_handle *handle, uint32_t rid)
5666 {
5667         NTSTATUS status;
5668         struct samr_OpenGroup r;
5669         struct policy_handle group_handle;
5670         bool ret = true;
5671
5672         torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5673
5674         r.in.domain_handle = handle;
5675         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5676         r.in.rid = rid;
5677         r.out.group_handle = &group_handle;
5678
5679         status = dcerpc_samr_OpenGroup(p, tctx, &r);
5680         if (!NT_STATUS_IS_OK(status)) {
5681                 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
5682                 return false;
5683         }
5684
5685         if (!torture_setting_bool(tctx, "samba3", false)) {
5686                 if (!test_QuerySecurity(p, tctx, &group_handle)) {
5687                         ret = false;
5688                 }
5689         }
5690
5691         if (!test_QueryGroupInfo(p, tctx, &group_handle)) {
5692                 ret = false;
5693         }
5694
5695         if (!test_QueryGroupMember(p, tctx, &group_handle)) {
5696                 ret = false;
5697         }
5698
5699         if (!test_samr_handle_Close(p, tctx, &group_handle)) {
5700                 ret = false;
5701         }
5702
5703         return ret;
5704 }
5705
5706 static bool test_OpenAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
5707                            struct policy_handle *handle, uint32_t rid)
5708 {
5709         NTSTATUS status;
5710         struct samr_OpenAlias r;
5711         struct policy_handle alias_handle;
5712         bool ret = true;
5713
5714         torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5715
5716         r.in.domain_handle = handle;
5717         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5718         r.in.rid = rid;
5719         r.out.alias_handle = &alias_handle;
5720
5721         status = dcerpc_samr_OpenAlias(p, tctx, &r);
5722         if (!NT_STATUS_IS_OK(status)) {
5723                 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
5724                 return false;
5725         }
5726
5727         if (!torture_setting_bool(tctx, "samba3", false)) {
5728                 if (!test_QuerySecurity(p, tctx, &alias_handle)) {
5729                         ret = false;
5730                 }
5731         }
5732
5733         if (!test_QueryAliasInfo(p, tctx, &alias_handle)) {
5734                 ret = false;
5735         }
5736
5737         if (!test_GetMembersInAlias(p, tctx, &alias_handle)) {
5738                 ret = false;
5739         }
5740
5741         if (!test_samr_handle_Close(p, tctx, &alias_handle)) {
5742                 ret = false;
5743         }
5744
5745         return ret;
5746 }
5747
5748 static bool check_mask(struct dcerpc_pipe *p, struct torture_context *tctx,
5749                        struct policy_handle *handle, uint32_t rid,
5750                        uint32_t acct_flag_mask)
5751 {
5752         NTSTATUS status;
5753         struct samr_OpenUser r;
5754         struct samr_QueryUserInfo q;
5755         union samr_UserInfo *info;
5756         struct policy_handle user_handle;
5757         bool ret = true;
5758
5759         torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5760
5761         r.in.domain_handle = handle;
5762         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5763         r.in.rid = rid;
5764         r.out.user_handle = &user_handle;
5765
5766         status = dcerpc_samr_OpenUser(p, tctx, &r);
5767         if (!NT_STATUS_IS_OK(status)) {
5768                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
5769                 return false;
5770         }
5771
5772         q.in.user_handle = &user_handle;
5773         q.in.level = 16;
5774         q.out.info = &info;
5775
5776         status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
5777         if (!NT_STATUS_IS_OK(status)) {
5778                 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
5779                        nt_errstr(status));
5780                 ret = false;
5781         } else {
5782                 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
5783                         torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
5784                                acct_flag_mask, info->info16.acct_flags, rid);
5785                         ret = false;
5786                 }
5787         }
5788
5789         if (!test_samr_handle_Close(p, tctx, &user_handle)) {
5790                 ret = false;
5791         }
5792
5793         return ret;
5794 }
5795
5796 static bool test_EnumDomainUsers_all(struct dcerpc_pipe *p,
5797                                      struct torture_context *tctx,
5798                                      struct policy_handle *handle)
5799 {
5800         NTSTATUS status = STATUS_MORE_ENTRIES;
5801         struct samr_EnumDomainUsers r;
5802         uint32_t mask, resume_handle=0;
5803         int i, mask_idx;
5804         bool ret = true;
5805         struct samr_LookupNames n;
5806         struct samr_LookupRids  lr ;
5807         struct lsa_Strings names;
5808         struct samr_Ids rids, types;
5809         struct samr_SamArray *sam = NULL;
5810         uint32_t num_entries = 0;
5811
5812         uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
5813                             ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
5814                             ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
5815                             ACB_PWNOEXP, 0};
5816
5817         torture_comment(tctx, "Testing EnumDomainUsers\n");
5818
5819         for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
5820                 r.in.domain_handle = handle;
5821                 r.in.resume_handle = &resume_handle;
5822                 r.in.acct_flags = mask = masks[mask_idx];
5823                 r.in.max_size = (uint32_t)-1;
5824                 r.out.resume_handle = &resume_handle;
5825                 r.out.num_entries = &num_entries;
5826                 r.out.sam = &sam;
5827
5828                 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
5829                 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
5830                     !NT_STATUS_IS_OK(status)) {
5831                         torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(status));
5832                         return false;
5833                 }
5834
5835                 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
5836
5837                 if (sam->count == 0) {
5838                         continue;
5839                 }
5840
5841                 for (i=0;i<sam->count;i++) {
5842                         if (mask) {
5843                                 if (!check_mask(p, tctx, handle, sam->entries[i].idx, mask)) {
5844                                         ret = false;
5845                                 }
5846                         } else if (!test_OpenUser(p, tctx, handle, sam->entries[i].idx)) {
5847                                 ret = false;
5848                         }
5849                 }
5850         }
5851
5852         torture_comment(tctx, "Testing LookupNames\n");
5853         n.in.domain_handle = handle;
5854         n.in.num_names = sam->count;
5855         n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
5856         n.out.rids = &rids;
5857         n.out.types = &types;
5858         for (i=0;i<sam->count;i++) {
5859                 n.in.names[i].string = sam->entries[i].name.string;
5860         }
5861         status = dcerpc_samr_LookupNames(p, tctx, &n);
5862         if (!NT_STATUS_IS_OK(status)) {
5863                 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(status));
5864                 ret = false;
5865         }
5866
5867
5868         torture_comment(tctx, "Testing LookupRids\n");
5869         lr.in.domain_handle = handle;
5870         lr.in.num_rids = sam->count;
5871         lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
5872         lr.out.names = &names;
5873         lr.out.types = &types;
5874         for (i=0;i<sam->count;i++) {
5875                 lr.in.rids[i] = sam->entries[i].idx;
5876         }
5877         status = dcerpc_samr_LookupRids(p, tctx, &lr);
5878         torture_assert_ntstatus_ok(tctx, status, "LookupRids");
5879
5880         return ret;
5881 }
5882
5883 /*
5884   try blasting the server with a bunch of sync requests
5885 */
5886 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
5887                                        struct policy_handle *handle)
5888 {
5889         NTSTATUS status;
5890         struct samr_EnumDomainUsers r;
5891         uint32_t resume_handle=0;
5892         int i;
5893 #define ASYNC_COUNT 100
5894         struct rpc_request *req[ASYNC_COUNT];
5895
5896         if (!torture_setting_bool(tctx, "dangerous", false)) {
5897                 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
5898         }
5899
5900         torture_comment(tctx, "Testing EnumDomainUsers_async\n");
5901
5902         r.in.domain_handle = handle;
5903         r.in.resume_handle = &resume_handle;
5904         r.in.acct_flags = 0;
5905         r.in.max_size = (uint32_t)-1;
5906         r.out.resume_handle = &resume_handle;
5907
5908         for (i=0;i<ASYNC_COUNT;i++) {
5909                 req[i] = dcerpc_samr_EnumDomainUsers_send(p, tctx, &r);
5910         }
5911
5912         for (i=0;i<ASYNC_COUNT;i++) {
5913                 status = dcerpc_ndr_request_recv(req[i]);
5914                 if (!NT_STATUS_IS_OK(status)) {
5915                         torture_warning(tctx, "EnumDomainUsers[%d] failed - %s\n",
5916                                i, nt_errstr(status));
5917                         return false;
5918                 }
5919         }
5920
5921         torture_comment(tctx, "%d async requests OK\n", i);
5922
5923         return true;
5924 }
5925
5926 static bool test_EnumDomainGroups_all(struct dcerpc_pipe *p,
5927                                       struct torture_context *tctx,
5928                                       struct policy_handle *handle)
5929 {
5930         NTSTATUS status;
5931         struct samr_EnumDomainGroups r;
5932         uint32_t resume_handle=0;
5933         struct samr_SamArray *sam = NULL;
5934         uint32_t num_entries = 0;
5935         int i;
5936         bool ret = true;
5937
5938         torture_comment(tctx, "Testing EnumDomainGroups\n");
5939
5940         r.in.domain_handle = handle;
5941         r.in.resume_handle = &resume_handle;
5942         r.in.max_size = (uint32_t)-1;
5943         r.out.resume_handle = &resume_handle;
5944         r.out.num_entries = &num_entries;
5945         r.out.sam = &sam;
5946
5947         status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
5948         if (!NT_STATUS_IS_OK(status)) {
5949                 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(status));
5950                 return false;
5951         }
5952
5953         if (!sam) {
5954                 return false;
5955         }
5956
5957         for (i=0;i<sam->count;i++) {
5958                 if (!test_OpenGroup(p, tctx, handle, sam->entries[i].idx)) {
5959                         ret = false;
5960                 }
5961         }
5962
5963         return ret;
5964 }
5965
5966 static bool test_EnumDomainAliases_all(struct dcerpc_pipe *p,
5967                                        struct torture_context *tctx,
5968                                        struct policy_handle *handle)
5969 {
5970         NTSTATUS status;
5971         struct samr_EnumDomainAliases r;
5972         uint32_t resume_handle=0;
5973         struct samr_SamArray *sam = NULL;
5974         uint32_t num_entries = 0;
5975         int i;
5976         bool ret = true;
5977
5978         torture_comment(tctx, "Testing EnumDomainAliases\n");
5979
5980         r.in.domain_handle = handle;
5981         r.in.resume_handle = &resume_handle;
5982         r.in.max_size = (uint32_t)-1;
5983         r.out.sam = &sam;
5984         r.out.num_entries = &num_entries;
5985         r.out.resume_handle = &resume_handle;
5986
5987         status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
5988         if (!NT_STATUS_IS_OK(status)) {
5989                 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(status));
5990                 return false;
5991         }
5992
5993         if (!sam) {
5994                 return false;
5995         }
5996
5997         for (i=0;i<sam->count;i++) {
5998                 if (!test_OpenAlias(p, tctx, handle, sam->entries[i].idx)) {
5999                         ret = false;
6000                 }
6001         }
6002
6003         return ret;
6004 }
6005
6006 static bool test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p,
6007                                             struct torture_context *tctx,
6008                                             struct policy_handle *handle)
6009 {
6010         NTSTATUS status;
6011         struct samr_GetDisplayEnumerationIndex r;
6012         bool ret = true;
6013         uint16_t levels[] = {1, 2, 3, 4, 5};
6014         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6015         struct lsa_String name;
6016         uint32_t idx = 0;
6017         int i;
6018
6019         for (i=0;i<ARRAY_SIZE(levels);i++) {
6020                 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6021
6022                 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6023
6024                 r.in.domain_handle = handle;
6025                 r.in.level = levels[i];
6026                 r.in.name = &name;
6027                 r.out.idx = &idx;
6028
6029                 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
6030
6031                 if (ok_lvl[i] &&
6032                     !NT_STATUS_IS_OK(status) &&
6033                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6034                         torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6035                                levels[i], nt_errstr(status));
6036                         ret = false;
6037                 }
6038
6039                 init_lsa_String(&name, "zzzzzzzz");
6040
6041                 status = dcerpc_samr_GetDisplayEnumerationIndex(p, tctx, &r);
6042
6043                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6044                         torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6045                                levels[i], nt_errstr(status));
6046                         ret = false;
6047                 }
6048         }
6049
6050         return ret;
6051 }
6052
6053 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p,
6054                                              struct torture_context *tctx,
6055                                              struct policy_handle *handle)
6056 {
6057         NTSTATUS status;
6058         struct samr_GetDisplayEnumerationIndex2 r;
6059         bool ret = true;
6060         uint16_t levels[] = {1, 2, 3, 4, 5};
6061         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6062         struct lsa_String name;
6063         uint32_t idx = 0;
6064         int i;
6065
6066         for (i=0;i<ARRAY_SIZE(levels);i++) {
6067                 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6068
6069                 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6070
6071                 r.in.domain_handle = handle;
6072                 r.in.level = levels[i];
6073                 r.in.name = &name;
6074                 r.out.idx = &idx;
6075
6076                 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
6077                 if (ok_lvl[i] &&
6078                     !NT_STATUS_IS_OK(status) &&
6079                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6080                         torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6081                                levels[i], nt_errstr(status));
6082                         ret = false;
6083                 }
6084
6085                 init_lsa_String(&name, "zzzzzzzz");
6086
6087                 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, tctx, &r);
6088                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
6089                         torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6090                                levels[i], nt_errstr(status));
6091                         ret = false;
6092                 }
6093         }
6094
6095         return ret;
6096 }
6097
6098 #define STRING_EQUAL_QUERY(s1, s2, user)                                        \
6099         if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6100                 /* odd, but valid */                                            \
6101         } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6102                         torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6103                                #s1, user.string,  s1.string, s2.string, __location__);   \
6104                         ret = false; \
6105         }
6106 #define INT_EQUAL_QUERY(s1, s2, user)           \
6107                 if (s1 != s2) { \
6108                         torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6109                                #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6110                         ret = false; \
6111                 }
6112
6113 static bool test_each_DisplayInfo_user(struct dcerpc_pipe *p,
6114                                        struct torture_context *tctx,
6115                                        struct samr_QueryDisplayInfo *querydisplayinfo,
6116                                        bool *seen_testuser)
6117 {
6118         struct samr_OpenUser r;
6119         struct samr_QueryUserInfo q;
6120         union samr_UserInfo *info;
6121         struct policy_handle user_handle;
6122         int i, ret = true;
6123         NTSTATUS status;
6124         r.in.domain_handle = querydisplayinfo->in.domain_handle;
6125         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6126         for (i = 0; ; i++) {
6127                 switch (querydisplayinfo->in.level) {
6128                 case 1:
6129                         if (i >= querydisplayinfo->out.info->info1.count) {
6130                                 return ret;
6131                         }
6132                         r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6133                         break;
6134                 case 2:
6135                         if (i >= querydisplayinfo->out.info->info2.count) {
6136                                 return ret;
6137                         }
6138                         r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6139                         break;
6140                 case 3:
6141                         /* Groups */
6142                 case 4:
6143                 case 5:
6144                         /* Not interested in validating just the account name */
6145                         return true;
6146                 }
6147
6148                 r.out.user_handle = &user_handle;
6149
6150                 switch (querydisplayinfo->in.level) {
6151                 case 1:
6152                 case 2:
6153                         status = dcerpc_samr_OpenUser(p, tctx, &r);
6154                         if (!NT_STATUS_IS_OK(status)) {
6155                                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
6156                                 return false;
6157                         }
6158                 }
6159
6160                 q.in.user_handle = &user_handle;
6161                 q.in.level = 21;
6162                 q.out.info = &info;
6163                 status = dcerpc_samr_QueryUserInfo(p, tctx, &q);
6164                 if (!NT_STATUS_IS_OK(status)) {
6165                         torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
6166                         return false;
6167                 }
6168
6169                 switch (querydisplayinfo->in.level) {
6170                 case 1:
6171                         if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6172                                 *seen_testuser = true;
6173                         }
6174                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6175                                            info->info21.full_name, info->info21.account_name);
6176                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6177                                            info->info21.account_name, info->info21.account_name);
6178                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6179                                            info->info21.description, info->info21.account_name);
6180                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6181                                         info->info21.rid, info->info21.account_name);
6182                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6183                                         info->info21.acct_flags, info->info21.account_name);
6184
6185                         break;
6186                 case 2:
6187                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6188                                            info->info21.account_name, info->info21.account_name);
6189                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6190                                            info->info21.description, info->info21.account_name);
6191                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6192                                         info->info21.rid, info->info21.account_name);
6193                         INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6194                                         info->info21.acct_flags, info->info21.account_name);
6195
6196                         if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6197                                 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6198                                        info->info21.account_name.string);
6199                         }
6200
6201                         if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6202                                 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6203                                        info->info21.account_name.string,
6204                                        querydisplayinfo->out.info->info2.entries[i].acct_flags,
6205                                        info->info21.acct_flags);
6206                                 return false;
6207                         }
6208
6209                         break;
6210                 }
6211
6212                 if (!test_samr_handle_Close(p, tctx, &user_handle)) {
6213                         return false;
6214                 }
6215         }
6216         return ret;
6217 }
6218
6219 static bool test_QueryDisplayInfo(struct dcerpc_pipe *p,
6220                                   struct torture_context *tctx,
6221                                   struct policy_handle *handle)
6222 {
6223         NTSTATUS status;
6224         struct samr_QueryDisplayInfo r;
6225         struct samr_QueryDomainInfo dom_info;
6226         union samr_DomainInfo *info = NULL;
6227         bool ret = true;
6228         uint16_t levels[] = {1, 2, 3, 4, 5};
6229         int i;
6230         bool seen_testuser = false;
6231         uint32_t total_size;
6232         uint32_t returned_size;
6233         union samr_DispInfo disp_info;
6234
6235
6236         for (i=0;i<ARRAY_SIZE(levels);i++) {
6237                 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6238
6239                 r.in.start_idx = 0;
6240                 status = STATUS_MORE_ENTRIES;
6241                 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6242                         r.in.domain_handle = handle;
6243                         r.in.level = levels[i];
6244                         r.in.max_entries = 2;
6245                         r.in.buf_size = (uint32_t)-1;
6246                         r.out.total_size = &total_size;
6247                         r.out.returned_size = &returned_size;
6248                         r.out.info = &disp_info;
6249
6250                         status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6251                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
6252                                 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6253                                        levels[i], nt_errstr(status));
6254                                 ret = false;
6255                         }
6256                         switch (r.in.level) {
6257                         case 1:
6258                                 if (!test_each_DisplayInfo_user(p, tctx, &r, &seen_testuser)) {
6259                                         ret = false;
6260                                 }
6261                                 r.in.start_idx += r.out.info->info1.count;
6262                                 break;
6263                         case 2:
6264                                 if (!test_each_DisplayInfo_user(p, tctx, &r, NULL)) {
6265                                         ret = false;
6266                                 }
6267                                 r.in.start_idx += r.out.info->info2.count;
6268                                 break;
6269                         case 3:
6270                                 r.in.start_idx += r.out.info->info3.count;
6271                                 break;
6272                         case 4:
6273                                 r.in.start_idx += r.out.info->info4.count;
6274                                 break;
6275                         case 5:
6276                                 r.in.start_idx += r.out.info->info5.count;
6277                                 break;
6278                         }
6279                 }
6280                 dom_info.in.domain_handle = handle;
6281                 dom_info.in.level = 2;
6282                 dom_info.out.info = &info;
6283
6284                 /* Check number of users returned is correct */
6285                 status = dcerpc_samr_QueryDomainInfo(p, tctx, &dom_info);
6286                 if (!NT_STATUS_IS_OK(status)) {
6287                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6288                                r.in.level, nt_errstr(status));
6289                                 ret = false;
6290                                 break;
6291                 }
6292                 switch (r.in.level) {
6293                 case 1:
6294                 case 4:
6295                         if (info->general.num_users < r.in.start_idx) {
6296                                 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6297                                        r.in.start_idx, info->general.num_groups,
6298                                        info->general.domain_name.string);
6299                                 ret = false;
6300                         }
6301                         if (!seen_testuser) {
6302                                 struct policy_handle user_handle;
6303                                 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6304                                         torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6305                                                info->general.domain_name.string);
6306                                         ret = false;
6307                                         test_samr_handle_Close(p, tctx, &user_handle);
6308                                 }
6309                         }
6310                         break;
6311                 case 3:
6312                 case 5:
6313                         if (info->general.num_groups != r.in.start_idx) {
6314                                 torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6315                                        r.in.start_idx, info->general.num_groups,
6316                                        info->general.domain_name.string);
6317                                 ret = false;
6318                         }
6319
6320                         break;
6321                 }
6322
6323         }
6324
6325         return ret;
6326 }
6327
6328 static bool test_QueryDisplayInfo2(struct dcerpc_pipe *p,
6329                                    struct torture_context *tctx,
6330                                    struct policy_handle *handle)
6331 {
6332         NTSTATUS status;
6333         struct samr_QueryDisplayInfo2 r;
6334         bool ret = true;
6335         uint16_t levels[] = {1, 2, 3, 4, 5};
6336         int i;
6337         uint32_t total_size;
6338         uint32_t returned_size;
6339         union samr_DispInfo info;
6340
6341         for (i=0;i<ARRAY_SIZE(levels);i++) {
6342                 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6343
6344                 r.in.domain_handle = handle;
6345                 r.in.level = levels[i];
6346                 r.in.start_idx = 0;
6347                 r.in.max_entries = 1000;
6348                 r.in.buf_size = (uint32_t)-1;
6349                 r.out.total_size = &total_size;
6350                 r.out.returned_size = &returned_size;
6351                 r.out.info = &info;
6352
6353                 status = dcerpc_samr_QueryDisplayInfo2(p, tctx, &r);
6354                 if (!NT_STATUS_IS_OK(status)) {
6355                         torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6356                                levels[i], nt_errstr(status));
6357                         ret = false;
6358                 }
6359         }
6360
6361         return ret;
6362 }
6363
6364 static bool test_QueryDisplayInfo3(struct dcerpc_pipe *p, struct torture_context *tctx,
6365                                   struct policy_handle *handle)
6366 {
6367         NTSTATUS status;
6368         struct samr_QueryDisplayInfo3 r;
6369         bool ret = true;
6370         uint16_t levels[] = {1, 2, 3, 4, 5};
6371         int i;
6372         uint32_t total_size;
6373         uint32_t returned_size;
6374         union samr_DispInfo info;
6375
6376         for (i=0;i<ARRAY_SIZE(levels);i++) {
6377                 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6378
6379                 r.in.domain_handle = handle;
6380                 r.in.level = levels[i];
6381                 r.in.start_idx = 0;
6382                 r.in.max_entries = 1000;
6383                 r.in.buf_size = (uint32_t)-1;
6384                 r.out.total_size = &total_size;
6385                 r.out.returned_size = &returned_size;
6386                 r.out.info = &info;
6387
6388                 status = dcerpc_samr_QueryDisplayInfo3(p, tctx, &r);
6389                 if (!NT_STATUS_IS_OK(status)) {
6390                         torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6391                                levels[i], nt_errstr(status));
6392                         ret = false;
6393                 }
6394         }
6395
6396         return ret;
6397 }
6398
6399
6400 static bool test_QueryDisplayInfo_continue(struct dcerpc_pipe *p,
6401                                            struct torture_context *tctx,
6402                                            struct policy_handle *handle)
6403 {
6404         NTSTATUS status;
6405         struct samr_QueryDisplayInfo r;
6406         bool ret = true;
6407         uint32_t total_size;
6408         uint32_t returned_size;
6409         union samr_DispInfo info;
6410
6411         torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6412
6413         r.in.domain_handle = handle;
6414         r.in.level = 1;
6415         r.in.start_idx = 0;
6416         r.in.max_entries = 1;
6417         r.in.buf_size = (uint32_t)-1;
6418         r.out.total_size = &total_size;
6419         r.out.returned_size = &returned_size;
6420         r.out.info = &info;
6421
6422         do {
6423                 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
6424                 if (NT_STATUS_IS_OK(status) && *r.out.returned_size != 0) {
6425                         if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6426                                 torture_warning(tctx, "expected idx %d but got %d\n",
6427                                        r.in.start_idx + 1,
6428                                        r.out.info->info1.entries[0].idx);
6429                                 break;
6430                         }
6431                 }
6432                 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
6433                     !NT_STATUS_IS_OK(status)) {
6434                         torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6435                                r.in.level, nt_errstr(status));
6436                         ret = false;
6437                         break;
6438                 }
6439                 r.in.start_idx++;
6440         } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
6441                   NT_STATUS_IS_OK(status)) &&
6442                  *r.out.returned_size != 0);
6443
6444         return ret;
6445 }
6446
6447 static bool test_QueryDomainInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
6448                                  struct policy_handle *handle)
6449 {
6450         NTSTATUS status;
6451         struct samr_QueryDomainInfo r;
6452         union samr_DomainInfo *info = NULL;
6453         struct samr_SetDomainInfo s;
6454         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6455         uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1,  0,  1,  0};
6456         int i;
6457         bool ret = true;
6458         const char *domain_comment = talloc_asprintf(tctx,
6459                                   "Tortured by Samba4 RPC-SAMR: %s",
6460                                   timestring(tctx, time(NULL)));
6461
6462         s.in.domain_handle = handle;
6463         s.in.level = 4;
6464         s.in.info = talloc(tctx, union samr_DomainInfo);
6465
6466         s.in.info->oem.oem_information.string = domain_comment;
6467         status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
6468         if (!NT_STATUS_IS_OK(status)) {
6469                 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6470                        s.in.level, nt_errstr(status));
6471                 return false;
6472         }
6473
6474         for (i=0;i<ARRAY_SIZE(levels);i++) {
6475                 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6476
6477                 r.in.domain_handle = handle;
6478                 r.in.level = levels[i];
6479                 r.out.info = &info;
6480
6481                 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
6482                 if (!NT_STATUS_IS_OK(status)) {
6483                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6484                                r.in.level, nt_errstr(status));
6485                         ret = false;
6486                         continue;
6487                 }
6488
6489                 switch (levels[i]) {
6490                 case 2:
6491                         if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6492                                 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6493                                        levels[i], info->general.oem_information.string, domain_comment);
6494                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6495                                         ret = false;
6496                                 }
6497                         }
6498                         if (!info->general.primary.string) {
6499                                 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6500                                        levels[i]);
6501                                 ret = false;
6502                         } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6503                                 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6504                                         torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6505                                                levels[i], info->general.primary.string, dcerpc_server_name(p));
6506                                 }
6507                         }
6508                         break;
6509                 case 4:
6510                         if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6511                                 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6512                                        levels[i], info->oem.oem_information.string, domain_comment);
6513                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6514                                         ret = false;
6515                                 }
6516                         }
6517                         break;
6518                 case 6:
6519                         if (!info->info6.primary.string) {
6520                                 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6521                                        levels[i]);
6522                                 ret = false;
6523                         }
6524                         break;
6525                 case 11:
6526                         if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6527                                 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6528                                        levels[i], info->general2.general.oem_information.string, domain_comment);
6529                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6530                                         ret = false;
6531                                 }
6532                         }
6533                         break;
6534                 }
6535
6536                 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6537
6538                 s.in.domain_handle = handle;
6539                 s.in.level = levels[i];
6540                 s.in.info = info;
6541
6542                 status = dcerpc_samr_SetDomainInfo(p, tctx, &s);
6543                 if (set_ok[i]) {
6544                         if (!NT_STATUS_IS_OK(status)) {
6545                                 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6546                                        r.in.level, nt_errstr(status));
6547                                 ret = false;
6548                                 continue;
6549                         }
6550                 } else {
6551                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
6552                                 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6553                                        r.in.level, nt_errstr(status));
6554                                 ret = false;
6555                                 continue;
6556                         }
6557                 }
6558
6559                 status = dcerpc_samr_QueryDomainInfo(p, tctx, &r);
6560                 if (!NT_STATUS_IS_OK(status)) {
6561                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6562                                r.in.level, nt_errstr(status));
6563                         ret = false;
6564                         continue;
6565                 }
6566         }
6567
6568         return ret;
6569 }
6570
6571
6572 static bool test_QueryDomainInfo2(struct dcerpc_pipe *p, struct torture_context *tctx,
6573                                   struct policy_handle *handle)
6574 {
6575         NTSTATUS status;
6576         struct samr_QueryDomainInfo2 r;
6577         union samr_DomainInfo *info = NULL;
6578         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6579         int i;
6580         bool ret = true;
6581
6582         for (i=0;i<ARRAY_SIZE(levels);i++) {
6583                 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6584
6585                 r.in.domain_handle = handle;
6586                 r.in.level = levels[i];
6587                 r.out.info = &info;
6588
6589                 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
6590                 if (!NT_STATUS_IS_OK(status)) {
6591                         torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6592                                r.in.level, nt_errstr(status));
6593                         ret = false;
6594                         continue;
6595                 }
6596         }
6597
6598         return true;
6599 }
6600
6601 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6602    set of group names. */
6603 static bool test_GroupList(struct dcerpc_pipe *p, struct torture_context *tctx,
6604                            struct policy_handle *handle)
6605 {
6606         struct samr_EnumDomainGroups q1;
6607         struct samr_QueryDisplayInfo q2;
6608         NTSTATUS status;
6609         uint32_t resume_handle=0;
6610         struct samr_SamArray *sam = NULL;
6611         uint32_t num_entries = 0;
6612         int i;
6613         bool ret = true;
6614         uint32_t total_size;
6615         uint32_t returned_size;
6616         union samr_DispInfo info;
6617
6618         int num_names = 0;
6619         const char **names = NULL;
6620
6621         torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6622
6623         q1.in.domain_handle = handle;
6624         q1.in.resume_handle = &resume_handle;
6625         q1.in.max_size = 5;
6626         q1.out.resume_handle = &resume_handle;
6627         q1.out.num_entries = &num_entries;
6628         q1.out.sam = &sam;
6629
6630         status = STATUS_MORE_ENTRIES;
6631         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6632                 status = dcerpc_samr_EnumDomainGroups(p, tctx, &q1);
6633
6634                 if (!NT_STATUS_IS_OK(status) &&
6635                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6636                         break;
6637
6638                 for (i=0; i<*q1.out.num_entries; i++) {
6639                         add_string_to_array(tctx,
6640                                             sam->entries[i].name.string,
6641                                             &names, &num_names);
6642                 }
6643         }
6644
6645         torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6646
6647         torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6648
6649         q2.in.domain_handle = handle;
6650         q2.in.level = 5;
6651         q2.in.start_idx = 0;
6652         q2.in.max_entries = 5;
6653         q2.in.buf_size = (uint32_t)-1;
6654         q2.out.total_size = &total_size;
6655         q2.out.returned_size = &returned_size;
6656         q2.out.info = &info;
6657
6658         status = STATUS_MORE_ENTRIES;
6659         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6660                 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &q2);
6661
6662                 if (!NT_STATUS_IS_OK(status) &&
6663                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6664                         break;
6665
6666                 for (i=0; i<q2.out.info->info5.count; i++) {
6667                         int j;
6668                         const char *name = q2.out.info->info5.entries[i].account_name.string;
6669                         bool found = false;
6670                         for (j=0; j<num_names; j++) {
6671                                 if (names[j] == NULL)
6672                                         continue;
6673                                 if (strequal(names[j], name)) {
6674                                         names[j] = NULL;
6675                                         found = true;
6676                                         break;
6677                                 }
6678                         }
6679
6680                         if (!found) {
6681                                 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
6682                                        name);
6683                                 ret = false;
6684                         }
6685                 }
6686                 q2.in.start_idx += q2.out.info->info5.count;
6687         }
6688
6689         if (!NT_STATUS_IS_OK(status)) {
6690                 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
6691                        nt_errstr(status));
6692                 ret = false;
6693         }
6694
6695         for (i=0; i<num_names; i++) {
6696                 if (names[i] != NULL) {
6697                         torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
6698                                names[i]);
6699                         ret = false;
6700                 }
6701         }
6702
6703         return ret;
6704 }
6705
6706 static bool test_DeleteDomainGroup(struct dcerpc_pipe *p, struct torture_context *tctx,
6707                                    struct policy_handle *group_handle)
6708 {
6709         struct samr_DeleteDomainGroup d;
6710         NTSTATUS status;
6711
6712         torture_comment(tctx, "Testing DeleteDomainGroup\n");
6713
6714         d.in.group_handle = group_handle;
6715         d.out.group_handle = group_handle;
6716
6717         status = dcerpc_samr_DeleteDomainGroup(p, tctx, &d);
6718         torture_assert_ntstatus_ok(tctx, status, "DeleteDomainGroup");
6719
6720         return true;
6721 }
6722
6723 static bool test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
6724                                             struct policy_handle *domain_handle)
6725 {
6726         struct samr_TestPrivateFunctionsDomain r;
6727         NTSTATUS status;
6728         bool ret = true;
6729
6730         torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
6731
6732         r.in.domain_handle = domain_handle;
6733
6734         status = dcerpc_samr_TestPrivateFunctionsDomain(p, tctx, &r);
6735         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
6736
6737         return ret;
6738 }
6739
6740 static bool test_RidToSid(struct dcerpc_pipe *p, struct torture_context *tctx,
6741                           struct dom_sid *domain_sid,
6742                           struct policy_handle *domain_handle)
6743 {
6744         struct samr_RidToSid r;
6745         NTSTATUS status;
6746         bool ret = true;
6747         struct dom_sid *calc_sid, *out_sid;
6748         int rids[] = { 0, 42, 512, 10200 };
6749         int i;
6750
6751         for (i=0;i<ARRAY_SIZE(rids);i++) {
6752                 torture_comment(tctx, "Testing RidToSid\n");
6753
6754                 calc_sid = dom_sid_dup(tctx, domain_sid);
6755                 r.in.domain_handle = domain_handle;
6756                 r.in.rid = rids[i];
6757                 r.out.sid = &out_sid;
6758
6759                 status = dcerpc_samr_RidToSid(p, tctx, &r);
6760                 if (!NT_STATUS_IS_OK(status)) {
6761                         torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
6762                         ret = false;
6763                 } else {
6764                         calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
6765
6766                         if (!dom_sid_equal(calc_sid, out_sid)) {
6767                                 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
6768                                        dom_sid_string(tctx, out_sid),
6769                                        dom_sid_string(tctx, calc_sid));
6770                                 ret = false;
6771                         }
6772                 }
6773         }
6774
6775         return ret;
6776 }
6777
6778 static bool test_GetBootKeyInformation(struct dcerpc_pipe *p, struct torture_context *tctx,
6779                                        struct policy_handle *domain_handle)
6780 {
6781         struct samr_GetBootKeyInformation r;
6782         NTSTATUS status;
6783         bool ret = true;
6784         uint32_t unknown = 0;
6785
6786         torture_comment(tctx, "Testing GetBootKeyInformation\n");
6787
6788         r.in.domain_handle = domain_handle;
6789         r.out.unknown = &unknown;
6790
6791         status = dcerpc_samr_GetBootKeyInformation(p, tctx, &r);
6792         if (!NT_STATUS_IS_OK(status)) {
6793                 /* w2k3 seems to fail this sometimes and pass it sometimes */
6794                 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
6795         }
6796
6797         return ret;
6798 }
6799
6800 static bool test_AddGroupMember(struct dcerpc_pipe *p, struct torture_context *tctx,
6801                                 struct policy_handle *domain_handle,
6802                                 struct policy_handle *group_handle)
6803 {
6804         NTSTATUS status;
6805         struct samr_AddGroupMember r;
6806         struct samr_DeleteGroupMember d;
6807         struct samr_QueryGroupMember q;
6808         struct samr_RidTypeArray *rids = NULL;
6809         struct samr_SetMemberAttributesOfGroup s;
6810         uint32_t rid;
6811         bool found_member = false;
6812         int i;
6813
6814         status = test_LookupName(p, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
6815         torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
6816
6817         r.in.group_handle = group_handle;
6818         r.in.rid = rid;
6819         r.in.flags = 0; /* ??? */
6820
6821         torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
6822
6823         d.in.group_handle = group_handle;
6824         d.in.rid = rid;
6825
6826         status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
6827         torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, status, "DeleteGroupMember");
6828
6829         status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6830         torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6831
6832         status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6833         torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, status, "AddGroupMember");
6834
6835         if (torture_setting_bool(tctx, "samba4", false) ||
6836             torture_setting_bool(tctx, "samba3", false)) {
6837                 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
6838         } else {
6839                 /* this one is quite strange. I am using random inputs in the
6840                    hope of triggering an error that might give us a clue */
6841
6842                 s.in.group_handle = group_handle;
6843                 s.in.unknown1 = random();
6844                 s.in.unknown2 = random();
6845
6846                 status = dcerpc_samr_SetMemberAttributesOfGroup(p, tctx, &s);
6847                 torture_assert_ntstatus_ok(tctx, status, "SetMemberAttributesOfGroup");
6848         }
6849
6850         q.in.group_handle = group_handle;
6851         q.out.rids = &rids;
6852
6853         status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
6854         torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6855         torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6856
6857         for (i=0; i < rids->count; i++) {
6858                 if (rids->rids[i] == rid) {
6859                         found_member = true;
6860                 }
6861         }
6862
6863         torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
6864
6865         status = dcerpc_samr_DeleteGroupMember(p, tctx, &d);
6866         torture_assert_ntstatus_ok(tctx, status, "DeleteGroupMember");
6867
6868         rids = NULL;
6869         found_member = false;
6870
6871         status = dcerpc_samr_QueryGroupMember(p, tctx, &q);
6872         torture_assert_ntstatus_ok(tctx, status, "QueryGroupMember");
6873         torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
6874
6875         for (i=0; i < rids->count; i++) {
6876                 if (rids->rids[i] == rid) {
6877                         found_member = true;
6878                 }
6879         }
6880
6881         torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
6882
6883         status = dcerpc_samr_AddGroupMember(p, tctx, &r);
6884         torture_assert_ntstatus_ok(tctx, status, "AddGroupMember");
6885
6886         return true;
6887 }
6888
6889
6890 static bool test_CreateDomainGroup(struct dcerpc_pipe *p,
6891                                    struct torture_context *tctx,
6892                                    struct policy_handle *domain_handle,
6893                                    const char *group_name,
6894                                    struct policy_handle *group_handle,
6895                                    struct dom_sid *domain_sid,
6896                                    bool test_group)
6897 {
6898         NTSTATUS status;
6899         struct samr_CreateDomainGroup r;
6900         uint32_t rid;
6901         struct lsa_String name;
6902         bool ret = true;
6903
6904         init_lsa_String(&name, group_name);
6905
6906         r.in.domain_handle = domain_handle;
6907         r.in.name = &name;
6908         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6909         r.out.group_handle = group_handle;
6910         r.out.rid = &rid;
6911
6912         torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
6913
6914         status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6915
6916         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
6917                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
6918                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
6919                         return true;
6920                 } else {
6921                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
6922                                nt_errstr(status));
6923                         return false;
6924                 }
6925         }
6926
6927         if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
6928                 if (!test_DeleteGroup_byname(p, tctx, domain_handle, r.in.name->string)) {
6929                         torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
6930                                nt_errstr(status));
6931                         return false;
6932                 }
6933                 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6934         }
6935         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
6936                 if (!test_DeleteUser_byname(p, tctx, domain_handle, r.in.name->string)) {
6937
6938                         torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
6939                                nt_errstr(status));
6940                         return false;
6941                 }
6942                 status = dcerpc_samr_CreateDomainGroup(p, tctx, &r);
6943         }
6944         torture_assert_ntstatus_ok(tctx, status, "CreateDomainGroup");
6945
6946         if (!test_group) {
6947                 return ret;
6948         }
6949
6950         if (!test_AddGroupMember(p, tctx, domain_handle, group_handle)) {
6951                 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(status));
6952                 ret = false;
6953         }
6954
6955         if (!test_SetGroupInfo(p, tctx, group_handle)) {
6956                 ret = false;
6957         }
6958
6959         return ret;
6960 }
6961
6962
6963 /*
6964   its not totally clear what this does. It seems to accept any sid you like.
6965 */
6966 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p,
6967                                                struct torture_context *tctx,
6968                                                struct policy_handle *domain_handle)
6969 {
6970         NTSTATUS status;
6971         struct samr_RemoveMemberFromForeignDomain r;
6972
6973         r.in.domain_handle = domain_handle;
6974         r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
6975
6976         status = dcerpc_samr_RemoveMemberFromForeignDomain(p, tctx, &r);
6977         torture_assert_ntstatus_ok(tctx, status, "RemoveMemberFromForeignDomain");
6978
6979         return true;
6980 }
6981
6982 static bool test_EnumDomainUsers(struct dcerpc_pipe *p,
6983                                  struct torture_context *tctx,
6984                                  struct policy_handle *domain_handle,
6985                                  uint32_t *total_num_entries_p)
6986 {
6987         NTSTATUS status;
6988         struct samr_EnumDomainUsers r;
6989         uint32_t resume_handle = 0;
6990         uint32_t num_entries = 0;
6991         uint32_t total_num_entries = 0;
6992         struct samr_SamArray *sam;
6993
6994         r.in.domain_handle = domain_handle;
6995         r.in.acct_flags = 0;
6996         r.in.max_size = (uint32_t)-1;
6997         r.in.resume_handle = &resume_handle;
6998
6999         r.out.sam = &sam;
7000         r.out.num_entries = &num_entries;
7001         r.out.resume_handle = &resume_handle;
7002
7003         torture_comment(tctx, "Testing EnumDomainUsers\n");
7004
7005         do {
7006                 status = dcerpc_samr_EnumDomainUsers(p, tctx, &r);
7007                 if (NT_STATUS_IS_ERR(status)) {
7008                         torture_assert_ntstatus_ok(tctx, status,
7009                                 "failed to enumerate users");
7010                 }
7011
7012                 total_num_entries += num_entries;
7013         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7014
7015         if (total_num_entries_p) {
7016                 *total_num_entries_p = total_num_entries;
7017         }
7018
7019         return true;
7020 }
7021
7022 static bool test_EnumDomainGroups(struct dcerpc_pipe *p,
7023                                   struct torture_context *tctx,
7024                                   struct policy_handle *domain_handle,
7025                                   uint32_t *total_num_entries_p)
7026 {
7027         NTSTATUS status;
7028         struct samr_EnumDomainGroups r;
7029         uint32_t resume_handle = 0;
7030         uint32_t num_entries = 0;
7031         uint32_t total_num_entries = 0;
7032         struct samr_SamArray *sam;
7033
7034         r.in.domain_handle = domain_handle;
7035         r.in.max_size = (uint32_t)-1;
7036         r.in.resume_handle = &resume_handle;
7037
7038         r.out.sam = &sam;
7039         r.out.num_entries = &num_entries;
7040         r.out.resume_handle = &resume_handle;
7041
7042         torture_comment(tctx, "Testing EnumDomainGroups\n");
7043
7044         do {
7045                 status = dcerpc_samr_EnumDomainGroups(p, tctx, &r);
7046                 if (NT_STATUS_IS_ERR(status)) {
7047                         torture_assert_ntstatus_ok(tctx, status,
7048                                 "failed to enumerate groups");
7049                 }
7050
7051                 total_num_entries += num_entries;
7052         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7053
7054         if (total_num_entries_p) {
7055                 *total_num_entries_p = total_num_entries;
7056         }
7057
7058         return true;
7059 }
7060
7061 static bool test_EnumDomainAliases(struct dcerpc_pipe *p,
7062                                    struct torture_context *tctx,
7063                                    struct policy_handle *domain_handle,
7064                                    uint32_t *total_num_entries_p)
7065 {
7066         NTSTATUS status;
7067         struct samr_EnumDomainAliases r;
7068         uint32_t resume_handle = 0;
7069         uint32_t num_entries = 0;
7070         uint32_t total_num_entries = 0;
7071         struct samr_SamArray *sam;
7072
7073         r.in.domain_handle = domain_handle;
7074         r.in.max_size = (uint32_t)-1;
7075         r.in.resume_handle = &resume_handle;
7076
7077         r.out.sam = &sam;
7078         r.out.num_entries = &num_entries;
7079         r.out.resume_handle = &resume_handle;
7080
7081         torture_comment(tctx, "Testing EnumDomainAliases\n");
7082
7083         do {
7084                 status = dcerpc_samr_EnumDomainAliases(p, tctx, &r);
7085                 if (NT_STATUS_IS_ERR(status)) {
7086                         torture_assert_ntstatus_ok(tctx, status,
7087                                 "failed to enumerate aliases");
7088                 }
7089
7090                 total_num_entries += num_entries;
7091         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7092
7093         if (total_num_entries_p) {
7094                 *total_num_entries_p = total_num_entries;
7095         }
7096
7097         return true;
7098 }
7099
7100 static bool test_QueryDisplayInfo_level(struct dcerpc_pipe *p,
7101                                         struct torture_context *tctx,
7102                                         struct policy_handle *handle,
7103                                         uint16_t level,
7104                                         uint32_t *total_num_entries_p)
7105 {
7106         NTSTATUS status;
7107         struct samr_QueryDisplayInfo r;
7108         uint32_t total_num_entries = 0;
7109
7110         r.in.domain_handle = handle;
7111         r.in.level = level;
7112         r.in.start_idx = 0;
7113         r.in.max_entries = (uint32_t)-1;
7114         r.in.buf_size = (uint32_t)-1;
7115
7116         torture_comment(tctx, "Testing QueryDisplayInfo\n");
7117
7118         do {
7119                 uint32_t total_size;
7120                 uint32_t returned_size;
7121                 union samr_DispInfo info;
7122
7123                 r.out.total_size = &total_size;
7124                 r.out.returned_size = &returned_size;
7125                 r.out.info = &info;
7126
7127                 status = dcerpc_samr_QueryDisplayInfo(p, tctx, &r);
7128                 if (NT_STATUS_IS_ERR(status)) {
7129                         torture_assert_ntstatus_ok(tctx, status,
7130                                 "failed to query displayinfo");
7131                 }
7132
7133                 if (*r.out.returned_size == 0) {
7134                         break;
7135                 }
7136
7137                 switch (r.in.level) {
7138                 case 1:
7139                         total_num_entries += info.info1.count;
7140                         r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7141                         break;
7142                 case 2:
7143                         total_num_entries += info.info2.count;
7144                         r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7145                         break;
7146                 case 3:
7147                         total_num_entries += info.info3.count;
7148                         r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7149                         break;
7150                 case 4:
7151                         total_num_entries += info.info4.count;
7152                         r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7153                         break;
7154                 case 5:
7155                         total_num_entries += info.info5.count;
7156                         r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7157                         break;
7158                 default:
7159                         return false;
7160                 }
7161
7162         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7163
7164         if (total_num_entries_p) {
7165                 *total_num_entries_p = total_num_entries;
7166         }
7167
7168         return true;
7169 }
7170
7171 static bool test_ManyObjects(struct dcerpc_pipe *p,
7172                              struct torture_context *tctx,
7173                              struct policy_handle *domain_handle,
7174                              struct dom_sid *domain_sid,
7175                              struct torture_samr_context *ctx)
7176 {
7177         uint32_t num_total = ctx->num_objects_large_dc;
7178         uint32_t num_enum = 0;
7179         uint32_t num_disp = 0;
7180         uint32_t num_created = 0;
7181         uint32_t num_anounced = 0;
7182         bool ret = true;
7183         NTSTATUS status;
7184         uint32_t i;
7185
7186         struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7187
7188         /* query */
7189
7190         {
7191                 struct samr_QueryDomainInfo2 r;
7192                 union samr_DomainInfo *info;
7193                 r.in.domain_handle = domain_handle;
7194                 r.in.level = 2;
7195                 r.out.info = &info;
7196
7197                 status = dcerpc_samr_QueryDomainInfo2(p, tctx, &r);
7198                 torture_assert_ntstatus_ok(tctx, status,
7199                         "failed to query domain info");
7200
7201                 switch (ctx->choice) {
7202                 case TORTURE_SAMR_MANY_ACCOUNTS:
7203                         num_anounced = info->general.num_users;
7204                         break;
7205                 case TORTURE_SAMR_MANY_GROUPS:
7206                         num_anounced = info->general.num_groups;
7207                         break;
7208                 case TORTURE_SAMR_MANY_ALIASES:
7209                         num_anounced = info->general.num_aliases;
7210                         break;
7211                 default:
7212                         return false;
7213                 }
7214         }
7215
7216         /* create */
7217
7218         for (i=0; i < num_total; i++) {
7219
7220                 const char *name = NULL;
7221
7222                 switch (ctx->choice) {
7223                 case TORTURE_SAMR_MANY_ACCOUNTS:
7224                         name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7225                         ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
7226                         break;
7227                 case TORTURE_SAMR_MANY_GROUPS:
7228                         name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7229                         ret &= test_CreateDomainGroup(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
7230                         break;
7231                 case TORTURE_SAMR_MANY_ALIASES:
7232                         name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7233                         ret &= test_CreateAlias(p, tctx, domain_handle, name, &handles[i], domain_sid, false);
7234                         break;
7235                 default:
7236                         return false;
7237                 }
7238                 if (!policy_handle_empty(&handles[i])) {
7239                         num_created++;
7240                 }
7241         }
7242
7243         /* enum */
7244
7245         switch (ctx->choice) {
7246         case TORTURE_SAMR_MANY_ACCOUNTS:
7247                 ret &= test_EnumDomainUsers(p, tctx, domain_handle, &num_enum);
7248                 break;
7249         case TORTURE_SAMR_MANY_GROUPS:
7250                 ret &= test_EnumDomainGroups(p, tctx, domain_handle, &num_enum);
7251                 break;
7252         case TORTURE_SAMR_MANY_ALIASES:
7253                 ret &= test_EnumDomainAliases(p, tctx, domain_handle, &num_enum);
7254                 break;
7255         default:
7256                 return false;
7257         }
7258
7259         /* dispinfo */
7260
7261         switch (ctx->choice) {
7262         case TORTURE_SAMR_MANY_ACCOUNTS:
7263                 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 1, &num_disp);
7264                 break;
7265         case TORTURE_SAMR_MANY_GROUPS:
7266                 ret &= test_QueryDisplayInfo_level(p, tctx, domain_handle, 3, &num_disp);
7267                 break;
7268         case TORTURE_SAMR_MANY_ALIASES:
7269                 /* no aliases in dispinfo */
7270                 break;
7271         default:
7272                 return false;
7273         }
7274
7275         /* close or delete */
7276
7277         for (i=0; i < num_total; i++) {
7278
7279                 if (policy_handle_empty(&handles[i])) {
7280                         continue;
7281                 }
7282
7283                 if (torture_setting_bool(tctx, "samba3", false)) {
7284                         ret &= test_samr_handle_Close(p, tctx, &handles[i]);
7285                 } else {
7286                         switch (ctx->choice) {
7287                         case TORTURE_SAMR_MANY_ACCOUNTS:
7288                                 ret &= test_DeleteUser(p, tctx, &handles[i]);
7289                                 break;
7290                         case TORTURE_SAMR_MANY_GROUPS:
7291                                 ret &= test_DeleteDomainGroup(p, tctx, &handles[i]);
7292                                 break;
7293                         case TORTURE_SAMR_MANY_ALIASES:
7294                                 ret &= test_DeleteAlias(p, tctx, &handles[i]);
7295                                 break;
7296                         default:
7297                                 return false;
7298                         }
7299                 }
7300         }
7301
7302         talloc_free(handles);
7303
7304         if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7305                 torture_comment(tctx,
7306                                 "unexpected number of results (%u) returned in enum call, expected %u\n",
7307                                 num_enum, num_anounced + num_created);
7308
7309                 torture_comment(tctx,
7310                                 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7311                                 num_disp, num_anounced + num_created);
7312         }
7313         return ret;
7314 }
7315
7316 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
7317                          struct policy_handle *handle);
7318
7319 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7320                             struct torture_samr_context *ctx, struct dom_sid *sid)
7321 {
7322         NTSTATUS status;
7323         struct samr_OpenDomain r;
7324         struct policy_handle domain_handle;
7325         struct policy_handle alias_handle;
7326         struct policy_handle user_handle;
7327         struct policy_handle group_handle;
7328         bool ret = true;
7329
7330         ZERO_STRUCT(alias_handle);
7331         ZERO_STRUCT(user_handle);
7332         ZERO_STRUCT(group_handle);
7333         ZERO_STRUCT(domain_handle);
7334
7335         torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7336
7337         r.in.connect_handle = &ctx->handle;
7338         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7339         r.in.sid = sid;
7340         r.out.domain_handle = &domain_handle;
7341
7342         status = dcerpc_samr_OpenDomain(p, tctx, &r);
7343         torture_assert_ntstatus_ok(tctx, status, "OpenDomain");
7344
7345         /* run the domain tests with the main handle closed - this tests
7346            the servers reference counting */
7347         torture_assert(tctx, test_samr_handle_Close(p, tctx, &ctx->handle), "Failed to close SAMR handle");
7348
7349         switch (ctx->choice) {
7350         case TORTURE_SAMR_PASSWORDS:
7351         case TORTURE_SAMR_USER_PRIVILEGES:
7352                 if (!torture_setting_bool(tctx, "samba3", false)) {
7353                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7354                 }
7355                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7356                 if (!ret) {
7357                         torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7358                 }
7359                 break;
7360         case TORTURE_SAMR_USER_ATTRIBUTES:
7361                 if (!torture_setting_bool(tctx, "samba3", false)) {
7362                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7363                 }
7364                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7365                 /* This test needs 'complex' users to validate */
7366                 ret &= test_QueryDisplayInfo(p, tctx, &domain_handle);
7367                 if (!ret) {
7368                         torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7369                 }
7370                 break;
7371         case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7372         case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7373         case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7374                 if (!torture_setting_bool(tctx, "samba3", false)) {
7375                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7376                 }
7377                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7378                 if (!ret) {
7379                         torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7380                 }
7381                 break;
7382         case TORTURE_SAMR_MANY_ACCOUNTS:
7383         case TORTURE_SAMR_MANY_GROUPS:
7384         case TORTURE_SAMR_MANY_ALIASES:
7385                 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7386                 if (!ret) {
7387                         torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7388                 }
7389                 break;
7390         case TORTURE_SAMR_OTHER:
7391                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7392                 if (!ret) {
7393                         torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7394                 }
7395                 if (!torture_setting_bool(tctx, "samba3", false)) {
7396                         ret &= test_QuerySecurity(p, tctx, &domain_handle);
7397                 }
7398                 ret &= test_RemoveMemberFromForeignDomain(p, tctx, &domain_handle);
7399                 ret &= test_CreateAlias(p, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7400                 ret &= test_CreateDomainGroup(p, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7401                 ret &= test_GetAliasMembership(p, tctx, &domain_handle);
7402                 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7403                 ret &= test_QueryDomainInfo2(p, tctx, &domain_handle);
7404                 ret &= test_EnumDomainUsers_all(p, tctx, &domain_handle);
7405                 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7406                 ret &= test_EnumDomainGroups_all(p, tctx, &domain_handle);
7407                 ret &= test_EnumDomainAliases_all(p, tctx, &domain_handle);
7408                 ret &= test_QueryDisplayInfo2(p, tctx, &domain_handle);
7409                 ret &= test_QueryDisplayInfo3(p, tctx, &domain_handle);
7410                 ret &= test_QueryDisplayInfo_continue(p, tctx, &domain_handle);
7411
7412                 if (torture_setting_bool(tctx, "samba4", false)) {
7413                         torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7414                 } else {
7415                         ret &= test_GetDisplayEnumerationIndex(p, tctx, &domain_handle);
7416                         ret &= test_GetDisplayEnumerationIndex2(p, tctx, &domain_handle);
7417                 }
7418                 ret &= test_GroupList(p, tctx, &domain_handle);
7419                 ret &= test_TestPrivateFunctionsDomain(p, tctx, &domain_handle);
7420                 ret &= test_RidToSid(p, tctx, sid, &domain_handle);
7421                 ret &= test_GetBootKeyInformation(p, tctx, &domain_handle);
7422                 if (!ret) {
7423                         torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7424                 }
7425                 break;
7426         }
7427
7428         if (!policy_handle_empty(&user_handle) &&
7429             !test_DeleteUser(p, tctx, &user_handle)) {
7430                 ret = false;
7431         }
7432
7433         if (!policy_handle_empty(&alias_handle) &&
7434             !test_DeleteAlias(p, tctx, &alias_handle)) {
7435                 ret = false;
7436         }
7437
7438         if (!policy_handle_empty(&group_handle) &&
7439             !test_DeleteDomainGroup(p, tctx, &group_handle)) {
7440                 ret = false;
7441         }
7442
7443         torture_assert(tctx, test_samr_handle_Close(p, tctx, &domain_handle), "Failed to close SAMR domain handle");
7444
7445         torture_assert(tctx, test_Connect(p, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7446         /* reconnect the main handle */
7447
7448         if (!ret) {
7449                 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7450         }
7451
7452         return ret;
7453 }
7454
7455 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7456                               struct torture_samr_context *ctx, const char *domain)
7457 {
7458         NTSTATUS status;
7459         struct samr_LookupDomain r;
7460         struct dom_sid2 *sid = NULL;
7461         struct lsa_String n1;
7462         struct lsa_String n2;
7463         bool ret = true;
7464
7465         torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7466
7467         /* check for correct error codes */
7468         r.in.connect_handle = &ctx->handle;
7469         r.in.domain_name = &n2;
7470         r.out.sid = &sid;
7471         n2.string = NULL;
7472
7473         status = dcerpc_samr_LookupDomain(p, tctx, &r);
7474         torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, status, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7475
7476         init_lsa_String(&n2, "xxNODOMAINxx");
7477
7478         status = dcerpc_samr_LookupDomain(p, tctx, &r);
7479         torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, status, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7480
7481         r.in.connect_handle = &ctx->handle;
7482
7483         init_lsa_String(&n1, domain);
7484         r.in.domain_name = &n1;
7485
7486         status = dcerpc_samr_LookupDomain(p, tctx, &r);
7487         torture_assert_ntstatus_ok(tctx, status, "LookupDomain");
7488
7489         if (!test_GetDomPwInfo(p, tctx, &n1)) {
7490                 ret = false;
7491         }
7492
7493         if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7494                 ret = false;
7495         }
7496
7497         return ret;
7498 }
7499
7500
7501 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7502                              struct torture_samr_context *ctx)
7503 {
7504         NTSTATUS status;
7505         struct samr_EnumDomains r;
7506         uint32_t resume_handle = 0;
7507         uint32_t num_entries = 0;
7508         struct samr_SamArray *sam = NULL;
7509         int i;
7510         bool ret = true;
7511
7512         r.in.connect_handle = &ctx->handle;
7513         r.in.resume_handle = &resume_handle;
7514         r.in.buf_size = (uint32_t)-1;
7515         r.out.resume_handle = &resume_handle;
7516         r.out.num_entries = &num_entries;
7517         r.out.sam = &sam;
7518
7519         status = dcerpc_samr_EnumDomains(p, tctx, &r);
7520         torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
7521
7522         if (!*r.out.sam) {
7523                 return false;
7524         }
7525
7526         for (i=0;i<sam->count;i++) {
7527                 if (!test_LookupDomain(p, tctx, ctx,
7528                                        sam->entries[i].name.string)) {
7529                         ret = false;
7530                 }
7531         }
7532
7533         status = dcerpc_samr_EnumDomains(p, tctx, &r);
7534         torture_assert_ntstatus_ok(tctx, status, "EnumDomains");
7535
7536         return ret;
7537 }
7538
7539
7540 static bool test_Connect(struct dcerpc_pipe *p, struct torture_context *tctx,
7541                          struct policy_handle *handle)
7542 {
7543         NTSTATUS status;
7544         struct samr_Connect r;
7545         struct samr_Connect2 r2;
7546         struct samr_Connect3 r3;
7547         struct samr_Connect4 r4;
7548         struct samr_Connect5 r5;
7549         union samr_ConnectInfo info;
7550         struct policy_handle h;
7551         uint32_t level_out = 0;
7552         bool ret = true, got_handle = false;
7553
7554         torture_comment(tctx, "testing samr_Connect\n");
7555
7556         r.in.system_name = 0;
7557         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7558         r.out.connect_handle = &h;
7559
7560         status = dcerpc_samr_Connect(p, tctx, &r);
7561         if (!NT_STATUS_IS_OK(status)) {
7562                 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(status));
7563                 ret = false;
7564         } else {
7565                 got_handle = true;
7566                 *handle = h;
7567         }
7568
7569         torture_comment(tctx, "testing samr_Connect2\n");
7570
7571         r2.in.system_name = NULL;
7572         r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7573         r2.out.connect_handle = &h;
7574
7575         status = dcerpc_samr_Connect2(p, tctx, &r2);
7576         if (!NT_STATUS_IS_OK(status)) {
7577                 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(status));
7578                 ret = false;
7579         } else {
7580                 if (got_handle) {
7581                         test_samr_handle_Close(p, tctx, handle);
7582                 }
7583                 got_handle = true;
7584                 *handle = h;
7585         }
7586
7587         torture_comment(tctx, "testing samr_Connect3\n");
7588
7589         r3.in.system_name = NULL;
7590         r3.in.unknown = 0;
7591         r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7592         r3.out.connect_handle = &h;
7593
7594         status = dcerpc_samr_Connect3(p, tctx, &r3);
7595         if (!NT_STATUS_IS_OK(status)) {
7596                 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(status));
7597                 ret = false;
7598         } else {
7599                 if (got_handle) {
7600                         test_samr_handle_Close(p, tctx, handle);
7601                 }
7602                 got_handle = true;
7603                 *handle = h;
7604         }
7605
7606         torture_comment(tctx, "testing samr_Connect4\n");
7607
7608         r4.in.system_name = "";
7609         r4.in.client_version = 0;
7610         r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7611         r4.out.connect_handle = &h;
7612
7613         status = dcerpc_samr_Connect4(p, tctx, &r4);
7614         if (!NT_STATUS_IS_OK(status)) {
7615                 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(status));
7616                 ret = false;
7617         } else {
7618                 if (got_handle) {
7619                         test_samr_handle_Close(p, tctx, handle);
7620                 }
7621                 got_handle = true;
7622                 *handle = h;
7623         }
7624
7625         torture_comment(tctx, "testing samr_Connect5\n");
7626
7627         info.info1.client_version = 0;
7628         info.info1.unknown2 = 0;
7629
7630         r5.in.system_name = "";
7631         r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7632         r5.in.level_in = 1;
7633         r5.out.level_out = &level_out;
7634         r5.in.info_in = &info;
7635         r5.out.info_out = &info;
7636         r5.out.connect_handle = &h;
7637
7638         status = dcerpc_samr_Connect5(p, tctx, &r5);
7639         if (!NT_STATUS_IS_OK(status)) {
7640                 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(status));
7641                 ret = false;
7642         } else {
7643                 if (got_handle) {
7644                         test_samr_handle_Close(p, tctx, handle);
7645                 }
7646                 got_handle = true;
7647                 *handle = h;
7648         }
7649
7650         return ret;
7651 }
7652
7653
7654 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p, struct torture_context *tctx)
7655 {
7656         struct samr_ValidatePassword r;
7657         union samr_ValidatePasswordReq req;
7658         union samr_ValidatePasswordRep *repp = NULL;
7659         NTSTATUS status;
7660         const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
7661         int i;
7662
7663         torture_comment(tctx, "testing samr_ValidatePassword\n");
7664
7665         ZERO_STRUCT(r);
7666         r.in.level = NetValidatePasswordReset;
7667         r.in.req = &req;
7668         r.out.rep = &repp;
7669
7670         ZERO_STRUCT(req);
7671         req.req3.account.string = "non-existant-account-aklsdji";
7672
7673         for (i=0; passwords[i]; i++) {
7674                 req.req3.password.string = passwords[i];
7675                 status = dcerpc_samr_ValidatePassword(p, tctx, &r);
7676                 torture_assert_ntstatus_ok(tctx, status, "samr_ValidatePassword");
7677                 torture_comment(tctx, "Server %s password '%s' with code %i\n",
7678                                 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
7679                                 req.req3.password.string, repp->ctr3.status);
7680         }
7681
7682         return true;
7683 }
7684
7685 bool torture_rpc_samr(struct torture_context *torture)
7686 {
7687         NTSTATUS status;
7688         struct dcerpc_pipe *p;
7689         bool ret = true;
7690         struct torture_samr_context *ctx;
7691
7692         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7693         if (!NT_STATUS_IS_OK(status)) {
7694                 return false;
7695         }
7696
7697         ctx = talloc_zero(torture, struct torture_samr_context);
7698
7699         ctx->choice = TORTURE_SAMR_OTHER;
7700
7701         ret &= test_Connect(p, torture, &ctx->handle);
7702
7703         if (!torture_setting_bool(torture, "samba3", false)) {
7704                 ret &= test_QuerySecurity(p, torture, &ctx->handle);
7705         }
7706
7707         ret &= test_EnumDomains(p, torture, ctx);
7708
7709         ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
7710
7711         ret &= test_Shutdown(p, torture, &ctx->handle);
7712
7713         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7714
7715         return ret;
7716 }
7717
7718
7719 bool torture_rpc_samr_users(struct torture_context *torture)
7720 {
7721         NTSTATUS status;
7722         struct dcerpc_pipe *p;
7723         bool ret = true;
7724         struct torture_samr_context *ctx;
7725
7726         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7727         if (!NT_STATUS_IS_OK(status)) {
7728                 return false;
7729         }
7730
7731         ctx = talloc_zero(torture, struct torture_samr_context);
7732
7733         ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
7734
7735         ret &= test_Connect(p, torture, &ctx->handle);
7736
7737         if (!torture_setting_bool(torture, "samba3", false)) {
7738                 ret &= test_QuerySecurity(p, torture, &ctx->handle);
7739         }
7740
7741         ret &= test_EnumDomains(p, torture, ctx);
7742
7743         ret &= test_SetDsrmPassword(p, torture, &ctx->handle);
7744
7745         ret &= test_Shutdown(p, torture, &ctx->handle);
7746
7747         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7748
7749         return ret;
7750 }
7751
7752
7753 bool torture_rpc_samr_passwords(struct torture_context *torture)
7754 {
7755         NTSTATUS status;
7756         struct dcerpc_pipe *p;
7757         bool ret = true;
7758         struct torture_samr_context *ctx;
7759
7760         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7761         if (!NT_STATUS_IS_OK(status)) {
7762                 return false;
7763         }
7764
7765         ctx = talloc_zero(torture, struct torture_samr_context);
7766
7767         ctx->choice = TORTURE_SAMR_PASSWORDS;
7768
7769         ret &= test_Connect(p, torture, &ctx->handle);
7770
7771         ret &= test_EnumDomains(p, torture, ctx);
7772
7773         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7774
7775         ret &= test_samr_ValidatePassword(p, torture);
7776
7777         return ret;
7778 }
7779
7780 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
7781                                         struct dcerpc_pipe *p2,
7782                                         struct cli_credentials *machine_credentials)
7783 {
7784         NTSTATUS status;
7785         struct dcerpc_pipe *p;
7786         bool ret = true;
7787         struct torture_samr_context *ctx;
7788
7789         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7790         if (!NT_STATUS_IS_OK(status)) {
7791                 return false;
7792         }
7793
7794         ctx = talloc_zero(torture, struct torture_samr_context);
7795
7796         ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
7797         ctx->machine_credentials = machine_credentials;
7798
7799         ret &= test_Connect(p, torture, &ctx->handle);
7800
7801         ret &= test_EnumDomains(p, torture, ctx);
7802
7803         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7804
7805         return ret;
7806 }
7807
7808 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
7809 {
7810         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-PWDLASTSET");
7811         struct torture_rpc_tcase *tcase;
7812
7813         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7814                                                           &ndr_table_samr,
7815                                                           TEST_ACCOUNT_NAME_PWD);
7816
7817         torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
7818                                          torture_rpc_samr_pwdlastset);
7819
7820         return suite;
7821 }
7822
7823 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
7824                                                           struct dcerpc_pipe *p2,
7825                                                           struct cli_credentials *machine_credentials)
7826 {
7827         NTSTATUS status;
7828         struct dcerpc_pipe *p;
7829         bool ret = true;
7830         struct torture_samr_context *ctx;
7831
7832         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7833         if (!NT_STATUS_IS_OK(status)) {
7834                 return false;
7835         }
7836
7837         ctx = talloc_zero(torture, struct torture_samr_context);
7838
7839         ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
7840         ctx->machine_credentials = machine_credentials;
7841
7842         ret &= test_Connect(p, torture, &ctx->handle);
7843
7844         ret &= test_EnumDomains(p, torture, ctx);
7845
7846         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7847
7848         return ret;
7849 }
7850
7851 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
7852 {
7853         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-USERS-PRIVILEGES");
7854         struct torture_rpc_tcase *tcase;
7855
7856         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
7857                                                           &ndr_table_samr,
7858                                                           TEST_ACCOUNT_NAME_PWD);
7859
7860         torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
7861                                          torture_rpc_samr_users_privileges_delete_user);
7862
7863         return suite;
7864 }
7865
7866 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
7867                                            struct dcerpc_pipe *p2,
7868                                            void *data)
7869 {
7870         NTSTATUS status;
7871         struct dcerpc_pipe *p;
7872         bool ret = true;
7873         struct torture_samr_context *ctx =
7874                 talloc_get_type_abort(data, struct torture_samr_context);
7875
7876         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7877         if (!NT_STATUS_IS_OK(status)) {
7878                 return false;
7879         }
7880
7881         ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
7882         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7883                                                         ctx->num_objects_large_dc);
7884
7885         ret &= test_Connect(p, torture, &ctx->handle);
7886
7887         ret &= test_EnumDomains(p, torture, ctx);
7888
7889         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7890
7891         return ret;
7892 }
7893
7894 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
7895                                          struct dcerpc_pipe *p2,
7896                                          void *data)
7897 {
7898         NTSTATUS status;
7899         struct dcerpc_pipe *p;
7900         bool ret = true;
7901         struct torture_samr_context *ctx =
7902                 talloc_get_type_abort(data, struct torture_samr_context);
7903
7904         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7905         if (!NT_STATUS_IS_OK(status)) {
7906                 return false;
7907         }
7908
7909         ctx->choice = TORTURE_SAMR_MANY_GROUPS;
7910         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7911                                                         ctx->num_objects_large_dc);
7912
7913         ret &= test_Connect(p, torture, &ctx->handle);
7914
7915         ret &= test_EnumDomains(p, torture, ctx);
7916
7917         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7918
7919         return ret;
7920 }
7921
7922 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
7923                                           struct dcerpc_pipe *p2,
7924                                           void *data)
7925 {
7926         NTSTATUS status;
7927         struct dcerpc_pipe *p;
7928         bool ret = true;
7929         struct torture_samr_context *ctx =
7930                 talloc_get_type_abort(data, struct torture_samr_context);
7931
7932         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7933         if (!NT_STATUS_IS_OK(status)) {
7934                 return false;
7935         }
7936
7937         ctx->choice = TORTURE_SAMR_MANY_ALIASES;
7938         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
7939                                                         ctx->num_objects_large_dc);
7940
7941         ret &= test_Connect(p, torture, &ctx->handle);
7942
7943         ret &= test_EnumDomains(p, torture, ctx);
7944
7945         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7946
7947         return ret;
7948 }
7949
7950 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
7951 {
7952         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-LARGE-DC");
7953         struct torture_rpc_tcase *tcase;
7954         struct torture_samr_context *ctx;
7955
7956         tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
7957
7958         ctx = talloc_zero(suite, struct torture_samr_context);
7959         ctx->num_objects_large_dc = 150;
7960
7961         torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
7962                                       torture_rpc_samr_many_aliases, ctx);
7963         torture_rpc_tcase_add_test_ex(tcase, "many_groups",
7964                                       torture_rpc_samr_many_groups, ctx);
7965         torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
7966                                       torture_rpc_samr_many_accounts, ctx);
7967
7968         return suite;
7969 }
7970
7971 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
7972                                          struct dcerpc_pipe *p2,
7973                                          struct cli_credentials *machine_credentials)
7974 {
7975         NTSTATUS status;
7976         struct dcerpc_pipe *p;
7977         bool ret = true;
7978         struct torture_samr_context *ctx;
7979
7980         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7981         if (!NT_STATUS_IS_OK(status)) {
7982                 return false;
7983         }
7984
7985         ctx = talloc_zero(torture, struct torture_samr_context);
7986
7987         ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
7988         ctx->machine_credentials = machine_credentials;
7989
7990         ret &= test_Connect(p, torture, &ctx->handle);
7991
7992         ret &= test_EnumDomains(p, torture, ctx);
7993
7994         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
7995
7996         return ret;
7997 }
7998
7999 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8000 {
8001         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-BADPWDCOUNT");
8002         struct torture_rpc_tcase *tcase;
8003
8004         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8005                                                           &ndr_table_samr,
8006                                                           TEST_ACCOUNT_NAME_PWD);
8007
8008         torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8009                                          torture_rpc_samr_badpwdcount);
8010
8011         return suite;
8012 }
8013
8014 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8015                                      struct dcerpc_pipe *p2,
8016                                      struct cli_credentials *machine_credentials)
8017 {
8018         NTSTATUS status;
8019         struct dcerpc_pipe *p;
8020         bool ret = true;
8021         struct torture_samr_context *ctx;
8022
8023         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8024         if (!NT_STATUS_IS_OK(status)) {
8025                 return false;
8026         }
8027
8028         ctx = talloc_zero(torture, struct torture_samr_context);
8029
8030         ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8031         ctx->machine_credentials = machine_credentials;
8032
8033         ret &= test_Connect(p, torture, &ctx->handle);
8034
8035         ret &= test_EnumDomains(p, torture, ctx);
8036
8037         ret &= test_samr_handle_Close(p, torture, &ctx->handle);
8038
8039         return ret;
8040 }
8041
8042 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8043 {
8044         struct torture_suite *suite = torture_suite_create(mem_ctx, "SAMR-PASSWORDS-LOCKOUT");
8045         struct torture_rpc_tcase *tcase;
8046
8047         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8048                                                           &ndr_table_samr,
8049                                                           TEST_ACCOUNT_NAME_PWD);
8050
8051         torture_rpc_tcase_add_test_creds(tcase, "lockout",
8052                                          torture_rpc_samr_lockout);
8053
8054         return suite;
8055 }
8056
8057