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