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