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