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