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