s4-smbtorture: Make test names lowercase and dot-separated.
[metze/samba/wip.git] / source4 / torture / rpc / samr.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for samr rpc operations
4
5    Copyright (C) Andrew Tridgell 2003
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7    Copyright (C) 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", (long int) 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_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1874                 ret = false;
1875         }
1876
1877         oldpass = newpass;
1878         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1879
1880         E_md4hash(oldpass, old_nt_hash);
1881         E_md4hash(newpass, new_nt_hash);
1882         E_deshash(oldpass, old_lm_hash);
1883         E_deshash(newpass, new_lm_hash);
1884
1885
1886         /* Reset the hashes to not broken values */
1887         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1888         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1889         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1890         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1891         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1892         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1893
1894         r.in.user_handle = &user_handle;
1895         r.in.lm_present = 1;
1896         r.in.old_lm_crypted = &hash1;
1897         r.in.new_lm_crypted = &hash2;
1898         r.in.nt_present = 1;
1899         r.in.old_nt_crypted = &hash3;
1900         r.in.new_nt_crypted = &hash4;
1901         r.in.cross1_present = 1;
1902         r.in.nt_cross = &hash5;
1903         r.in.cross2_present = 1;
1904         r.in.lm_cross = &hash6;
1905
1906         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1907                 "ChangePasswordUser failed");
1908         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1909                 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1910         } else  if (!NT_STATUS_IS_OK(r.out.result)) {
1911                 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1912                 ret = false;
1913         } else {
1914                 changed = true;
1915                 *password = newpass;
1916         }
1917
1918         r.in.user_handle = &user_handle;
1919         r.in.lm_present = 1;
1920         r.in.old_lm_crypted = &hash1;
1921         r.in.new_lm_crypted = &hash2;
1922         r.in.nt_present = 1;
1923         r.in.old_nt_crypted = &hash3;
1924         r.in.new_nt_crypted = &hash4;
1925         r.in.cross1_present = 1;
1926         r.in.nt_cross = &hash5;
1927         r.in.cross2_present = 1;
1928         r.in.lm_cross = &hash6;
1929
1930         if (changed) {
1931                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1932                         "ChangePasswordUser failed");
1933                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1934                         torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1935                 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1936                         torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
1937                         ret = false;
1938                 }
1939         }
1940
1941
1942         if (!test_samr_handle_Close(b, tctx, &user_handle)) {
1943                 ret = false;
1944         }
1945
1946         return ret;
1947 }
1948
1949
1950 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
1951                                         struct torture_context *tctx,
1952                                         const char *acct_name,
1953                                         struct policy_handle *handle, char **password)
1954 {
1955         struct samr_OemChangePasswordUser2 r;
1956         bool ret = true;
1957         struct samr_Password lm_verifier;
1958         struct samr_CryptPassword lm_pass;
1959         struct lsa_AsciiString server, account, account_bad;
1960         char *oldpass;
1961         char *newpass;
1962         struct dcerpc_binding_handle *b = p->binding_handle;
1963         uint8_t old_lm_hash[16], new_lm_hash[16];
1964
1965         struct samr_GetDomPwInfo dom_pw_info;
1966         struct samr_PwInfo info;
1967         int policy_min_pw_len = 0;
1968
1969         struct lsa_String domain_name;
1970
1971         domain_name.string = "";
1972         dom_pw_info.in.domain_name = &domain_name;
1973         dom_pw_info.out.info = &info;
1974
1975         torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1976
1977         torture_assert(tctx, *password != NULL,
1978                                    "Failing OemChangePasswordUser2 as old password was NULL.  Previous test failed?");
1979
1980         oldpass = *password;
1981
1982         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
1983                 "GetDomPwInfo failed");
1984         if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
1985                 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1986         }
1987
1988         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1989
1990         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1991         account.string = acct_name;
1992
1993         E_deshash(oldpass, old_lm_hash);
1994         E_deshash(newpass, new_lm_hash);
1995
1996         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1997         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1998         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1999
2000         r.in.server = &server;
2001         r.in.account = &account;
2002         r.in.password = &lm_pass;
2003         r.in.hash = &lm_verifier;
2004
2005         /* Break the verification */
2006         lm_verifier.hash[0]++;
2007
2008         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2009                 "OemChangePasswordUser2 failed");
2010
2011         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2012             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2013                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2014                         nt_errstr(r.out.result));
2015                 ret = false;
2016         }
2017
2018         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2019         /* Break the old password */
2020         old_lm_hash[0]++;
2021         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2022         /* unbreak it for the next operation */
2023         old_lm_hash[0]--;
2024         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2025
2026         r.in.server = &server;
2027         r.in.account = &account;
2028         r.in.password = &lm_pass;
2029         r.in.hash = &lm_verifier;
2030
2031         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2032                 "OemChangePasswordUser2 failed");
2033
2034         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2035             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2036                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2037                         nt_errstr(r.out.result));
2038                 ret = false;
2039         }
2040
2041         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2042         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2043
2044         r.in.server = &server;
2045         r.in.account = &account;
2046         r.in.password = &lm_pass;
2047         r.in.hash = NULL;
2048
2049         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2050                 "OemChangePasswordUser2 failed");
2051
2052         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2053             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2054                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2055                         nt_errstr(r.out.result));
2056                 ret = false;
2057         }
2058
2059         /* This shouldn't be a valid name */
2060         account_bad.string = TEST_ACCOUNT_NAME "XX";
2061         r.in.account = &account_bad;
2062
2063         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2064                 "OemChangePasswordUser2 failed");
2065
2066         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2067                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2068                         nt_errstr(r.out.result));
2069                 ret = false;
2070         }
2071
2072         /* This shouldn't be a valid name */
2073         account_bad.string = TEST_ACCOUNT_NAME "XX";
2074         r.in.account = &account_bad;
2075         r.in.password = &lm_pass;
2076         r.in.hash = &lm_verifier;
2077
2078         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2079                 "OemChangePasswordUser2 failed");
2080
2081         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2082                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2083                         nt_errstr(r.out.result));
2084                 ret = false;
2085         }
2086
2087         /* This shouldn't be a valid name */
2088         account_bad.string = TEST_ACCOUNT_NAME "XX";
2089         r.in.account = &account_bad;
2090         r.in.password = NULL;
2091         r.in.hash = &lm_verifier;
2092
2093         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2094                 "OemChangePasswordUser2 failed");
2095
2096         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2097                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2098                         nt_errstr(r.out.result));
2099                 ret = false;
2100         }
2101
2102         E_deshash(oldpass, old_lm_hash);
2103         E_deshash(newpass, new_lm_hash);
2104
2105         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2106         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2107         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2108
2109         r.in.server = &server;
2110         r.in.account = &account;
2111         r.in.password = &lm_pass;
2112         r.in.hash = &lm_verifier;
2113
2114         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2115                 "OemChangePasswordUser2 failed");
2116
2117         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2118                 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2119         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2120                 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2121                 ret = false;
2122         } else {
2123                 *password = newpass;
2124         }
2125
2126         return ret;
2127 }
2128
2129
2130 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2131                                      const char *acct_name,
2132                                      char **password,
2133                                      char *newpass, bool allow_password_restriction)
2134 {
2135         struct samr_ChangePasswordUser2 r;
2136         bool ret = true;
2137         struct lsa_String server, account;
2138         struct samr_CryptPassword nt_pass, lm_pass;
2139         struct samr_Password nt_verifier, lm_verifier;
2140         char *oldpass;
2141         struct dcerpc_binding_handle *b = p->binding_handle;
2142         uint8_t old_nt_hash[16], new_nt_hash[16];
2143         uint8_t old_lm_hash[16], new_lm_hash[16];
2144
2145         struct samr_GetDomPwInfo dom_pw_info;
2146         struct samr_PwInfo info;
2147
2148         struct lsa_String domain_name;
2149
2150         domain_name.string = "";
2151         dom_pw_info.in.domain_name = &domain_name;
2152         dom_pw_info.out.info = &info;
2153
2154         torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2155
2156         torture_assert(tctx, *password != NULL,
2157                                    "Failing ChangePasswordUser2 as old password was NULL.  Previous test failed?");
2158         oldpass = *password;
2159
2160         if (!newpass) {
2161                 int policy_min_pw_len = 0;
2162                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2163                         "GetDomPwInfo failed");
2164                 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2165                         policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2166                 }
2167
2168                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2169         }
2170
2171         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2172         init_lsa_String(&account, acct_name);
2173
2174         E_md4hash(oldpass, old_nt_hash);
2175         E_md4hash(newpass, new_nt_hash);
2176
2177         E_deshash(oldpass, old_lm_hash);
2178         E_deshash(newpass, new_lm_hash);
2179
2180         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
2181         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2182         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2183
2184         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2185         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2186         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2187
2188         r.in.server = &server;
2189         r.in.account = &account;
2190         r.in.nt_password = &nt_pass;
2191         r.in.nt_verifier = &nt_verifier;
2192         r.in.lm_change = 1;
2193         r.in.lm_password = &lm_pass;
2194         r.in.lm_verifier = &lm_verifier;
2195
2196         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2197                 "ChangePasswordUser2 failed");
2198
2199         if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2200                 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2201         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2202                 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2203                 ret = false;
2204         } else {
2205                 *password = newpass;
2206         }
2207
2208         return ret;
2209 }
2210
2211
2212 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2213                               const char *account_string,
2214                               int policy_min_pw_len,
2215                               char **password,
2216                               const char *newpass,
2217                               NTTIME last_password_change,
2218                               bool handle_reject_reason)
2219 {
2220         struct samr_ChangePasswordUser3 r;
2221         bool ret = true;
2222         struct lsa_String server, account, account_bad;
2223         struct samr_CryptPassword nt_pass, lm_pass;
2224         struct samr_Password nt_verifier, lm_verifier;
2225         char *oldpass;
2226         struct dcerpc_binding_handle *b = p->binding_handle;
2227         uint8_t old_nt_hash[16], new_nt_hash[16];
2228         uint8_t old_lm_hash[16], new_lm_hash[16];
2229         NTTIME t;
2230         struct samr_DomInfo1 *dominfo = NULL;
2231         struct userPwdChangeFailureInformation *reject = NULL;
2232
2233         torture_comment(tctx, "Testing ChangePasswordUser3\n");
2234
2235         if (newpass == NULL) {
2236                 do {
2237                         if (policy_min_pw_len == 0) {
2238                                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2239                         } else {
2240                                 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2241                         }
2242                 } while (check_password_quality(newpass) == false);
2243         } else {
2244                 torture_comment(tctx, "Using password '%s'\n", newpass);
2245         }
2246
2247         torture_assert(tctx, *password != NULL,
2248                                    "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
2249
2250         oldpass = *password;
2251         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2252         init_lsa_String(&account, account_string);
2253
2254         E_md4hash(oldpass, old_nt_hash);
2255         E_md4hash(newpass, new_nt_hash);
2256
2257         E_deshash(oldpass, old_lm_hash);
2258         E_deshash(newpass, new_lm_hash);
2259
2260         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2261         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2262         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2263
2264         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2265         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2266         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2267
2268         /* Break the verification */
2269         nt_verifier.hash[0]++;
2270
2271         r.in.server = &server;
2272         r.in.account = &account;
2273         r.in.nt_password = &nt_pass;
2274         r.in.nt_verifier = &nt_verifier;
2275         r.in.lm_change = 1;
2276         r.in.lm_password = &lm_pass;
2277         r.in.lm_verifier = &lm_verifier;
2278         r.in.password3 = NULL;
2279         r.out.dominfo = &dominfo;
2280         r.out.reject = &reject;
2281
2282         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2283                 "ChangePasswordUser3 failed");
2284         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2285             (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2286                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2287                         nt_errstr(r.out.result));
2288                 ret = false;
2289         }
2290
2291         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2292         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2293         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2294
2295         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2296         /* Break the NT hash */
2297         old_nt_hash[0]++;
2298         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2299         /* Unbreak it again */
2300         old_nt_hash[0]--;
2301         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2302
2303         r.in.server = &server;
2304         r.in.account = &account;
2305         r.in.nt_password = &nt_pass;
2306         r.in.nt_verifier = &nt_verifier;
2307         r.in.lm_change = 1;
2308         r.in.lm_password = &lm_pass;
2309         r.in.lm_verifier = &lm_verifier;
2310         r.in.password3 = NULL;
2311         r.out.dominfo = &dominfo;
2312         r.out.reject = &reject;
2313
2314         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2315                 "ChangePasswordUser3 failed");
2316         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2317             (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2318                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2319                         nt_errstr(r.out.result));
2320                 ret = false;
2321         }
2322
2323         /* This shouldn't be a valid name */
2324         init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2325
2326         r.in.account = &account_bad;
2327         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2328                 "ChangePasswordUser3 failed");
2329         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2330                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2331                         nt_errstr(r.out.result));
2332                 ret = false;
2333         }
2334
2335         E_md4hash(oldpass, old_nt_hash);
2336         E_md4hash(newpass, new_nt_hash);
2337
2338         E_deshash(oldpass, old_lm_hash);
2339         E_deshash(newpass, new_lm_hash);
2340
2341         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2342         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2343         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2344
2345         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2346         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2347         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2348
2349         r.in.server = &server;
2350         r.in.account = &account;
2351         r.in.nt_password = &nt_pass;
2352         r.in.nt_verifier = &nt_verifier;
2353         r.in.lm_change = 1;
2354         r.in.lm_password = &lm_pass;
2355         r.in.lm_verifier = &lm_verifier;
2356         r.in.password3 = NULL;
2357         r.out.dominfo = &dominfo;
2358         r.out.reject = &reject;
2359
2360         unix_to_nt_time(&t, time(NULL));
2361
2362         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2363                 "ChangePasswordUser3 failed");
2364
2365         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2366             && dominfo
2367             && reject
2368             && handle_reject_reason
2369             && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2370                 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2371
2372                         if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2373                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2374                                         SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2375                                 return false;
2376                         }
2377                 }
2378
2379                 /* We tested the order of precendence which is as follows:
2380
2381                 * pwd min_age
2382                 * pwd length
2383                 * pwd complexity
2384                 * pwd history
2385
2386                 Guenther */
2387
2388                 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2389                            (last_password_change + dominfo->min_password_age > t)) {
2390
2391                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2392                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2393                                         SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2394                                 return false;
2395                         }
2396
2397                 } else if ((dominfo->min_password_length > 0) &&
2398                            (strlen(newpass) < dominfo->min_password_length)) {
2399
2400                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2401                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2402                                         SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2403                                 return false;
2404                         }
2405
2406                 } else if ((dominfo->password_history_length > 0) &&
2407                             strequal(oldpass, newpass)) {
2408
2409                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2410                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2411                                         SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2412                                 return false;
2413                         }
2414                 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2415
2416                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2417                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2418                                         SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2419                                 return false;
2420                         }
2421
2422                 }
2423
2424                 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2425                         /* retry with adjusted size */
2426                         return test_ChangePasswordUser3(p, tctx, account_string,
2427                                                         dominfo->min_password_length,
2428                                                         password, NULL, 0, false);
2429
2430                 }
2431
2432         } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2433                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2434                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2435                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2436                         return false;
2437                 }
2438                 /* Perhaps the server has a 'min password age' set? */
2439
2440         } else {
2441                 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2442
2443                 *password = talloc_strdup(tctx, newpass);
2444         }
2445
2446         return ret;
2447 }
2448
2449 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2450                                     const char *account_string,
2451                                     struct policy_handle *handle,
2452                                     char **password)
2453 {
2454         NTSTATUS status;
2455         struct samr_ChangePasswordUser3 r;
2456         struct samr_SetUserInfo s;
2457         union samr_UserInfo u;
2458         DATA_BLOB session_key;
2459         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2460         uint8_t confounder[16];
2461         struct MD5Context ctx;
2462
2463         bool ret = true;
2464         struct lsa_String server, account;
2465         struct samr_CryptPassword nt_pass;
2466         struct samr_Password nt_verifier;
2467         DATA_BLOB new_random_pass;
2468         char *newpass;
2469         char *oldpass;
2470         struct dcerpc_binding_handle *b = p->binding_handle;
2471         uint8_t old_nt_hash[16], new_nt_hash[16];
2472         NTTIME t;
2473         struct samr_DomInfo1 *dominfo = NULL;
2474         struct userPwdChangeFailureInformation *reject = NULL;
2475
2476         new_random_pass = samr_very_rand_pass(tctx, 128);
2477
2478         torture_assert(tctx, *password != NULL,
2479                                    "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
2480
2481         oldpass = *password;
2482         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2483         init_lsa_String(&account, account_string);
2484
2485         s.in.user_handle = handle;
2486         s.in.info = &u;
2487         s.in.level = 25;
2488
2489         ZERO_STRUCT(u);
2490
2491         u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2492
2493         set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2494
2495         status = dcerpc_fetch_session_key(p, &session_key);
2496         if (!NT_STATUS_IS_OK(status)) {
2497                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2498                        s.in.level, nt_errstr(status));
2499                 return false;
2500         }
2501
2502         generate_random_buffer((uint8_t *)confounder, 16);
2503
2504         MD5Init(&ctx);
2505         MD5Update(&ctx, confounder, 16);
2506         MD5Update(&ctx, session_key.data, session_key.length);
2507         MD5Final(confounded_session_key.data, &ctx);
2508
2509         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2510         memcpy(&u.info25.password.data[516], confounder, 16);
2511
2512         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2513
2514         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2515                 "SetUserInfo failed");
2516         if (!NT_STATUS_IS_OK(s.out.result)) {
2517                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2518                        s.in.level, nt_errstr(s.out.result));
2519                 ret = false;
2520         }
2521
2522         torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2523
2524         mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2525
2526         new_random_pass = samr_very_rand_pass(tctx, 128);
2527
2528         mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2529
2530         set_pw_in_buffer(nt_pass.data, &new_random_pass);
2531         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2532         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2533
2534         r.in.server = &server;
2535         r.in.account = &account;
2536         r.in.nt_password = &nt_pass;
2537         r.in.nt_verifier = &nt_verifier;
2538         r.in.lm_change = 0;
2539         r.in.lm_password = NULL;
2540         r.in.lm_verifier = NULL;
2541         r.in.password3 = NULL;
2542         r.out.dominfo = &dominfo;
2543         r.out.reject = &reject;
2544
2545         unix_to_nt_time(&t, time(NULL));
2546
2547         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2548                 "ChangePasswordUser3 failed");
2549
2550         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2551                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2552                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2553                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2554                         return false;
2555                 }
2556                 /* Perhaps the server has a 'min password age' set? */
2557
2558         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2559                 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2560                 ret = false;
2561         }
2562
2563         newpass = samr_rand_pass(tctx, 128);
2564
2565         mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2566
2567         E_md4hash(newpass, new_nt_hash);
2568
2569         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2570         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2571         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2572
2573         r.in.server = &server;
2574         r.in.account = &account;
2575         r.in.nt_password = &nt_pass;
2576         r.in.nt_verifier = &nt_verifier;
2577         r.in.lm_change = 0;
2578         r.in.lm_password = NULL;
2579         r.in.lm_verifier = NULL;
2580         r.in.password3 = NULL;
2581         r.out.dominfo = &dominfo;
2582         r.out.reject = &reject;
2583
2584         unix_to_nt_time(&t, time(NULL));
2585
2586         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2587                 "ChangePasswordUser3 failed");
2588
2589         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2590                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2591                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2592                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2593                         return false;
2594                 }
2595                 /* Perhaps the server has a 'min password age' set? */
2596
2597         } else {
2598                 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2599                 *password = talloc_strdup(tctx, newpass);
2600         }
2601
2602         return ret;
2603 }
2604
2605
2606 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2607                                    struct torture_context *tctx,
2608                                    struct policy_handle *alias_handle)
2609 {
2610         struct samr_GetMembersInAlias r;
2611         struct lsa_SidArray sids;
2612
2613         torture_comment(tctx, "Testing GetMembersInAlias\n");
2614
2615         r.in.alias_handle = alias_handle;
2616         r.out.sids = &sids;
2617
2618         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2619                 "GetMembersInAlias failed");
2620         torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2621
2622         return true;
2623 }
2624
2625 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2626                                   struct torture_context *tctx,
2627                                   struct policy_handle *alias_handle,
2628                                   const struct dom_sid *domain_sid)
2629 {
2630         struct samr_AddAliasMember r;
2631         struct samr_DeleteAliasMember d;
2632         struct dom_sid *sid;
2633
2634         sid = dom_sid_add_rid(tctx, domain_sid, 512);
2635
2636         torture_comment(tctx, "Testing AddAliasMember\n");
2637         r.in.alias_handle = alias_handle;
2638         r.in.sid = sid;
2639
2640         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2641                 "AddAliasMember failed");
2642         torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2643
2644         d.in.alias_handle = alias_handle;
2645         d.in.sid = sid;
2646
2647         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2648                 "DeleteAliasMember failed");
2649         torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2650
2651         return true;
2652 }
2653
2654 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2655                                            struct torture_context *tctx,
2656                                            struct policy_handle *alias_handle)
2657 {
2658         struct samr_AddMultipleMembersToAlias a;
2659         struct samr_RemoveMultipleMembersFromAlias r;
2660         struct lsa_SidArray sids;
2661
2662         torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2663         a.in.alias_handle = alias_handle;
2664         a.in.sids = &sids;
2665
2666         sids.num_sids = 3;
2667         sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2668
2669         sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2670         sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2671         sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2672
2673         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2674                 "AddMultipleMembersToAlias failed");
2675         torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2676
2677
2678         torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2679         r.in.alias_handle = alias_handle;
2680         r.in.sids = &sids;
2681
2682         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2683                 "RemoveMultipleMembersFromAlias failed");
2684         torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2685
2686         /* strange! removing twice doesn't give any error */
2687         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2688                 "RemoveMultipleMembersFromAlias failed");
2689         torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2690
2691         /* but removing an alias that isn't there does */
2692         sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2693
2694         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2695                 "RemoveMultipleMembersFromAlias failed");
2696         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2697
2698         return true;
2699 }
2700
2701 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2702                                     struct torture_context *tctx,
2703                                     struct policy_handle *domain_handle)
2704 {
2705         struct samr_GetAliasMembership r;
2706         struct lsa_SidArray sids;
2707         struct samr_Ids rids;
2708
2709         torture_comment(tctx, "Testing GetAliasMembership\n");
2710
2711         r.in.domain_handle      = domain_handle;
2712         r.in.sids               = &sids;
2713         r.out.rids              = &rids;
2714
2715         sids.num_sids = 0;
2716         sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2717
2718         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2719                 "GetAliasMembership failed");
2720         torture_assert_ntstatus_ok(tctx, r.out.result,
2721                 "samr_GetAliasMembership failed");
2722
2723         torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2724                 "protocol misbehaviour");
2725
2726         sids.num_sids = 1;
2727         sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2728         sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2729
2730         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2731                 "samr_GetAliasMembership failed");
2732         torture_assert_ntstatus_ok(tctx, r.out.result,
2733                 "samr_GetAliasMembership failed");
2734
2735 #if 0
2736         /* only true for w2k8 it seems
2737          * win7, xp, w2k3 will return a 0 length array pointer */
2738
2739         if (rids.ids && (rids.count == 0)) {
2740                 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2741         }
2742 #endif
2743         if (!rids.ids && rids.count) {
2744                 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2745         }
2746
2747         return true;
2748 }
2749
2750 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2751                                           struct torture_context *tctx,
2752                                           struct policy_handle *user_handle)
2753 {
2754         struct samr_TestPrivateFunctionsUser r;
2755
2756         torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2757
2758         r.in.user_handle = user_handle;
2759
2760         torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2761                 "TestPrivateFunctionsUser failed");
2762         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2763
2764         return true;
2765 }
2766
2767 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2768                                           struct torture_context *tctx,
2769                                           struct policy_handle *handle,
2770                                           bool use_info2,
2771                                           NTTIME *pwdlastset)
2772 {
2773         NTSTATUS status;
2774         uint16_t levels[] = { /* 3, */ 5, 21 };
2775         int i;
2776         NTTIME pwdlastset3 = 0;
2777         NTTIME pwdlastset5 = 0;
2778         NTTIME pwdlastset21 = 0;
2779
2780         torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2781                         use_info2 ? "2":"");
2782
2783         for (i=0; i<ARRAY_SIZE(levels); i++) {
2784
2785                 struct samr_QueryUserInfo r;
2786                 struct samr_QueryUserInfo2 r2;
2787                 union samr_UserInfo *info;
2788
2789                 if (use_info2) {
2790                         r2.in.user_handle = handle;
2791                         r2.in.level = levels[i];
2792                         r2.out.info = &info;
2793                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2794                                 "QueryUserInfo2 failed");
2795                         status = r2.out.result;
2796
2797                 } else {
2798                         r.in.user_handle = handle;
2799                         r.in.level = levels[i];
2800                         r.out.info = &info;
2801                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2802                                 "QueryUserInfo failed");
2803                         status = r.out.result;
2804                 }
2805
2806                 if (!NT_STATUS_IS_OK(status) &&
2807                     !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2808                         torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2809                                use_info2 ? "2":"", levels[i], nt_errstr(status));
2810                         return false;
2811                 }
2812
2813                 switch (levels[i]) {
2814                 case 3:
2815                         pwdlastset3 = info->info3.last_password_change;
2816                         break;
2817                 case 5:
2818                         pwdlastset5 = info->info5.last_password_change;
2819                         break;
2820                 case 21:
2821                         pwdlastset21 = info->info21.last_password_change;
2822                         break;
2823                 default:
2824                         return false;
2825                 }
2826         }
2827         /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2828                                     "pwdlastset mixup"); */
2829         torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2830                                  "pwdlastset mixup");
2831
2832         *pwdlastset = pwdlastset21;
2833
2834         torture_comment(tctx, "(pwdlastset: %llu)\n",
2835                         (unsigned long long) *pwdlastset);
2836
2837         return true;
2838 }
2839
2840 static bool test_SamLogon(struct torture_context *tctx,
2841                           struct dcerpc_pipe *p,
2842                           struct cli_credentials *test_credentials,
2843                           NTSTATUS expected_result,
2844                           bool interactive)
2845 {
2846         NTSTATUS status;
2847         struct netr_LogonSamLogonEx r;
2848         union netr_LogonLevel logon;
2849         union netr_Validation validation;
2850         uint8_t authoritative;
2851         struct netr_IdentityInfo identity;
2852         struct netr_NetworkInfo ninfo;
2853         struct netr_PasswordInfo pinfo;
2854         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2855         int flags = CLI_CRED_NTLM_AUTH;
2856         uint32_t samlogon_flags = 0;
2857         struct netlogon_creds_CredentialState *creds;
2858         struct netr_Authenticator a;
2859         struct dcerpc_binding_handle *b = p->binding_handle;
2860
2861         torture_assert_ntstatus_ok(tctx, dcerpc_schannel_creds(p->conn->security_state.generic_state, tctx, &creds), "");
2862
2863         if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
2864                 flags |= CLI_CRED_LANMAN_AUTH;
2865         }
2866
2867         if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
2868                 flags |= CLI_CRED_NTLMv2_AUTH;
2869         }
2870
2871         cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2872                                                  &identity.account_name.string,
2873                                                  &identity.domain_name.string);
2874
2875         identity.parameter_control =
2876                 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2877                 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2878         identity.logon_id_low = 0;
2879         identity.logon_id_high = 0;
2880         identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2881
2882         if (interactive) {
2883                 netlogon_creds_client_authenticator(creds, &a);
2884
2885                 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
2886                         ZERO_STRUCT(pinfo.lmpassword.hash);
2887                 }
2888                 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
2889
2890                 if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
2891                         netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
2892                         netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
2893                 } else {
2894                         netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
2895                         netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
2896                 }
2897
2898                 pinfo.identity_info = identity;
2899                 logon.password = &pinfo;
2900
2901                 r.in.logon_level = NetlogonInteractiveInformation;
2902         } else {
2903                 generate_random_buffer(ninfo.challenge,
2904                                        sizeof(ninfo.challenge));
2905                 chal = data_blob_const(ninfo.challenge,
2906                                        sizeof(ninfo.challenge));
2907
2908                 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
2909                                                         cli_credentials_get_domain(test_credentials));
2910
2911                 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
2912                                                            &flags,
2913                                                            chal,
2914                                                            names_blob,
2915                                                            &lm_resp, &nt_resp,
2916                                                            NULL, NULL);
2917                 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
2918
2919                 ninfo.lm.data = lm_resp.data;
2920                 ninfo.lm.length = lm_resp.length;
2921
2922                 ninfo.nt.data = nt_resp.data;
2923                 ninfo.nt.length = nt_resp.length;
2924
2925                 ninfo.identity_info = identity;
2926                 logon.network = &ninfo;
2927
2928                 r.in.logon_level = NetlogonNetworkInformation;
2929         }
2930
2931         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2932         r.in.computer_name = cli_credentials_get_workstation(test_credentials);
2933         r.in.logon = &logon;
2934         r.in.flags = &samlogon_flags;
2935         r.out.flags = &samlogon_flags;
2936         r.out.validation = &validation;
2937         r.out.authoritative = &authoritative;
2938
2939         torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
2940
2941         r.in.validation_level = 6;
2942
2943         torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
2944                 "netr_LogonSamLogonEx failed");
2945         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
2946                 r.in.validation_level = 3;
2947                 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
2948                         "netr_LogonSamLogonEx failed");
2949         }
2950         if (!NT_STATUS_IS_OK(r.out.result)) {
2951                 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
2952                 return true;
2953         } else {
2954                 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
2955         }
2956
2957         return true;
2958 }
2959
2960 static bool test_SamLogon_with_creds(struct torture_context *tctx,
2961                                      struct dcerpc_pipe *p,
2962                                      struct cli_credentials *machine_creds,
2963                                      const char *acct_name,
2964                                      const char *password,
2965                                      NTSTATUS expected_samlogon_result,
2966                                      bool interactive)
2967 {
2968         bool ret = true;
2969         struct cli_credentials *test_credentials;
2970
2971         test_credentials = cli_credentials_init(tctx);
2972
2973         cli_credentials_set_workstation(test_credentials,
2974                                         cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
2975         cli_credentials_set_domain(test_credentials,
2976                                    cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
2977         cli_credentials_set_username(test_credentials,
2978                                      acct_name, CRED_SPECIFIED);
2979         cli_credentials_set_password(test_credentials,
2980                                      password, CRED_SPECIFIED);
2981
2982         torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
2983                 interactive ? "interactive" : "network", acct_name, password);
2984
2985         if (!test_SamLogon(tctx, p, test_credentials,
2986                             expected_samlogon_result, interactive)) {
2987                 torture_warning(tctx, "new password did not work\n");
2988                 ret = false;
2989         }
2990
2991         return ret;
2992 }
2993
2994 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2995                                    struct dcerpc_pipe *np,
2996                                    struct torture_context *tctx,
2997                                    struct policy_handle *handle,
2998                                    uint16_t level,
2999                                    uint32_t fields_present,
3000                                    uint8_t password_expired,
3001                                    bool *matched_expected_error,
3002                                    bool use_setinfo2,
3003                                    const char *acct_name,
3004                                    char **password,
3005                                    struct cli_credentials *machine_creds,
3006                                    bool use_queryinfo2,
3007                                    NTTIME *pwdlastset,
3008                                    NTSTATUS expected_samlogon_result)
3009 {
3010         const char *fields = NULL;
3011         bool ret = true;
3012         struct dcerpc_binding_handle *b = p->binding_handle;
3013
3014         switch (level) {
3015         case 21:
3016         case 23:
3017         case 25:
3018                 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3019                                          fields_present);
3020                 break;
3021         default:
3022                 break;
3023         }
3024
3025         torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3026                 "(password_expired: %d) %s\n",
3027                 use_setinfo2 ? "2":"", level, password_expired,
3028                 fields ? fields : "");
3029
3030         if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3031                                        fields_present,
3032                                        password,
3033                                        password_expired,
3034                                        use_setinfo2,
3035                                        matched_expected_error)) {
3036                 ret = false;
3037         }
3038
3039         if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3040                                            use_queryinfo2,
3041                                            pwdlastset)) {
3042                 ret = false;
3043         }
3044
3045         if (*matched_expected_error == true) {
3046                 return ret;
3047         }
3048
3049         if (!test_SamLogon_with_creds(tctx, np,
3050                                       machine_creds,
3051                                       acct_name,
3052                                       *password,
3053                                       expected_samlogon_result,
3054                                       false)) {
3055                 ret = false;
3056         }
3057
3058         return ret;
3059 }
3060
3061 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3062                                          struct cli_credentials *credentials,
3063                                          struct dcerpc_pipe **p)
3064 {
3065         struct dcerpc_binding *b;
3066
3067         torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3068                 "failed to get rpc binding");
3069
3070         /* We have to use schannel, otherwise the SamLogonEx fails
3071          * with INTERNAL_ERROR */
3072
3073         b->flags &= ~DCERPC_AUTH_OPTIONS;
3074         b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_128;
3075
3076         torture_assert_ntstatus_ok(tctx,
3077                 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3078                                       credentials, tctx->ev, tctx->lp_ctx),
3079                 "failed to bind to netlogon");
3080
3081         return true;
3082 }
3083
3084 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3085                                         struct torture_context *tctx,
3086                                         uint32_t acct_flags,
3087                                         const char *acct_name,
3088                                         struct policy_handle *handle,
3089                                         char **password,
3090                                         struct cli_credentials *machine_credentials)
3091 {
3092         int s = 0, q = 0, f = 0, l = 0, z = 0;
3093         bool ret = true;
3094         int delay = 50000;
3095         bool set_levels[] = { false, true };
3096         bool query_levels[] = { false, true };
3097         uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3098         uint32_t nonzeros[] = { 1, 24 };
3099         uint32_t fields_present[] = {
3100                 0,
3101                 SAMR_FIELD_EXPIRED_FLAG,
3102                 SAMR_FIELD_LAST_PWD_CHANGE,
3103                 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3104                 SAMR_FIELD_COMMENT,
3105                 SAMR_FIELD_NT_PASSWORD_PRESENT,
3106                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3107                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3108                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3109                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3110                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3111                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3112         };
3113         struct dcerpc_pipe *np = NULL;
3114
3115         if (torture_setting_bool(tctx, "samba3", false) ||
3116             torture_setting_bool(tctx, "samba4", false)) {
3117                 delay = 999999;
3118                 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3119                         delay);
3120         }
3121
3122         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3123
3124         /* set to 1 to enable testing for all possible opcode
3125            (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3126            combinations */
3127 #if 0
3128 #define TEST_ALL_LEVELS 1
3129 #define TEST_SET_LEVELS 1
3130 #define TEST_QUERY_LEVELS 1
3131 #endif
3132 #ifdef TEST_ALL_LEVELS
3133         for (l=0; l<ARRAY_SIZE(levels); l++) {
3134 #else
3135         for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3136 #endif
3137         for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3138         for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3139 #ifdef TEST_SET_LEVELS
3140         for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3141 #endif
3142 #ifdef TEST_QUERY_LEVELS
3143         for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3144 #endif
3145                 NTTIME pwdlastset_old = 0;
3146                 NTTIME pwdlastset_new = 0;
3147                 bool matched_expected_error = false;
3148                 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3149
3150                 torture_comment(tctx, "------------------------------\n"
3151                                 "Testing pwdLastSet attribute for flags: 0x%08x "
3152                                 "(s: %d (l: %d), q: %d)\n",
3153                                 acct_flags, s, levels[l], q);
3154
3155                 switch (levels[l]) {
3156                 case 21:
3157                 case 23:
3158                 case 25:
3159                         if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3160                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3161                                 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3162                         }
3163                         break;
3164                 }
3165
3166
3167                 /* set #1 */
3168
3169                 /* set a password and force password change (pwdlastset 0) by
3170                  * setting the password expired flag to a non-0 value */
3171
3172                 if (!test_SetPassword_level(p, np, tctx, handle,
3173                                             levels[l],
3174                                             fields_present[f],
3175                                             nonzeros[z],
3176                                             &matched_expected_error,
3177                                             set_levels[s],
3178                                             acct_name,
3179                                             password,
3180                                             machine_credentials,
3181                                             query_levels[q],
3182                                             &pwdlastset_new,
3183                                             expected_samlogon_result)) {
3184                         ret = false;
3185                 }
3186
3187                 if (matched_expected_error == true) {
3188                         /* skipping on expected failure */
3189                         continue;
3190                 }
3191
3192                 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3193                  * set without the SAMR_FIELD_EXPIRED_FLAG */
3194
3195                 switch (levels[l]) {
3196                 case 21:
3197                 case 23:
3198                 case 25:
3199                         if ((pwdlastset_new != 0) &&
3200                             !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3201                                 torture_comment(tctx, "not considering a non-0 "
3202                                         "pwdLastSet as a an error as the "
3203                                         "SAMR_FIELD_EXPIRED_FLAG has not "
3204                                         "been set\n");
3205                                 break;
3206                         }
3207                         break;
3208                 default:
3209                         if (pwdlastset_new != 0) {
3210                                 torture_warning(tctx, "pwdLastSet test failed: "
3211                                         "expected pwdLastSet 0 but got %llu\n",
3212                                         (unsigned long long) pwdlastset_old);
3213                                 ret = false;
3214                         }
3215                         break;
3216                 }
3217
3218                 switch (levels[l]) {
3219                 case 21:
3220                 case 23:
3221                 case 25:
3222                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3223                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3224                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3225                              (pwdlastset_old >= pwdlastset_new)) {
3226                                 torture_warning(tctx, "pwdlastset not increasing\n");
3227                                 ret = false;
3228                         }
3229                         break;
3230                 }
3231
3232                 pwdlastset_old = pwdlastset_new;
3233
3234                 usleep(delay);
3235
3236                 /* set #2 */
3237
3238                 /* set a password, pwdlastset needs to get updated (increased
3239                  * value), password_expired value used here is 0 */
3240
3241                 if (!test_SetPassword_level(p, np, tctx, handle,
3242                                             levels[l],
3243                                             fields_present[f],
3244                                             0,
3245                                             &matched_expected_error,
3246                                             set_levels[s],
3247                                             acct_name,
3248                                             password,
3249                                             machine_credentials,
3250                                             query_levels[q],
3251                                             &pwdlastset_new,
3252                                             expected_samlogon_result)) {
3253                         ret = false;
3254                 }
3255
3256                 /* when a password has been changed, pwdlastset must not be 0 afterwards
3257                  * and must be larger then the old value */
3258
3259                 switch (levels[l]) {
3260                 case 21:
3261                 case 23:
3262                 case 25:
3263                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3264                          * password has been changed, old and new pwdlastset
3265                          * need to be the same value */
3266
3267                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3268                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3269                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3270                         {
3271                                 torture_assert_int_equal(tctx, pwdlastset_old,
3272                                         pwdlastset_new, "pwdlastset must be equal");
3273                                 break;
3274                         }
3275                         break;
3276                 default:
3277                         if (pwdlastset_old >= pwdlastset_new) {
3278                                 torture_warning(tctx, "pwdLastSet test failed: "
3279                                         "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3280                                         (unsigned long long) pwdlastset_old,
3281                                         (unsigned long long) pwdlastset_new);
3282                                 ret = false;
3283                         }
3284                         if (pwdlastset_new == 0) {
3285                                 torture_warning(tctx, "pwdLastSet test failed: "
3286                                         "expected non-0 pwdlastset, got: %llu\n",
3287                                         (unsigned long long) pwdlastset_new);
3288                                 ret = false;
3289                         }
3290                         break;
3291                 }
3292
3293                 switch (levels[l]) {
3294                 case 21:
3295                 case 23:
3296                 case 25:
3297                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3298                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3299                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3300                              (pwdlastset_old >= pwdlastset_new)) {
3301                                 torture_warning(tctx, "pwdlastset not increasing\n");
3302                                 ret = false;
3303                         }
3304                         break;
3305                 }
3306
3307                 pwdlastset_old = pwdlastset_new;
3308
3309                 usleep(delay);
3310
3311                 /* set #2b */
3312
3313                 /* set a password, pwdlastset needs to get updated (increased
3314                  * value), password_expired value used here is 0 */
3315
3316                 if (!test_SetPassword_level(p, np, tctx, handle,
3317                                             levels[l],
3318                                             fields_present[f],
3319                                             0,
3320                                             &matched_expected_error,
3321                                             set_levels[s],
3322                                             acct_name,
3323                                             password,
3324                                             machine_credentials,
3325                                             query_levels[q],
3326                                             &pwdlastset_new,
3327                                             expected_samlogon_result)) {
3328                         ret = false;
3329                 }
3330
3331                 /* when a password has been changed, pwdlastset must not be 0 afterwards
3332                  * and must be larger then the old value */
3333
3334                 switch (levels[l]) {
3335                 case 21:
3336                 case 23:
3337                 case 25:
3338
3339                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3340                          * password has been changed, old and new pwdlastset
3341                          * need to be the same value */
3342
3343                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3344                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3345                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3346                         {
3347                                 torture_assert_int_equal(tctx, pwdlastset_old,
3348                                         pwdlastset_new, "pwdlastset must be equal");
3349                                 break;
3350                         }
3351                         break;
3352                 default:
3353                         if (pwdlastset_old >= pwdlastset_new) {
3354                                 torture_warning(tctx, "pwdLastSet test failed: "
3355                                         "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3356                                         (unsigned long long) pwdlastset_old,
3357                                         (unsigned long long) pwdlastset_new);
3358                                 ret = false;
3359                         }
3360                         if (pwdlastset_new == 0) {
3361                                 torture_warning(tctx, "pwdLastSet test failed: "
3362                                         "expected non-0 pwdlastset, got: %llu\n",
3363                                         (unsigned long long) pwdlastset_new);
3364                                 ret = false;
3365                         }
3366                         break;
3367                 }
3368
3369                 switch (levels[l]) {
3370                 case 21:
3371                 case 23:
3372                 case 25:
3373                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3374                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3375                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3376                              (pwdlastset_old >= pwdlastset_new)) {
3377                                 torture_warning(tctx, "pwdlastset not increasing\n");
3378                                 ret = false;
3379                         }
3380                         break;
3381                 }
3382
3383                 pwdlastset_old = pwdlastset_new;
3384
3385                 usleep(delay);
3386
3387                 /* set #3 */
3388
3389                 /* set a password and force password change (pwdlastset 0) by
3390                  * setting the password expired flag to a non-0 value */
3391
3392                 if (!test_SetPassword_level(p, np, tctx, handle,
3393                                             levels[l],
3394                                             fields_present[f],
3395                                             nonzeros[z],
3396                                             &matched_expected_error,
3397                                             set_levels[s],
3398                                             acct_name,
3399                                             password,
3400                                             machine_credentials,
3401                                             query_levels[q],
3402                                             &pwdlastset_new,
3403                                             expected_samlogon_result)) {
3404                         ret = false;
3405                 }
3406
3407                 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3408                  * set without the SAMR_FIELD_EXPIRED_FLAG */
3409
3410                 switch (levels[l]) {
3411                 case 21:
3412                 case 23:
3413                 case 25:
3414                         if ((pwdlastset_new != 0) &&
3415                             !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3416                                 torture_comment(tctx, "not considering a non-0 "
3417                                         "pwdLastSet as a an error as the "
3418                                         "SAMR_FIELD_EXPIRED_FLAG has not "
3419                                         "been set\n");
3420                                 break;
3421                         }
3422
3423                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3424                          * password has been changed, old and new pwdlastset
3425                          * need to be the same value */
3426
3427                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3428                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3429                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3430                         {
3431                                 torture_assert_int_equal(tctx, pwdlastset_old,
3432                                         pwdlastset_new, "pwdlastset must be equal");
3433                                 break;
3434                         }
3435                         break;
3436                 default:
3437                         if (pwdlastset_new != 0) {
3438                                 torture_warning(tctx, "pwdLastSet test failed: "
3439                                         "expected pwdLastSet 0, got %llu\n",
3440                                         (unsigned long long) pwdlastset_old);
3441                                 ret = false;
3442                         }
3443                         break;
3444                 }
3445
3446                 switch (levels[l]) {
3447                 case 21:
3448                 case 23:
3449                 case 25:
3450                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3451                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3452                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3453                              (pwdlastset_old >= pwdlastset_new)) {
3454                                 torture_warning(tctx, "pwdlastset not increasing\n");
3455                                 ret = false;
3456                         }
3457                         break;
3458                 }
3459
3460                 /* if the level we are testing does not have a fields_present
3461                  * field, skip all fields present tests by setting f to to
3462                  * arraysize */
3463                 switch (levels[l]) {
3464                 case 18:
3465                 case 24:
3466                 case 26:
3467                         f = ARRAY_SIZE(fields_present);
3468                         break;
3469                 }
3470
3471 #ifdef TEST_QUERY_LEVELS
3472         }
3473 #endif
3474 #ifdef TEST_SET_LEVELS
3475         }
3476 #endif
3477         } /* fields present */
3478         } /* nonzeros */
3479         } /* levels */
3480
3481 #undef TEST_SET_LEVELS
3482 #undef TEST_QUERY_LEVELS
3483
3484         talloc_free(np);
3485
3486         return ret;
3487 }
3488
3489 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3490                                            struct torture_context *tctx,
3491                                            struct policy_handle *handle,
3492                                            uint32_t *badpwdcount)
3493 {
3494         union samr_UserInfo *info;
3495         struct samr_QueryUserInfo r;
3496
3497         r.in.user_handle = handle;
3498         r.in.level = 3;
3499         r.out.info = &info;
3500
3501         torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3502
3503         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3504                 "failed to query userinfo");
3505         torture_assert_ntstatus_ok(tctx, r.out.result,
3506                 "failed to query userinfo");
3507
3508         *badpwdcount = info->info3.bad_password_count;
3509
3510         torture_comment(tctx, " (bad password count: %d)\n", *badpwdcount);
3511
3512         return true;
3513 }
3514
3515 static bool test_SetUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3516                                         struct torture_context *tctx,
3517                                         struct policy_handle *user_handle,
3518                                         uint32_t acct_flags)
3519 {
3520         struct samr_SetUserInfo r;
3521         union samr_UserInfo user_info;
3522
3523         torture_comment(tctx, "Testing SetUserInfo level 16\n");
3524
3525         user_info.info16.acct_flags = acct_flags;
3526
3527         r.in.user_handle = user_handle;
3528         r.in.level = 16;
3529         r.in.info = &user_info;
3530
3531         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &r),
3532                 "failed to set account flags");
3533         torture_assert_ntstatus_ok(tctx, r.out.result,
3534                 "failed to set account flags");
3535
3536         return true;
3537 }
3538
3539 static bool test_reset_badpwdcount(struct dcerpc_pipe *p,
3540                                    struct torture_context *tctx,
3541                                    struct policy_handle *user_handle,
3542                                    uint32_t acct_flags,
3543                                    char **password)
3544 {
3545         struct dcerpc_binding_handle *b = p->binding_handle;
3546
3547         torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3548                 "failed to set password");
3549
3550         torture_comment(tctx, "Testing SetUserInfo level 16 (enable account)\n");
3551
3552         torture_assert(tctx,
3553                        test_SetUserInfo_acct_flags(b, tctx, user_handle,
3554                                                    acct_flags & ~ACB_DISABLED),
3555                        "failed to enable user");
3556
3557         torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3558                 "failed to set password");
3559
3560         return true;
3561 }
3562
3563 static bool test_SetDomainInfo(struct dcerpc_binding_handle *b,
3564                                struct torture_context *tctx,
3565                                struct policy_handle *domain_handle,
3566                                enum samr_DomainInfoClass level,
3567                                union samr_DomainInfo *info)
3568 {
3569         struct samr_SetDomainInfo r;
3570
3571         r.in.domain_handle = domain_handle;
3572         r.in.level = level;
3573         r.in.info = info;
3574
3575         torture_assert_ntstatus_ok(tctx,
3576                                    dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3577                                    "failed to set domain info");
3578         torture_assert_ntstatus_ok(tctx, r.out.result,
3579                                    "failed to set domain info");
3580
3581         return true;
3582 }
3583
3584 static bool test_SetDomainInfo_ntstatus(struct dcerpc_binding_handle *b,
3585                                         struct torture_context *tctx,
3586                                         struct policy_handle *domain_handle,
3587                                         enum samr_DomainInfoClass level,
3588                                         union samr_DomainInfo *info,
3589                                         NTSTATUS expected)
3590 {
3591         struct samr_SetDomainInfo r;
3592
3593         r.in.domain_handle = domain_handle;
3594         r.in.level = level;
3595         r.in.info = info;
3596
3597         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &r),
3598                 "SetDomainInfo failed");
3599         torture_assert_ntstatus_equal(tctx, r.out.result, expected, "");
3600
3601         return true;
3602 }
3603
3604 static bool test_QueryDomainInfo2_level(struct dcerpc_binding_handle *b,
3605                                         struct torture_context *tctx,
3606                                         struct policy_handle *domain_handle,
3607                                         enum samr_DomainInfoClass level,
3608                                         union samr_DomainInfo **q_info)
3609 {
3610         struct samr_QueryDomainInfo2 r;
3611
3612         r.in.domain_handle = domain_handle;
3613         r.in.level = level;
3614         r.out.info = q_info;
3615
3616         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
3617                 "failed to query domain info");
3618         torture_assert_ntstatus_ok(tctx, r.out.result,
3619                 "failed to query domain info");
3620
3621         return true;
3622 }
3623
3624 static bool test_Password_badpwdcount(struct dcerpc_pipe *p,
3625                                       struct dcerpc_pipe *np,
3626                                       struct torture_context *tctx,
3627                                       uint32_t acct_flags,
3628                                       const char *acct_name,
3629                                       struct policy_handle *domain_handle,
3630                                       struct policy_handle *user_handle,
3631                                       char **password,
3632                                       struct cli_credentials *machine_credentials,
3633                                       const char *comment,
3634                                       bool disable,
3635                                       bool interactive,
3636                                       NTSTATUS expected_success_status,
3637                                       struct samr_DomInfo1 *info1,
3638                                       struct samr_DomInfo12 *info12)
3639 {
3640         union samr_DomainInfo info;
3641         char **passwords;
3642         int i;
3643         uint32_t badpwdcount, tmp;
3644         uint32_t password_history_length = 12;
3645         uint32_t lockout_threshold = 15;
3646         struct dcerpc_binding_handle *b = p->binding_handle;
3647
3648         torture_comment(tctx, "\nTesting bad pwd count with: %s\n", comment);
3649
3650         torture_assert(tctx, password_history_length < lockout_threshold,
3651                 "password history length needs to be smaller than account lockout threshold for this test");
3652
3653
3654         /* set policies */
3655
3656         info.info1 = *info1;
3657         info.info1.password_history_length = password_history_length;
3658
3659         torture_assert(tctx,
3660                        test_SetDomainInfo(b, tctx, domain_handle,
3661                                           DomainPasswordInformation, &info),
3662                        "failed to set password history length");
3663
3664         info.info12 = *info12;
3665         info.info12.lockout_threshold = lockout_threshold;
3666
3667         torture_assert(tctx,
3668                        test_SetDomainInfo(b, tctx, domain_handle,
3669                                           DomainLockoutInformation, &info),
3670                        "failed to set lockout threshold");
3671
3672         /* reset bad pwd count */
3673
3674         torture_assert(tctx,
3675                 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
3676
3677
3678         /* enable or disable account */
3679         if (disable) {
3680                 torture_assert(tctx,
3681                                test_SetUserInfo_acct_flags(b, tctx, user_handle,
3682                                                 acct_flags | ACB_DISABLED),
3683                                "failed to disable user");
3684         } else {
3685                 torture_assert(tctx,
3686                                test_SetUserInfo_acct_flags(b, tctx, user_handle,
3687                                                 acct_flags & ~ACB_DISABLED),
3688                                "failed to enable user");
3689         }
3690
3691
3692         /* setup password history */
3693
3694         passwords = talloc_array(tctx, char *, password_history_length);
3695
3696         for (i=0; i < password_history_length; i++) {
3697
3698                 torture_assert(tctx, test_SetUserPass(p, tctx, user_handle, password),
3699                         "failed to set password");
3700                 passwords[i] = talloc_strdup(tctx, *password);
3701
3702                 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3703                                               acct_name, passwords[i],
3704                                               expected_success_status, interactive)) {
3705                         torture_fail(tctx, "failed to auth with latest password");
3706                 }
3707
3708                 torture_assert(tctx,
3709                         test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3710
3711                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3712         }
3713
3714
3715         /* test with wrong password */
3716
3717         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3718                                       acct_name, "random_crap",
3719                                       NT_STATUS_WRONG_PASSWORD, interactive)) {
3720                 torture_fail(tctx, "succeeded to authenticate with wrong password");
3721         }
3722
3723         torture_assert(tctx,
3724                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3725
3726         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3727
3728
3729         /* test with latest good password */
3730
3731         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
3732                                       passwords[password_history_length-1],
3733                                       expected_success_status, interactive)) {
3734                 torture_fail(tctx, "succeeded to authenticate with wrong password");
3735         }
3736
3737         torture_assert(tctx,
3738                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3739
3740         if (disable) {
3741                 torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
3742         } else {
3743                 /* only enabled accounts get the bad pwd count reset upon
3744                  * successful logon */
3745                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3746         }
3747
3748         tmp = badpwdcount;
3749
3750
3751         /* test password history */
3752
3753         for (i=0; i < password_history_length; i++) {
3754
3755                 torture_comment(tctx, "Testing bad password count behavior with "
3756                                       "password #%d of #%d\n", i, password_history_length);
3757
3758                 /* - network samlogon will succeed auth and not
3759                  *   increase badpwdcount for 2 last entries
3760                  * - interactive samlogon only for the last one */
3761
3762                 if (i == password_history_length - 1 ||
3763                     (i == password_history_length - 2 && !interactive)) {
3764
3765                         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3766                                                       acct_name, passwords[i],
3767                                                       expected_success_status, interactive)) {
3768                                 torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3769                         }
3770
3771                         torture_assert(tctx,
3772                                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3773
3774                         if (disable) {
3775                                 /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE* for pwd history entry %d\n", i); */
3776                                 torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3777                         } else {
3778                                 /* torture_comment(tctx, "expecting bad pwd count to be 0 for pwd history entry %d\n", i); */
3779                                 torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
3780                         }
3781
3782                         tmp = badpwdcount;
3783
3784                         continue;
3785                 }
3786
3787                 if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
3788                                               acct_name, passwords[i],
3789                                               NT_STATUS_WRONG_PASSWORD, interactive)) {
3790                         torture_fail(tctx, talloc_asprintf(tctx, "succeeded to authenticate with old password (#%d of #%d in history)", i, password_history_length));
3791                 }
3792
3793                 torture_assert(tctx,
3794                         test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
3795
3796                 /* - network samlogon will fail auth but not increase
3797                  *   badpwdcount for 3rd last entry
3798                  * - interactive samlogon for 3rd and 2nd last entry */
3799
3800                 if (i == password_history_length - 3 ||
3801                     (i == password_history_length - 2 && interactive)) {
3802                         /* torture_comment(tctx, "expecting bad pwd count to *NOT INCREASE * by one for pwd history entry %d\n", i); */
3803                         torture_assert_int_equal(tctx, badpwdcount, tmp, "unexpected badpwdcount");
3804                 } else {
3805                         /* torture_comment(tctx, "expecting bad pwd count to increase by one for pwd history entry %d\n", i); */
3806                         torture_assert_int_equal(tctx, badpwdcount, tmp + 1, "unexpected badpwdcount");
3807                 }
3808
3809                 tmp = badpwdcount;
3810         }
3811
3812         return true;
3813 }
3814
3815 static bool test_Password_badpwdcount_wrap(struct dcerpc_pipe *p,
3816                                            struct torture_context *tctx,
3817                                            uint32_t acct_flags,
3818                                            const char *acct_name,
3819                                            struct policy_handle *domain_handle,
3820                                            struct policy_handle *user_handle,
3821                                            char **password,
3822                                            struct cli_credentials *machine_credentials)
3823 {
3824         union samr_DomainInfo *q_info, s_info;
3825         struct samr_DomInfo1 info1, _info1;
3826         struct samr_DomInfo12 info12, _info12;
3827         bool ret = true;
3828         struct dcerpc_binding_handle *b = p->binding_handle;
3829         struct dcerpc_pipe *np;
3830         int i;
3831
3832         struct {
3833                 const char *comment;
3834                 bool disabled;
3835                 bool interactive;
3836                 NTSTATUS expected_success_status;
3837         } creds[] = {
3838                 {
3839                         .comment                = "network logon (disabled account)",
3840                         .disabled               = true,
3841                         .interactive            = false,
3842                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3843                 },
3844                 {
3845                         .comment                = "network logon (enabled account)",
3846                         .disabled               = false,
3847                         .interactive            = false,
3848                         .expected_success_status= NT_STATUS_OK
3849                 },
3850                 {
3851                         .comment                = "interactive logon (disabled account)",
3852                         .disabled               = true,
3853                         .interactive            = true,
3854                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
3855                 },
3856                 {
3857                         .comment                = "interactive logon (enabled account)",
3858                         .disabled               = false,
3859                         .interactive            = true,
3860                         .expected_success_status= NT_STATUS_OK
3861                 },
3862         };
3863
3864         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3865
3866         /* backup old policies */
3867
3868         torture_assert(tctx,
3869                 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3870                                             DomainPasswordInformation, &q_info),
3871                 "failed to query domain info level 1");
3872
3873         info1 = q_info->info1;
3874         _info1 = info1;
3875
3876         torture_assert(tctx,
3877                 test_QueryDomainInfo2_level(b, tctx, domain_handle,
3878                                             DomainLockoutInformation, &q_info),
3879                 "failed to query domain info level 12");
3880
3881         info12 = q_info->info12;
3882         _info12 = info12;
3883
3884         /* run tests */
3885
3886         for (i=0; i < ARRAY_SIZE(creds); i++) {
3887
3888                 /* skip trust tests for now */
3889                 if (acct_flags & ACB_WSTRUST ||
3890                     acct_flags & ACB_SVRTRUST ||
3891                     acct_flags & ACB_DOMTRUST) {
3892                         continue;
3893                 }
3894
3895                 ret &= test_Password_badpwdcount(p, np, tctx, acct_flags, acct_name,
3896                                                  domain_handle, user_handle, password,
3897                                                  machine_credentials,
3898                                                  creds[i].comment,
3899                                                  creds[i].disabled,
3900                                                  creds[i].interactive,
3901                                                  creds[i].expected_success_status,
3902                                                  &_info1, &_info12);
3903                 if (!ret) {
3904                         torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
3905                 } else {
3906                         torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
3907                 }
3908         }
3909
3910         /* restore policies */
3911
3912         s_info.info1 = info1;
3913
3914         torture_assert(tctx,
3915                        test_SetDomainInfo(b, tctx, domain_handle,
3916                                           DomainPasswordInformation, &s_info),
3917                        "failed to set password information");
3918
3919         s_info.info12 = info12;
3920
3921         torture_assert(tctx,
3922                        test_SetDomainInfo(b, tctx, domain_handle,
3923                                           DomainLockoutInformation, &s_info),
3924                        "failed to set lockout information");
3925
3926         return ret;
3927 }
3928
3929 static bool test_QueryUserInfo_acct_flags(struct dcerpc_binding_handle *b,
3930                                           struct torture_context *tctx,
3931                                           struct policy_handle *handle,
3932                                           uint32_t *acct_flags)
3933 {
3934         union samr_UserInfo *info;
3935         struct samr_QueryUserInfo r;
3936
3937         r.in.user_handle = handle;
3938         r.in.level = 16;
3939         r.out.info = &info;
3940
3941         torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3942
3943         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3944                 "failed to query userinfo");
3945         torture_assert_ntstatus_ok(tctx, r.out.result,
3946                 "failed to query userinfo");
3947
3948         *acct_flags = info->info16.acct_flags;
3949
3950         torture_comment(tctx, "  (acct_flags: 0x%08x)\n", *acct_flags);
3951
3952         return true;
3953 }
3954
3955 static bool test_Password_lockout(struct dcerpc_pipe *p,
3956                                   struct dcerpc_pipe *np,
3957                                   struct torture_context *tctx,
3958                                   uint32_t acct_flags,
3959                                   const char *acct_name,
3960                                   struct policy_handle *domain_handle,
3961                                   struct policy_handle *user_handle,
3962                                   char **password,
3963                                   struct cli_credentials *machine_credentials,
3964                                   const char *comment,
3965                                   bool disable,
3966                                   bool interactive,
3967                                   NTSTATUS expected_success_status,
3968                                   struct samr_DomInfo1 *info1,
3969                                   struct samr_DomInfo12 *info12)
3970 {
3971         union samr_DomainInfo info;
3972         uint32_t badpwdcount;
3973         uint32_t password_history_length = 1;
3974         uint64_t lockout_threshold = 1;
3975         uint32_t lockout_seconds = 5;
3976         uint64_t delta_time_factor = 10 * 1000 * 1000;
3977         struct dcerpc_binding_handle *b = p->binding_handle;
3978
3979         torture_comment(tctx, "\nTesting account lockout: %s\n", comment);
3980
3981         /* set policies */
3982
3983         info.info1 = *info1;
3984
3985         torture_comment(tctx, "setting password history length.\n");
3986         info.info1.password_history_length = password_history_length;
3987
3988         torture_assert(tctx,
3989                        test_SetDomainInfo(b, tctx, domain_handle,
3990                                           DomainPasswordInformation, &info),
3991                        "failed to set password history length");
3992
3993         info.info12 = *info12;
3994         info.info12.lockout_threshold = lockout_threshold;
3995
3996         /* set lockout duration < lockout window: should fail */
3997         info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
3998         info.info12.lockout_window = ~((lockout_seconds + 1) * delta_time_factor);
3999
4000         torture_assert(tctx,
4001                 test_SetDomainInfo_ntstatus(b, tctx, domain_handle,
4002                                             DomainLockoutInformation, &info,
4003                                             NT_STATUS_INVALID_PARAMETER),
4004                 "setting lockout duration < lockout window gave unexpected result");
4005
4006         info.info12.lockout_duration = 0;
4007         info.info12.lockout_window = 0;
4008
4009         torture_assert(tctx,
4010                        test_SetDomainInfo(b, tctx, domain_handle,
4011                                           DomainLockoutInformation, &info),
4012                        "failed to set lockout window and duration to 0");
4013
4014
4015         /* set lockout duration of 5 seconds */
4016         info.info12.lockout_duration = ~(lockout_seconds * delta_time_factor);
4017         info.info12.lockout_window = ~(lockout_seconds * delta_time_factor);
4018
4019         torture_assert(tctx,
4020                        test_SetDomainInfo(b, tctx, domain_handle,
4021                                           DomainLockoutInformation, &info),
4022                        "failed to set lockout window and duration to 5 seconds");
4023
4024         /* reset bad pwd count */
4025
4026         torture_assert(tctx,
4027                 test_reset_badpwdcount(p, tctx, user_handle, acct_flags, password), "");
4028
4029
4030         /* enable or disable account */
4031
4032         if (disable) {
4033                 torture_assert(tctx,
4034                                test_SetUserInfo_acct_flags(b, tctx, user_handle,
4035                                                 acct_flags | ACB_DISABLED),
4036                                "failed to disable user");
4037         } else {
4038                 torture_assert(tctx,
4039                                test_SetUserInfo_acct_flags(b, tctx, user_handle,
4040                                                 acct_flags & ~ACB_DISABLED),
4041                                "failed to enable user");
4042         }
4043
4044
4045         /* test logon with right password */
4046
4047         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4048                                       acct_name, *password,
4049                                       expected_success_status, interactive)) {
4050                 torture_fail(tctx, "failed to auth with latest password");
4051         }
4052
4053         torture_assert(tctx,
4054                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4055         torture_assert_int_equal(tctx, badpwdcount, 0, "expected badpwdcount to be 0");
4056
4057
4058         /* test with wrong password ==> lockout */
4059
4060         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4061                                       acct_name, "random_crap",
4062                                       NT_STATUS_WRONG_PASSWORD, interactive)) {
4063                 torture_fail(tctx, "succeeded to authenticate with wrong password");
4064         }
4065
4066         torture_assert(tctx,
4067                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4068         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4069
4070         torture_assert(tctx,
4071                 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4072         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4073                                  "expected account to be locked");
4074
4075
4076         /* test with good password */
4077
4078         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4079                                      *password,
4080                                      NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4081         {
4082                 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4083         }
4084
4085         /* bad pwd count should not get updated */
4086         torture_assert(tctx,
4087                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4088         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4089
4090         /* curiously, windows does _not_ set the autlock flag */
4091         torture_assert(tctx,
4092                 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4093         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4094                                  "expected account to be locked");
4095
4096
4097         /* with bad password */
4098
4099         if (!test_SamLogon_with_creds(tctx, np, machine_credentials,
4100                                       acct_name, "random_crap2",
4101                                       NT_STATUS_ACCOUNT_LOCKED_OUT, interactive))
4102         {
4103                 torture_fail(tctx, "authenticate did not return NT_STATUS_ACCOUNT_LOCKED_OUT");
4104         }
4105
4106         /* bad pwd count should not get updated */
4107         torture_assert(tctx,
4108                 test_QueryUserInfo_badpwdcount(b, tctx, user_handle, &badpwdcount), "");
4109         torture_assert_int_equal(tctx, badpwdcount, 1, "expected badpwdcount to be 1");
4110
4111         /* curiously, windows does _not_ set the autlock flag */
4112         torture_assert(tctx,
4113                 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4114         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4115                                  "expected account to be locked");
4116
4117
4118         /* let lockout duration expire ==> unlock */
4119
4120         torture_comment(tctx, "let lockout duration expire...\n");
4121         sleep(lockout_seconds + 1);
4122
4123         if (!test_SamLogon_with_creds(tctx, np, machine_credentials, acct_name,
4124                                      *password,
4125                                      expected_success_status, interactive))
4126         {
4127                 torture_fail(tctx, "failed to authenticate after lockout expired");
4128         }
4129
4130         torture_assert(tctx,
4131                 test_QueryUserInfo_acct_flags(b, tctx, user_handle, &acct_flags), "");
4132         torture_assert_int_equal(tctx, acct_flags & ACB_AUTOLOCK, 0,
4133                                  "expected account not to be locked");
4134
4135         return true;
4136 }
4137
4138 static bool test_Password_lockout_wrap(struct dcerpc_pipe *p,
4139                                        struct torture_context *tctx,
4140                                        uint32_t acct_flags,
4141                                        const char *acct_name,
4142                                        struct policy_handle *domain_handle,
4143                                        struct policy_handle *user_handle,
4144                                        char **password,
4145                                        struct cli_credentials *machine_credentials)
4146 {
4147         union samr_DomainInfo *q_info, s_info;
4148         struct samr_DomInfo1 info1, _info1;
4149         struct samr_DomInfo12 info12, _info12;
4150         bool ret = true;
4151         struct dcerpc_binding_handle *b = p->binding_handle;
4152         struct dcerpc_pipe *np;
4153         int i;
4154
4155         struct {
4156                 const char *comment;
4157                 bool disabled;
4158                 bool interactive;
4159                 NTSTATUS expected_success_status;
4160         } creds[] = {
4161                 {
4162                         .comment                = "network logon (disabled account)",
4163                         .disabled               = true,
4164                         .interactive            = false,
4165                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4166                 },
4167                 {
4168                         .comment                = "network logon (enabled account)",
4169                         .disabled               = false,
4170                         .interactive            = false,
4171                         .expected_success_status= NT_STATUS_OK
4172                 },
4173                 {
4174                         .comment                = "interactive logon (disabled account)",
4175                         .disabled               = true,
4176                         .interactive            = true,
4177                         .expected_success_status= NT_STATUS_ACCOUNT_DISABLED
4178                 },
4179                 {
4180                         .comment                = "interactive logon (enabled account)",
4181                         .disabled               = false,
4182                         .interactive            = true,
4183                         .expected_success_status= NT_STATUS_OK
4184                 },
4185         };
4186
4187         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
4188
4189         /* backup old policies */
4190
4191         torture_assert(tctx,
4192                 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4193                                             DomainPasswordInformation, &q_info),
4194                 "failed to query domain info level 1");
4195
4196         info1 = q_info->info1;
4197         _info1 = info1;
4198
4199         torture_assert(tctx,
4200                 test_QueryDomainInfo2_level(b, tctx, domain_handle,
4201                                             DomainLockoutInformation, &q_info),
4202                 "failed to query domain info level 12");
4203
4204         info12 = q_info->info12;
4205         _info12 = info12;
4206
4207         /* run tests */
4208
4209         for (i=0; i < ARRAY_SIZE(creds); i++) {
4210
4211                 /* skip trust tests for now */
4212                 if (acct_flags & ACB_WSTRUST ||
4213                     acct_flags & ACB_SVRTRUST ||
4214                     acct_flags & ACB_DOMTRUST) {
4215                         continue;
4216                 }
4217
4218                 ret &= test_Password_lockout(p, np, tctx, acct_flags, acct_name,
4219                                              domain_handle, user_handle, password,
4220                                              machine_credentials,
4221                                              creds[i].comment,
4222                                              creds[i].disabled,
4223                                              creds[i].interactive,
4224                                              creds[i].expected_success_status,
4225                                              &_info1, &_info12);
4226                 if (!ret) {
4227                         torture_warning(tctx, "TEST #%d (%s) failed\n", i, creds[i].comment);
4228                 } else {
4229                         torture_comment(tctx, "TEST #%d (%s) succeeded\n", i, creds[i].comment);
4230                 }
4231         }
4232
4233         /* restore policies */
4234
4235         s_info.info1 = info1;
4236
4237         torture_assert(tctx,
4238                        test_SetDomainInfo(b, tctx, domain_handle,
4239                                           DomainPasswordInformation, &s_info),
4240                        "failed to set password information");
4241
4242         s_info.info12 = info12;
4243
4244         torture_assert(tctx,
4245                        test_SetDomainInfo(b, tctx, domain_handle,
4246                                           DomainLockoutInformation, &s_info),
4247                        "failed to set lockout information");
4248
4249         return ret;
4250 }
4251
4252 static bool test_DeleteUser_with_privs(struct dcerpc_pipe *p,
4253                                        struct dcerpc_pipe *lp,
4254                                        struct torture_context *tctx,
4255                                        struct policy_handle *domain_handle,
4256                                        struct policy_handle *lsa_handle,
4257                                        struct policy_handle *user_handle,
4258                                        const struct dom_sid *domain_sid,
4259                                        uint32_t rid,
4260                                        struct cli_credentials *machine_credentials)
4261 {
4262         bool ret = true;
4263         struct dcerpc_binding_handle *b = p->binding_handle;
4264         struct dcerpc_binding_handle *lb = lp->binding_handle;
4265
4266         struct policy_handle lsa_acct_handle;
4267         struct dom_sid *user_sid;
4268
4269         user_sid = dom_sid_add_rid(tctx, domain_sid, rid);
4270
4271         {
4272                 struct lsa_EnumAccountRights r;
4273                 struct lsa_RightSet rights;
4274
4275                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4276
4277                 r.in.handle = lsa_handle;
4278                 r.in.sid = user_sid;
4279                 r.out.rights = &rights;
4280
4281                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4282                         "lsa_EnumAccountRights failed");
4283                 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4284                         "Expected enum rights for account to fail");
4285         }
4286
4287         {
4288                 struct lsa_RightSet rights;
4289                 struct lsa_StringLarge names[2];
4290                 struct lsa_AddAccountRights r;
4291
4292                 torture_comment(tctx, "Testing LSA AddAccountRights\n");
4293
4294                 init_lsa_StringLarge(&names[0], "SeMachineAccountPrivilege");
4295                 init_lsa_StringLarge(&names[1], NULL);
4296
4297                 rights.count = 1;
4298                 rights.names = names;
4299
4300                 r.in.handle = lsa_handle;
4301                 r.in.sid = user_sid;
4302                 r.in.rights = &rights;
4303
4304                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_AddAccountRights_r(lb, tctx, &r),
4305                         "lsa_AddAccountRights failed");
4306                 torture_assert_ntstatus_ok(tctx, r.out.result,
4307                         "Failed to add privileges");
4308         }
4309
4310         {
4311                 struct lsa_EnumAccounts r;
4312                 uint32_t resume_handle = 0;
4313                 struct lsa_SidArray lsa_sid_array;
4314                 int i;
4315                 bool found_sid = false;
4316
4317                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4318
4319                 r.in.handle = lsa_handle;
4320                 r.in.num_entries = 0x1000;
4321                 r.in.resume_handle = &resume_handle;
4322                 r.out.sids = &lsa_sid_array;
4323                 r.out.resume_handle = &resume_handle;
4324
4325                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4326                         "lsa_EnumAccounts failed");
4327                 torture_assert_ntstatus_ok(tctx, r.out.result,
4328                         "Failed to enum accounts");
4329
4330                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4331                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4332                                 found_sid = true;
4333                         }
4334                 }
4335
4336                 torture_assert(tctx, found_sid,
4337                         "failed to list privileged account");
4338         }
4339
4340         {
4341                 struct lsa_EnumAccountRights r;
4342                 struct lsa_RightSet user_rights;
4343
4344                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4345
4346                 r.in.handle = lsa_handle;
4347                 r.in.sid = user_sid;
4348                 r.out.rights = &user_rights;
4349
4350                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4351                         "lsa_EnumAccountRights failed");
4352                 torture_assert_ntstatus_ok(tctx, r.out.result,
4353                         "Failed to enum rights for account");
4354
4355                 if (user_rights.count < 1) {
4356                         torture_warning(tctx, "failed to find newly added rights");
4357                         return false;
4358                 }
4359         }
4360
4361         {
4362                 struct lsa_OpenAccount r;
4363
4364                 torture_comment(tctx, "Testing LSA OpenAccount\n");
4365
4366                 r.in.handle = lsa_handle;
4367                 r.in.sid = user_sid;
4368                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4369                 r.out.acct_handle = &lsa_acct_handle;
4370
4371                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4372                         "lsa_OpenAccount failed");
4373                 torture_assert_ntstatus_ok(tctx, r.out.result,
4374                         "Failed to open lsa account");
4375         }
4376
4377         {
4378                 struct lsa_GetSystemAccessAccount r;
4379                 uint32_t access_mask;
4380
4381                 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4382
4383                 r.in.handle = &lsa_acct_handle;
4384                 r.out.access_mask = &access_mask;
4385
4386                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4387                         "lsa_GetSystemAccessAccount failed");
4388                 torture_assert_ntstatus_ok(tctx, r.out.result,
4389                         "Failed to get lsa system access account");
4390         }
4391
4392         {
4393                 struct lsa_Close r;
4394
4395                 torture_comment(tctx, "Testing LSA Close\n");
4396
4397                 r.in.handle = &lsa_acct_handle;
4398                 r.out.handle = &lsa_acct_handle;
4399
4400                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_Close_r(lb, tctx, &r),
4401                         "lsa_Close failed");
4402                 torture_assert_ntstatus_ok(tctx, r.out.result,
4403                         "Failed to close lsa");
4404         }
4405
4406         {
4407                 struct samr_DeleteUser r;
4408
4409                 torture_comment(tctx, "Testing SAMR DeleteUser\n");
4410
4411                 r.in.user_handle = user_handle;
4412                 r.out.user_handle = user_handle;
4413
4414                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &r),
4415                         "DeleteUser failed");
4416                 torture_assert_ntstatus_ok(tctx, r.out.result,
4417                         "DeleteUser failed");
4418         }
4419
4420         {
4421                 struct lsa_EnumAccounts r;
4422                 uint32_t resume_handle = 0;
4423                 struct lsa_SidArray lsa_sid_array;
4424                 int i;
4425                 bool found_sid = false;
4426
4427                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4428
4429                 r.in.handle = lsa_handle;
4430                 r.in.num_entries = 0x1000;
4431                 r.in.resume_handle = &resume_handle;
4432                 r.out.sids = &lsa_sid_array;
4433                 r.out.resume_handle = &resume_handle;
4434
4435                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4436                         "lsa_EnumAccounts failed");
4437                 torture_assert_ntstatus_ok(tctx, r.out.result,
4438                         "Failed to enum accounts");
4439
4440                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4441                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4442                                 found_sid = true;
4443                         }
4444                 }
4445
4446                 torture_assert(tctx, found_sid,
4447                         "failed to list privileged account");
4448         }
4449
4450         {
4451                 struct lsa_EnumAccountRights r;
4452                 struct lsa_RightSet user_rights;
4453
4454                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4455
4456                 r.in.handle = lsa_handle;
4457                 r.in.sid = user_sid;
4458                 r.out.rights = &user_rights;
4459
4460                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4461                         "lsa_EnumAccountRights failed");
4462                 torture_assert_ntstatus_ok(tctx, r.out.result,
4463                         "Failed to enum rights for account");
4464
4465                 if (user_rights.count < 1) {
4466                         torture_warning(tctx, "failed to find newly added rights");
4467                         return false;
4468                 }
4469         }
4470
4471         {
4472                 struct lsa_OpenAccount r;
4473
4474                 torture_comment(tctx, "Testing LSA OpenAccount\n");
4475
4476                 r.in.handle = lsa_handle;
4477                 r.in.sid = user_sid;
4478                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4479                 r.out.acct_handle = &lsa_acct_handle;
4480
4481                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_OpenAccount_r(lb, tctx, &r),
4482                         "lsa_OpenAccount failed");
4483                 torture_assert_ntstatus_ok(tctx, r.out.result,
4484                         "Failed to open lsa account");
4485         }
4486
4487         {
4488                 struct lsa_GetSystemAccessAccount r;
4489                 uint32_t access_mask;
4490
4491                 torture_comment(tctx, "Testing LSA GetSystemAccessAccount\n");
4492
4493                 r.in.handle = &lsa_acct_handle;
4494                 r.out.access_mask = &access_mask;
4495
4496                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_GetSystemAccessAccount_r(lb, tctx, &r),
4497                         "lsa_GetSystemAccessAccount failed");
4498                 torture_assert_ntstatus_ok(tctx, r.out.result,
4499                         "Failed to get lsa system access account");
4500         }
4501
4502         {
4503                 struct lsa_DeleteObject r;
4504
4505                 torture_comment(tctx, "Testing LSA DeleteObject\n");
4506
4507                 r.in.handle = &lsa_acct_handle;
4508                 r.out.handle = &lsa_acct_handle;
4509
4510                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_DeleteObject_r(lb, tctx, &r),
4511                         "lsa_DeleteObject failed");
4512                 torture_assert_ntstatus_ok(tctx, r.out.result,
4513                         "Failed to delete object");
4514         }
4515
4516         {
4517                 struct lsa_EnumAccounts r;
4518                 uint32_t resume_handle = 0;
4519                 struct lsa_SidArray lsa_sid_array;
4520                 int i;
4521                 bool found_sid = false;
4522
4523                 torture_comment(tctx, "Testing LSA EnumAccounts\n");
4524
4525                 r.in.handle = lsa_handle;
4526                 r.in.num_entries = 0x1000;
4527                 r.in.resume_handle = &resume_handle;
4528                 r.out.sids = &lsa_sid_array;
4529                 r.out.resume_handle = &resume_handle;
4530
4531                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccounts_r(lb, tctx, &r),
4532                         "lsa_EnumAccounts failed");
4533                 torture_assert_ntstatus_ok(tctx, r.out.result,
4534                         "Failed to enum accounts");
4535
4536                 for (i=0; i < lsa_sid_array.num_sids; i++) {
4537                         if (dom_sid_equal(user_sid, lsa_sid_array.sids[i].sid)) {
4538                                 found_sid = true;
4539                         }
4540                 }
4541
4542                 torture_assert(tctx, !found_sid,
4543                         "should not have listed privileged account");
4544         }
4545
4546         {
4547                 struct lsa_EnumAccountRights r;
4548                 struct lsa_RightSet user_rights;
4549
4550                 torture_comment(tctx, "Testing LSA EnumAccountRights\n");
4551
4552                 r.in.handle = lsa_handle;
4553                 r.in.sid = user_sid;
4554                 r.out.rights = &user_rights;
4555
4556                 torture_assert_ntstatus_ok(tctx, dcerpc_lsa_EnumAccountRights_r(lb, tctx, &r),
4557                         "lsa_EnumAccountRights failed");
4558                 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND,
4559                         "Failed to enum rights for account");
4560         }
4561
4562         return ret;
4563 }
4564
4565 static bool test_user_ops(struct dcerpc_pipe *p,
4566                           struct torture_context *tctx,
4567                           struct policy_handle *user_handle,
4568                           struct policy_handle *domain_handle,
4569                           const struct dom_sid *domain_sid,
4570                           uint32_t base_acct_flags,
4571                           const char *base_acct_name, enum torture_samr_choice which_ops,
4572                           struct cli_credentials *machine_credentials)
4573 {
4574         char *password = NULL;
4575         struct samr_QueryUserInfo q;
4576         union samr_UserInfo *info;
4577         NTSTATUS status;
4578         struct dcerpc_binding_handle *b = p->binding_handle;
4579
4580         bool ret = true;
4581         int i;
4582         uint32_t rid;
4583         const uint32_t password_fields[] = {
4584                 SAMR_FIELD_NT_PASSWORD_PRESENT,
4585                 SAMR_FIELD_LM_PASSWORD_PRESENT,
4586                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
4587                 0
4588         };
4589
4590         status = test_LookupName(b, tctx, domain_handle, base_acct_name, &rid);
4591         if (!NT_STATUS_IS_OK(status)) {
4592                 ret = false;
4593         }
4594
4595         switch (which_ops) {
4596         case TORTURE_SAMR_USER_ATTRIBUTES:
4597                 if (!test_QuerySecurity(b, tctx, user_handle)) {
4598                         ret = false;
4599                 }
4600
4601                 if (!test_QueryUserInfo(b, tctx, user_handle)) {
4602                         ret = false;
4603                 }
4604
4605                 if (!test_QueryUserInfo2(b, tctx, user_handle)) {
4606                         ret = false;
4607                 }
4608
4609                 if (!test_SetUserInfo(b, tctx, user_handle, base_acct_flags,
4610                                       base_acct_name)) {
4611                         ret = false;
4612                 }
4613
4614                 if (!test_GetUserPwInfo(b, tctx, user_handle)) {
4615                         ret = false;
4616                 }
4617
4618                 if (!test_TestPrivateFunctionsUser(b, tctx, user_handle)) {
4619                         ret = false;
4620                 }
4621
4622                 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
4623                         ret = false;
4624                 }
4625                 break;
4626         case TORTURE_SAMR_PASSWORDS:
4627                 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
4628                         char simple_pass[9];
4629                         char *v = generate_random_str(tctx, 1);
4630
4631                         ZERO_STRUCT(simple_pass);
4632                         memset(simple_pass, *v, sizeof(simple_pass) - 1);
4633
4634                         torture_comment(tctx, "Testing machine account password policy rules\n");
4635
4636                         /* Workstation trust accounts don't seem to need to honour password quality policy */
4637                         if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4638                                 ret = false;
4639                         }
4640
4641                         if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
4642                                 ret = false;
4643                         }
4644
4645                         /* reset again, to allow another 'user' password change */
4646                         if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
4647                                 ret = false;
4648                         }
4649
4650                         /* Try a 'short' password */
4651                         if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
4652                                 ret = false;
4653                         }
4654
4655                         /* Try a compleatly random password */
4656                         if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
4657                                 ret = false;
4658                         }
4659                 }
4660
4661                 for (i = 0; password_fields[i]; i++) {
4662                         if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
4663                                 ret = false;
4664                         }
4665
4666                         /* check it was set right */
4667                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4668                                 ret = false;
4669                         }
4670                 }
4671
4672                 for (i = 0; password_fields[i]; i++) {
4673                         if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
4674                                 ret = false;
4675                         }
4676
4677                         /* check it was set right */
4678                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4679                                 ret = false;
4680                         }
4681                 }
4682
4683                 if (!test_SetUserPassEx(p, tctx, user_handle, false, &password)) {
4684                         ret = false;
4685                 }
4686
4687                 if (!test_ChangePassword(p, tctx, base_acct_name, domain_handle, &password)) {
4688                         ret = false;
4689                 }
4690
4691                 if (!test_SetUserPass_18(p, tctx, user_handle, &password)) {
4692                         ret = false;
4693                 }
4694
4695                 if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4696                         ret = false;
4697                 }
4698
4699                 for (i = 0; password_fields[i]; i++) {
4700
4701                         if (password_fields[i] == SAMR_FIELD_LM_PASSWORD_PRESENT) {
4702                                 /* we need to skip as that would break
4703                                  * the ChangePasswordUser3 verify */
4704                                 continue;
4705                         }
4706
4707                         if (!test_SetUserPass_21(p, tctx, user_handle, password_fields[i], &password)) {
4708                                 ret = false;
4709                         }
4710
4711                         /* check it was set right */
4712                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
4713                                 ret = false;
4714                         }
4715                 }
4716
4717                 q.in.user_handle = user_handle;
4718                 q.in.level = 5;
4719                 q.out.info = &info;
4720
4721                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
4722                         "QueryUserInfo failed");
4723                 if (!NT_STATUS_IS_OK(q.out.result)) {
4724                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
4725                                q.in.level, nt_errstr(q.out.result));
4726                         ret = false;
4727                 } else {
4728                         uint32_t expected_flags = (base_acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
4729                         if ((info->info5.acct_flags) != expected_flags) {
4730                                 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
4731                                        info->info5.acct_flags,
4732                                        expected_flags);
4733                                 /* FIXME: GD */
4734                                 if (!torture_setting_bool(tctx, "samba3", false)) {
4735                                         ret = false;
4736                                 }
4737                         }
4738                         if (info->info5.rid != rid) {
4739                                 torture_warning(tctx, "QueryUserInfo level 5 failed, it returned %u when we expected rid of %u\n",
4740                                        info->info5.rid, rid);
4741
4742                         }
4743                 }
4744
4745                 break;
4746
4747         case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
4748
4749                 /* test last password change timestamp behaviour */
4750                 if (!test_SetPassword_pwdlastset(p, tctx, base_acct_flags,
4751                                                  base_acct_name,
4752                                                  user_handle, &password,
4753                                                  machine_credentials)) {
4754                         ret = false;
4755                 }
4756
4757                 if (ret == true) {
4758                         torture_comment(tctx, "pwdLastSet test succeeded\n");
4759                 } else {
4760                         torture_warning(tctx, "pwdLastSet test failed\n");
4761                 }
4762
4763                 break;
4764
4765         case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
4766
4767                 /* test bad pwd count change behaviour */
4768                 if (!test_Password_badpwdcount_wrap(p, tctx, base_acct_flags,
4769                                                     base_acct_name,
4770                                                     domain_handle,
4771                                                     user_handle, &password,
4772                                                     machine_credentials)) {
4773                         ret = false;
4774                 }
4775
4776                 if (ret == true) {
4777                         torture_comment(tctx, "badPwdCount test succeeded\n");
4778                 } else {
4779                         torture_warning(tctx, "badPwdCount test failed\n");
4780                 }
4781
4782                 break;
4783
4784         case TORTURE_SAMR_PASSWORDS_LOCKOUT:
4785
4786                 if (!test_Password_lockout_wrap(p, tctx, base_acct_flags,
4787                                                 base_acct_name,
4788                                                 domain_handle,
4789                                                 user_handle, &password,
4790                                                 machine_credentials))
4791                 {
4792                         ret = false;
4793                 }
4794
4795                 if (ret == true) {
4796                         torture_comment(tctx, "lockout test succeeded\n");
4797                 } else {
4798                         torture_warning(tctx, "lockout test failed\n");
4799                 }
4800
4801                 break;
4802
4803
4804         case TORTURE_SAMR_USER_PRIVILEGES: {
4805
4806                 struct dcerpc_pipe *lp;
4807                 struct policy_handle *lsa_handle;
4808                 struct dcerpc_binding_handle *lb;
4809
4810                 status = torture_rpc_connection(tctx, &lp, &ndr_table_lsarpc);
4811                 torture_assert_ntstatus_ok(tctx, status, "Failed to open LSA pipe");
4812                 lb = lp->binding_handle;
4813
4814                 if (!test_lsa_OpenPolicy2(lb, tctx, &lsa_handle)) {
4815                         ret = false;
4816                 }
4817
4818                 if (!test_DeleteUser_with_privs(p, lp, tctx,
4819                                                 domain_handle, lsa_handle, user_handle,
4820                                                 domain_sid, rid,
4821                                                 machine_credentials)) {
4822                         ret = false;
4823                 }
4824
4825                 if (!test_lsa_Close(lb, tctx, lsa_handle)) {
4826                         ret = false;
4827                 }
4828
4829                 if (!ret) {
4830                         torture_warning(tctx, "privileged user delete test failed\n");
4831                 }
4832
4833                 break;
4834         }
4835         case TORTURE_SAMR_OTHER:
4836         case TORTURE_SAMR_MANY_ACCOUNTS:
4837         case TORTURE_SAMR_MANY_GROUPS:
4838         case TORTURE_SAMR_MANY_ALIASES:
4839                 /* We just need the account to exist */
4840                 break;
4841         }
4842         return ret;
4843 }
4844
4845 static bool test_alias_ops(struct dcerpc_binding_handle *b,
4846                            struct torture_context *tctx,
4847                            struct policy_handle *alias_handle,
4848                            const struct dom_sid *domain_sid)
4849 {
4850         bool ret = true;
4851
4852         if (!torture_setting_bool(tctx, "samba3", false)) {
4853                 if (!test_QuerySecurity(b, tctx, alias_handle)) {
4854                         ret = false;
4855                 }
4856         }
4857
4858         if (!test_QueryAliasInfo(b, tctx, alias_handle)) {
4859                 ret = false;
4860         }
4861
4862         if (!test_SetAliasInfo(b, tctx, alias_handle)) {
4863                 ret = false;
4864         }
4865
4866         if (!test_AddMemberToAlias(b, tctx, alias_handle, domain_sid)) {
4867                 ret = false;
4868         }
4869
4870         if (torture_setting_bool(tctx, "samba3", false) ||
4871             torture_setting_bool(tctx, "samba4", false)) {
4872                 torture_comment(tctx, "skipping MultipleMembers Alias tests against Samba\n");
4873                 return ret;
4874         }
4875
4876         if (!test_AddMultipleMembersToAlias(b, tctx, alias_handle)) {
4877                 ret = false;
4878         }
4879
4880         return ret;
4881 }
4882
4883
4884 static bool test_DeleteUser(struct dcerpc_binding_handle *b,
4885                             struct torture_context *tctx,
4886                             struct policy_handle *user_handle)
4887 {
4888         struct samr_DeleteUser d;
4889         torture_comment(tctx, "Testing DeleteUser\n");
4890
4891         d.in.user_handle = user_handle;
4892         d.out.user_handle = user_handle;
4893
4894         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
4895                 "DeleteUser failed");
4896         torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteUser");
4897
4898         return true;
4899 }
4900
4901 bool test_DeleteUser_byname(struct dcerpc_binding_handle *b,
4902                             struct torture_context *tctx,
4903                             struct policy_handle *handle, const char *name)
4904 {
4905         NTSTATUS status;
4906         struct samr_DeleteUser d;
4907         struct policy_handle user_handle;
4908         uint32_t rid;
4909
4910         status = test_LookupName(b, tctx, handle, name, &rid);
4911         if (!NT_STATUS_IS_OK(status)) {
4912                 goto failed;
4913         }
4914
4915         status = test_OpenUser_byname(b, tctx, handle, name, &user_handle);
4916         if (!NT_STATUS_IS_OK(status)) {
4917                 goto failed;
4918         }
4919
4920         d.in.user_handle = &user_handle;
4921         d.out.user_handle = &user_handle;
4922         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, tctx, &d),
4923                 "DeleteUser failed");
4924         if (!NT_STATUS_IS_OK(d.out.result)) {
4925                 status = d.out.result;
4926                 goto failed;
4927         }
4928
4929         return true;
4930
4931 failed:
4932         torture_warning(tctx, "DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
4933         return false;
4934 }
4935
4936
4937 static bool test_DeleteGroup_byname(struct dcerpc_binding_handle *b,
4938                                     struct torture_context *tctx,
4939                                     struct policy_handle *handle, const char *name)
4940 {
4941         NTSTATUS status;
4942         struct samr_OpenGroup r;
4943         struct samr_DeleteDomainGroup d;
4944         struct policy_handle group_handle;
4945         uint32_t rid;
4946
4947         status = test_LookupName(b, tctx, handle, name, &rid);
4948         if (!NT_STATUS_IS_OK(status)) {
4949                 goto failed;
4950         }
4951
4952         r.in.domain_handle = handle;
4953         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4954         r.in.rid = rid;
4955         r.out.group_handle = &group_handle;
4956         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
4957                 "OpenGroup failed");
4958         if (!NT_STATUS_IS_OK(r.out.result)) {
4959                 status = r.out.result;
4960                 goto failed;
4961         }
4962
4963         d.in.group_handle = &group_handle;
4964         d.out.group_handle = &group_handle;
4965         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
4966                 "DeleteDomainGroup failed");
4967         if (!NT_STATUS_IS_OK(d.out.result)) {
4968                 status = d.out.result;
4969                 goto failed;
4970         }
4971
4972         return true;
4973
4974 failed:
4975         torture_warning(tctx, "DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
4976         return false;
4977 }
4978
4979
4980 static bool test_DeleteAlias_byname(struct dcerpc_binding_handle *b,
4981                                     struct torture_context *tctx,
4982                                     struct policy_handle *domain_handle,
4983                                     const char *name)
4984 {
4985         NTSTATUS status;
4986         struct samr_OpenAlias r;
4987         struct samr_DeleteDomAlias d;
4988         struct policy_handle alias_handle;
4989         uint32_t rid;
4990
4991         torture_comment(tctx, "Testing DeleteAlias_byname\n");
4992
4993         status = test_LookupName(b, tctx, domain_handle, name, &rid);
4994         if (!NT_STATUS_IS_OK(status)) {
4995                 goto failed;
4996         }
4997
4998         r.in.domain_handle = domain_handle;
4999         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5000         r.in.rid = rid;
5001         r.out.alias_handle = &alias_handle;
5002         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5003                 "OpenAlias failed");
5004         if (!NT_STATUS_IS_OK(r.out.result)) {
5005                 status = r.out.result;
5006                 goto failed;
5007         }
5008
5009         d.in.alias_handle = &alias_handle;
5010         d.out.alias_handle = &alias_handle;
5011         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5012                 "DeleteDomAlias failed");
5013         if (!NT_STATUS_IS_OK(d.out.result)) {
5014                 status = d.out.result;
5015                 goto failed;
5016         }
5017
5018         return true;
5019
5020 failed:
5021         torture_warning(tctx, "DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
5022         return false;
5023 }
5024
5025 static bool test_DeleteAlias(struct dcerpc_binding_handle *b,
5026                              struct torture_context *tctx,
5027                              struct policy_handle *alias_handle)
5028 {
5029         struct samr_DeleteDomAlias d;
5030         bool ret = true;
5031
5032         torture_comment(tctx, "Testing DeleteAlias\n");
5033
5034         d.in.alias_handle = alias_handle;
5035         d.out.alias_handle = alias_handle;
5036
5037         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomAlias_r(b, tctx, &d),
5038                 "DeleteDomAlias failed");
5039         if (!NT_STATUS_IS_OK(d.out.result)) {
5040                 torture_warning(tctx, "DeleteAlias failed - %s\n", nt_errstr(d.out.result));
5041                 ret = false;
5042         }
5043
5044         return ret;
5045 }
5046
5047 static bool test_CreateAlias(struct dcerpc_binding_handle *b,
5048                              struct torture_context *tctx,
5049                              struct policy_handle *domain_handle,
5050                              const char *alias_name,
5051                              struct policy_handle *alias_handle,
5052                              const struct dom_sid *domain_sid,
5053                              bool test_alias)
5054 {
5055         struct samr_CreateDomAlias r;
5056         struct lsa_String name;
5057         uint32_t rid;
5058         bool ret = true;
5059
5060         init_lsa_String(&name, alias_name);
5061         r.in.domain_handle = domain_handle;
5062         r.in.alias_name = &name;
5063         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5064         r.out.alias_handle = alias_handle;
5065         r.out.rid = &rid;
5066
5067         torture_comment(tctx, "Testing CreateAlias (%s)\n", r.in.alias_name->string);
5068
5069         torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5070                 "CreateDomAlias failed");
5071
5072         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5073                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
5074                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.alias_name->string);
5075                         return true;
5076                 } else {
5077                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.alias_name->string,
5078                                nt_errstr(r.out.result));
5079                         return false;
5080                 }
5081         }
5082
5083         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ALIAS_EXISTS)) {
5084                 if (!test_DeleteAlias_byname(b, tctx, domain_handle, r.in.alias_name->string)) {
5085                         return false;
5086                 }
5087                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomAlias_r(b, tctx, &r),
5088                         "CreateDomAlias failed");
5089         }
5090
5091         if (!NT_STATUS_IS_OK(r.out.result)) {
5092                 torture_warning(tctx, "CreateAlias failed - %s\n", nt_errstr(r.out.result));
5093                 return false;
5094         }
5095
5096         if (!test_alias) {
5097                 return ret;
5098         }
5099
5100         if (!test_alias_ops(b, tctx, alias_handle, domain_sid)) {
5101                 ret = false;
5102         }
5103
5104         return ret;
5105 }
5106
5107 static bool test_ChangePassword(struct dcerpc_pipe *p,
5108                                 struct torture_context *tctx,
5109                                 const char *acct_name,
5110                                 struct policy_handle *domain_handle, char **password)
5111 {
5112         bool ret = true;
5113         struct dcerpc_binding_handle *b = p->binding_handle;
5114
5115         if (!*password) {
5116                 return false;
5117         }
5118
5119         if (!test_ChangePasswordUser(b, tctx, acct_name, domain_handle, password)) {
5120                 ret = false;
5121         }
5122
5123         if (!test_ChangePasswordUser2(p, tctx, acct_name, password, 0, true)) {
5124                 ret = false;
5125         }
5126
5127         if (!test_OemChangePasswordUser2(p, tctx, acct_name, domain_handle, password)) {
5128                 ret = false;
5129         }
5130
5131         /* test what happens when setting the old password again */
5132         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, *password, 0, true)) {
5133                 ret = false;
5134         }
5135
5136         {
5137                 char simple_pass[9];
5138                 char *v = generate_random_str(tctx, 1);
5139
5140                 ZERO_STRUCT(simple_pass);
5141                 memset(simple_pass, *v, sizeof(simple_pass) - 1);
5142
5143                 /* test what happens when picking a simple password */
5144                 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, simple_pass, 0, true)) {
5145                         ret = false;
5146                 }
5147         }
5148
5149         /* set samr_SetDomainInfo level 1 with min_length 5 */
5150         {
5151                 struct samr_QueryDomainInfo r;
5152                 union samr_DomainInfo *info = NULL;
5153                 struct samr_SetDomainInfo s;
5154                 uint16_t len_old, len;
5155                 uint32_t pwd_prop_old;
5156                 int64_t min_pwd_age_old;
5157
5158                 len = 5;
5159
5160                 r.in.domain_handle = domain_handle;
5161                 r.in.level = 1;
5162                 r.out.info = &info;
5163
5164                 torture_comment(tctx, "Testing samr_QueryDomainInfo level 1\n");
5165                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
5166                         "QueryDomainInfo failed");
5167                 if (!NT_STATUS_IS_OK(r.out.result)) {
5168                         return false;
5169                 }
5170
5171                 s.in.domain_handle = domain_handle;
5172                 s.in.level = 1;
5173                 s.in.info = info;
5174
5175                 /* remember the old min length, so we can reset it */
5176                 len_old = s.in.info->info1.min_password_length;
5177                 s.in.info->info1.min_password_length = len;
5178                 pwd_prop_old = s.in.info->info1.password_properties;
5179                 /* turn off password complexity checks for this test */
5180                 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
5181
5182                 min_pwd_age_old = s.in.info->info1.min_password_age;
5183                 s.in.info->info1.min_password_age = 0;
5184
5185                 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5186                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5187                         "SetDomainInfo failed");
5188                 if (!NT_STATUS_IS_OK(s.out.result)) {
5189                         return false;
5190                 }
5191
5192                 torture_comment(tctx, "calling test_ChangePasswordUser3 with too short password\n");
5193
5194                 if (!test_ChangePasswordUser3(p, tctx, acct_name, len - 1, password, NULL, 0, true)) {
5195                         ret = false;
5196                 }
5197
5198                 s.in.info->info1.min_password_length = len_old;
5199                 s.in.info->info1.password_properties = pwd_prop_old;
5200                 s.in.info->info1.min_password_age = min_pwd_age_old;
5201
5202                 torture_comment(tctx, "Testing samr_SetDomainInfo level 1\n");
5203                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
5204                         "SetDomainInfo failed");
5205                 if (!NT_STATUS_IS_OK(s.out.result)) {
5206                         return false;
5207                 }
5208
5209         }
5210
5211         {
5212                 struct samr_OpenUser r;
5213                 struct samr_QueryUserInfo q;
5214                 union samr_UserInfo *info;
5215                 struct samr_LookupNames n;
5216                 struct policy_handle user_handle;
5217                 struct samr_Ids rids, types;
5218
5219                 n.in.domain_handle = domain_handle;
5220                 n.in.num_names = 1;
5221                 n.in.names = talloc_array(tctx, struct lsa_String, 1);
5222                 n.in.names[0].string = acct_name;
5223                 n.out.rids = &rids;
5224                 n.out.types = &types;
5225
5226                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
5227                         "LookupNames failed");
5228                 if (!NT_STATUS_IS_OK(n.out.result)) {
5229                         torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
5230                         return false;
5231                 }
5232
5233                 r.in.domain_handle = domain_handle;
5234                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5235                 r.in.rid = n.out.rids->ids[0];
5236                 r.out.user_handle = &user_handle;
5237
5238                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5239                         "OpenUser failed");
5240                 if (!NT_STATUS_IS_OK(r.out.result)) {
5241                         torture_warning(tctx, "OpenUser(%u) failed - %s\n", n.out.rids->ids[0], nt_errstr(r.out.result));
5242                         return false;
5243                 }
5244
5245                 q.in.user_handle = &user_handle;
5246                 q.in.level = 5;
5247                 q.out.info = &info;
5248
5249                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5250                         "QueryUserInfo failed");
5251                 if (!NT_STATUS_IS_OK(q.out.result)) {
5252                         torture_warning(tctx, "QueryUserInfo failed - %s\n", nt_errstr(q.out.result));
5253                         return false;
5254                 }
5255
5256                 torture_comment(tctx, "calling test_ChangePasswordUser3 with too early password change\n");
5257
5258                 if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL,
5259                                               info->info5.last_password_change, true)) {
5260                         ret = false;
5261                 }
5262         }
5263
5264         /* we change passwords twice - this has the effect of verifying
5265            they were changed correctly for the final call */
5266         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5267                 ret = false;
5268         }
5269
5270         if (!test_ChangePasswordUser3(p, tctx, acct_name, 0, password, NULL, 0, true)) {
5271                 ret = false;
5272         }
5273
5274         return ret;
5275 }
5276
5277 static bool test_CreateUser(struct dcerpc_pipe *p, struct torture_context *tctx,
5278                             struct policy_handle *domain_handle,
5279                             const char *user_name,
5280                             struct policy_handle *user_handle_out,
5281                             struct dom_sid *domain_sid,
5282                             enum torture_samr_choice which_ops,
5283                             struct cli_credentials *machine_credentials,
5284                             bool test_user)
5285 {
5286
5287         TALLOC_CTX *user_ctx;
5288
5289         struct samr_CreateUser r;
5290         struct samr_QueryUserInfo q;
5291         union samr_UserInfo *info;
5292         struct samr_DeleteUser d;
5293         uint32_t rid;
5294
5295         /* This call creates a 'normal' account - check that it really does */
5296         const uint32_t acct_flags = ACB_NORMAL;
5297         struct lsa_String name;
5298         bool ret = true;
5299         struct dcerpc_binding_handle *b = p->binding_handle;
5300
5301         struct policy_handle user_handle;
5302         user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5303         init_lsa_String(&name, user_name);
5304
5305         r.in.domain_handle = domain_handle;
5306         r.in.account_name = &name;
5307         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5308         r.out.user_handle = &user_handle;
5309         r.out.rid = &rid;
5310
5311         torture_comment(tctx, "Testing CreateUser(%s)\n", r.in.account_name->string);
5312
5313         torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5314                 "CreateUser failed");
5315
5316         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5317                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5318                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5319                         return true;
5320                 } else {
5321                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5322                                nt_errstr(r.out.result));
5323                         return false;
5324                 }
5325         }
5326
5327         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5328                 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5329                         talloc_free(user_ctx);
5330                         return false;
5331                 }
5332                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser_r(b, user_ctx, &r),
5333                         "CreateUser failed");
5334         }
5335
5336         if (!NT_STATUS_IS_OK(r.out.result)) {
5337                 talloc_free(user_ctx);
5338                 torture_warning(tctx, "CreateUser failed - %s\n", nt_errstr(r.out.result));
5339                 return false;
5340         }
5341
5342         if (!test_user) {
5343                 if (user_handle_out) {
5344                         *user_handle_out = user_handle;
5345                 }
5346                 return ret;
5347         }
5348
5349         {
5350                 q.in.user_handle = &user_handle;
5351                 q.in.level = 16;
5352                 q.out.info = &info;
5353
5354                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5355                         "QueryUserInfo failed");
5356                 if (!NT_STATUS_IS_OK(q.out.result)) {
5357                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5358                                q.in.level, nt_errstr(q.out.result));
5359                         ret = false;
5360                 } else {
5361                         if ((info->info16.acct_flags & acct_flags) != acct_flags) {
5362                                 torture_warning(tctx, "QueryUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5363                                        info->info16.acct_flags,
5364                                        acct_flags);
5365                                 ret = false;
5366                         }
5367                 }
5368
5369                 if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5370                                    domain_sid, acct_flags, name.string, which_ops,
5371                                    machine_credentials)) {
5372                         ret = false;
5373                 }
5374
5375                 if (user_handle_out) {
5376                         *user_handle_out = user_handle;
5377                 } else {
5378                         torture_comment(tctx, "Testing DeleteUser (createuser test)\n");
5379
5380                         d.in.user_handle = &user_handle;
5381                         d.out.user_handle = &user_handle;
5382
5383                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5384                                 "DeleteUser failed");
5385                         if (!NT_STATUS_IS_OK(d.out.result)) {
5386                                 torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5387                                 ret = false;
5388                         }
5389                 }
5390
5391         }
5392
5393         talloc_free(user_ctx);
5394
5395         return ret;
5396 }
5397
5398
5399 static bool test_CreateUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
5400                              struct policy_handle *domain_handle,
5401                              struct dom_sid *domain_sid,
5402                              enum torture_samr_choice which_ops,
5403                              struct cli_credentials *machine_credentials)
5404 {
5405         struct samr_CreateUser2 r;
5406         struct samr_QueryUserInfo q;
5407         union samr_UserInfo *info;
5408         struct samr_DeleteUser d;
5409         struct policy_handle user_handle;
5410         uint32_t rid;
5411         struct lsa_String name;
5412         bool ret = true;
5413         int i;
5414         struct dcerpc_binding_handle *b = p->binding_handle;
5415
5416         struct {
5417                 uint32_t acct_flags;
5418                 const char *account_name;
5419                 NTSTATUS nt_status;
5420         } account_types[] = {
5421                 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
5422                 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5423                 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5424                 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5425                 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5426                 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5427                 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
5428                 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5429                 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
5430                 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_ACCESS_DENIED },
5431                 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5432                 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
5433                 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5434                 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
5435                 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
5436         };
5437
5438         for (i = 0; account_types[i].account_name; i++) {
5439                 TALLOC_CTX *user_ctx;
5440                 uint32_t acct_flags = account_types[i].acct_flags;
5441                 uint32_t access_granted;
5442                 user_ctx = talloc_named(tctx, 0, "test_CreateUser2 per-user context");
5443                 init_lsa_String(&name, account_types[i].account_name);
5444
5445                 r.in.domain_handle = domain_handle;
5446                 r.in.account_name = &name;
5447                 r.in.acct_flags = acct_flags;
5448                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5449                 r.out.user_handle = &user_handle;
5450                 r.out.access_granted = &access_granted;
5451                 r.out.rid = &rid;
5452
5453                 torture_comment(tctx, "Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
5454
5455                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5456                         "CreateUser2 failed");
5457
5458                 if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
5459                         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
5460                                 torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.account_name->string);
5461                                 continue;
5462                         } else {
5463                                 torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.account_name->string,
5464                                        nt_errstr(r.out.result));
5465                                 ret = false;
5466                                 continue;
5467                         }
5468                 }
5469
5470                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
5471                         if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.account_name->string)) {
5472                                 talloc_free(user_ctx);
5473                                 ret = false;
5474                                 continue;
5475                         }
5476                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateUser2_r(b, user_ctx, &r),
5477                                 "CreateUser2 failed");
5478
5479                 }
5480                 if (!NT_STATUS_EQUAL(r.out.result, account_types[i].nt_status)) {
5481                         torture_warning(tctx, "CreateUser2 failed gave incorrect error return - %s (should be %s)\n",
5482                                nt_errstr(r.out.result), nt_errstr(account_types[i].nt_status));
5483                         ret = false;
5484                 }
5485
5486                 if (NT_STATUS_IS_OK(r.out.result)) {
5487                         q.in.user_handle = &user_handle;
5488                         q.in.level = 5;
5489                         q.out.info = &info;
5490
5491                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, user_ctx, &q),
5492                                 "QueryUserInfo failed");
5493                         if (!NT_STATUS_IS_OK(q.out.result)) {
5494                                 torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5495                                        q.in.level, nt_errstr(q.out.result));
5496                                 ret = false;
5497                         } else {
5498                                 uint32_t expected_flags = (acct_flags | ACB_PWNOTREQ | ACB_DISABLED);
5499                                 if (acct_flags == ACB_NORMAL) {
5500                                         expected_flags |= ACB_PW_EXPIRED;
5501                                 }
5502                                 if ((info->info5.acct_flags) != expected_flags) {
5503                                         torture_warning(tctx, "QueryUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
5504                                                info->info5.acct_flags,
5505                                                expected_flags);
5506                                         ret = false;
5507                                 }
5508                                 switch (acct_flags) {
5509                                 case ACB_SVRTRUST:
5510                                         if (info->info5.primary_gid != DOMAIN_RID_DCS) {
5511                                                 torture_warning(tctx, "QueryUserInfo level 5: DC should have had Primary Group %d, got %d\n",
5512                                                        DOMAIN_RID_DCS, info->info5.primary_gid);
5513                                                 ret = false;
5514                                         }
5515                                         break;
5516                                 case ACB_WSTRUST:
5517                                         if (info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
5518                                                 torture_warning(tctx, "QueryUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n",
5519                                                        DOMAIN_RID_DOMAIN_MEMBERS, info->info5.primary_gid);
5520                                                 ret = false;
5521                                         }
5522                                         break;
5523                                 case ACB_NORMAL:
5524                                         if (info->info5.primary_gid != DOMAIN_RID_USERS) {
5525                                                 torture_warning(tctx, "QueryUserInfo level 5: Users should have had Primary Group %d, got %d\n",
5526                                                        DOMAIN_RID_USERS, info->info5.primary_gid);
5527                                                 ret = false;
5528                                         }
5529                                         break;
5530                                 }
5531                         }
5532
5533                         if (!test_user_ops(p, tctx, &user_handle, domain_handle,
5534                                            domain_sid, acct_flags, name.string, which_ops,
5535                                            machine_credentials)) {
5536                                 ret = false;
5537                         }
5538
5539                         if (!policy_handle_empty(&user_handle)) {
5540                                 torture_comment(tctx, "Testing DeleteUser (createuser2 test)\n");
5541
5542                                 d.in.user_handle = &user_handle;
5543                                 d.out.user_handle = &user_handle;
5544
5545                                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteUser_r(b, user_ctx, &d),
5546                                         "DeleteUser failed");
5547                                 if (!NT_STATUS_IS_OK(d.out.result)) {
5548                                         torture_warning(tctx, "DeleteUser failed - %s\n", nt_errstr(d.out.result));
5549                                         ret = false;
5550                                 }
5551                         }
5552                 }
5553                 talloc_free(user_ctx);
5554         }
5555
5556         return ret;
5557 }
5558
5559 static bool test_QueryAliasInfo(struct dcerpc_binding_handle *b,
5560                                 struct torture_context *tctx,
5561                                 struct policy_handle *handle)
5562 {
5563         struct samr_QueryAliasInfo r;
5564         union samr_AliasInfo *info;
5565         uint16_t levels[] = {1, 2, 3};
5566         int i;
5567         bool ret = true;
5568
5569         for (i=0;i<ARRAY_SIZE(levels);i++) {
5570                 torture_comment(tctx, "Testing QueryAliasInfo level %u\n", levels[i]);
5571
5572                 r.in.alias_handle = handle;
5573                 r.in.level = levels[i];
5574                 r.out.info = &info;
5575
5576                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &r),
5577                         "QueryAliasInfo failed");
5578                 if (!NT_STATUS_IS_OK(r.out.result)) {
5579                         torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
5580                                levels[i], nt_errstr(r.out.result));
5581                         ret = false;
5582                 }
5583         }
5584
5585         return ret;
5586 }
5587
5588 static bool test_QueryGroupInfo(struct dcerpc_binding_handle *b,
5589                                 struct torture_context *tctx,
5590                                 struct policy_handle *handle)
5591 {
5592         struct samr_QueryGroupInfo r;
5593         union samr_GroupInfo *info;
5594         uint16_t levels[] = {1, 2, 3, 4, 5};
5595         int i;
5596         bool ret = true;
5597
5598         for (i=0;i<ARRAY_SIZE(levels);i++) {
5599                 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5600
5601                 r.in.group_handle = handle;
5602                 r.in.level = levels[i];
5603                 r.out.info = &info;
5604
5605                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5606                         "QueryGroupInfo failed");
5607                 if (!NT_STATUS_IS_OK(r.out.result)) {
5608                         torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5609                                levels[i], nt_errstr(r.out.result));
5610                         ret = false;
5611                 }
5612         }
5613
5614         return ret;
5615 }
5616
5617 static bool test_QueryGroupMember(struct dcerpc_binding_handle *b,
5618                                   struct torture_context *tctx,
5619                                   struct policy_handle *handle)
5620 {
5621         struct samr_QueryGroupMember r;
5622         struct samr_RidAttrArray *rids = NULL;
5623         bool ret = true;
5624
5625         torture_comment(tctx, "Testing QueryGroupMember\n");
5626
5627         r.in.group_handle = handle;
5628         r.out.rids = &rids;
5629
5630         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &r),
5631                 "QueryGroupMember failed");
5632         if (!NT_STATUS_IS_OK(r.out.result)) {
5633                 torture_warning(tctx, "QueryGroupMember failed - %s\n", nt_errstr(r.out.result));
5634                 ret = false;
5635         }
5636
5637         return ret;
5638 }
5639
5640
5641 static bool test_SetGroupInfo(struct dcerpc_binding_handle *b,
5642                               struct torture_context *tctx,
5643                               struct policy_handle *handle)
5644 {
5645         struct samr_QueryGroupInfo r;
5646         union samr_GroupInfo *info;
5647         struct samr_SetGroupInfo s;
5648         uint16_t levels[] = {1, 2, 3, 4};
5649         uint16_t set_ok[] = {0, 1, 1, 1};
5650         int i;
5651         bool ret = true;
5652
5653         for (i=0;i<ARRAY_SIZE(levels);i++) {
5654                 torture_comment(tctx, "Testing QueryGroupInfo level %u\n", levels[i]);
5655
5656                 r.in.group_handle = handle;
5657                 r.in.level = levels[i];
5658                 r.out.info = &info;
5659
5660                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupInfo_r(b, tctx, &r),
5661                         "QueryGroupInfo failed");
5662                 if (!NT_STATUS_IS_OK(r.out.result)) {
5663                         torture_warning(tctx, "QueryGroupInfo level %u failed - %s\n",
5664                                levels[i], nt_errstr(r.out.result));
5665                         ret = false;
5666                 }
5667
5668                 torture_comment(tctx, "Testing SetGroupInfo level %u\n", levels[i]);
5669
5670                 s.in.group_handle = handle;
5671                 s.in.level = levels[i];
5672                 s.in.info = *r.out.info;
5673
5674 #if 0
5675                 /* disabled this, as it changes the name only from the point of view of samr,
5676                    but leaves the name from the point of view of w2k3 internals (and ldap). This means
5677                    the name is still reserved, so creating the old name fails, but deleting by the old name
5678                    also fails */
5679                 if (s.in.level == 2) {
5680                         init_lsa_String(&s.in.info->string, "NewName");
5681                 }
5682 #endif
5683
5684                 if (s.in.level == 4) {
5685                         init_lsa_String(&s.in.info->description, "test description");
5686                 }
5687
5688                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetGroupInfo_r(b, tctx, &s),
5689                         "SetGroupInfo failed");
5690                 if (set_ok[i]) {
5691                         if (!NT_STATUS_IS_OK(s.out.result)) {
5692                                 torture_warning(tctx, "SetGroupInfo level %u failed - %s\n",
5693                                        r.in.level, nt_errstr(s.out.result));
5694                                 ret = false;
5695                                 continue;
5696                         }
5697                 } else {
5698                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
5699                                 torture_warning(tctx, "SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
5700                                        r.in.level, nt_errstr(s.out.result));
5701                                 ret = false;
5702                                 continue;
5703                         }
5704                 }
5705         }
5706
5707         return ret;
5708 }
5709
5710 static bool test_QueryUserInfo(struct dcerpc_binding_handle *b,
5711                                struct torture_context *tctx,
5712                                struct policy_handle *handle)
5713 {
5714         struct samr_QueryUserInfo r;
5715         union samr_UserInfo *info;
5716         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5717                            11, 12, 13, 14, 16, 17, 20, 21};
5718         int i;
5719         bool ret = true;
5720
5721         for (i=0;i<ARRAY_SIZE(levels);i++) {
5722                 torture_comment(tctx, "Testing QueryUserInfo level %u\n", levels[i]);
5723
5724                 r.in.user_handle = handle;
5725                 r.in.level = levels[i];
5726                 r.out.info = &info;
5727
5728                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
5729                         "QueryUserInfo failed");
5730                 if (!NT_STATUS_IS_OK(r.out.result)) {
5731                         torture_warning(tctx, "QueryUserInfo level %u failed - %s\n",
5732                                levels[i], nt_errstr(r.out.result));
5733                         ret = false;
5734                 }
5735         }
5736
5737         return ret;
5738 }
5739
5740 static bool test_QueryUserInfo2(struct dcerpc_binding_handle *b,
5741                                 struct torture_context *tctx,
5742                                 struct policy_handle *handle)
5743 {
5744         struct samr_QueryUserInfo2 r;
5745         union samr_UserInfo *info;
5746         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
5747                            11, 12, 13, 14, 16, 17, 20, 21};
5748         int i;
5749         bool ret = true;
5750
5751         for (i=0;i<ARRAY_SIZE(levels);i++) {
5752                 torture_comment(tctx, "Testing QueryUserInfo2 level %u\n", levels[i]);
5753
5754                 r.in.user_handle = handle;
5755                 r.in.level = levels[i];
5756                 r.out.info = &info;
5757
5758                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r),
5759                         "QueryUserInfo2 failed");
5760                 if (!NT_STATUS_IS_OK(r.out.result)) {
5761                         torture_warning(tctx, "QueryUserInfo2 level %u failed - %s\n",
5762                                levels[i], nt_errstr(r.out.result));
5763                         ret = false;
5764                 }
5765         }
5766
5767         return ret;
5768 }
5769
5770 static bool test_OpenUser(struct dcerpc_binding_handle *b,
5771                           struct torture_context *tctx,
5772                           struct policy_handle *handle, uint32_t rid)
5773 {
5774         struct samr_OpenUser r;
5775         struct policy_handle user_handle;
5776         bool ret = true;
5777
5778         torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5779
5780         r.in.domain_handle = handle;
5781         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5782         r.in.rid = rid;
5783         r.out.user_handle = &user_handle;
5784
5785         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5786                 "OpenUser failed");
5787         if (!NT_STATUS_IS_OK(r.out.result)) {
5788                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5789                 return false;
5790         }
5791
5792         if (!test_QuerySecurity(b, tctx, &user_handle)) {
5793                 ret = false;
5794         }
5795
5796         if (!test_QueryUserInfo(b, tctx, &user_handle)) {
5797                 ret = false;
5798         }
5799
5800         if (!test_QueryUserInfo2(b, tctx, &user_handle)) {
5801                 ret = false;
5802         }
5803
5804         if (!test_GetUserPwInfo(b, tctx, &user_handle)) {
5805                 ret = false;
5806         }
5807
5808         if (!test_GetGroupsForUser(b, tctx, &user_handle)) {
5809                 ret = false;
5810         }
5811
5812         if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5813                 ret = false;
5814         }
5815
5816         return ret;
5817 }
5818
5819 static bool test_OpenGroup(struct dcerpc_binding_handle *b,
5820                            struct torture_context *tctx,
5821                            struct policy_handle *handle, uint32_t rid)
5822 {
5823         struct samr_OpenGroup r;
5824         struct policy_handle group_handle;
5825         bool ret = true;
5826
5827         torture_comment(tctx, "Testing OpenGroup(%u)\n", rid);
5828
5829         r.in.domain_handle = handle;
5830         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5831         r.in.rid = rid;
5832         r.out.group_handle = &group_handle;
5833
5834         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenGroup_r(b, tctx, &r),
5835                 "OpenGroup failed");
5836         if (!NT_STATUS_IS_OK(r.out.result)) {
5837                 torture_warning(tctx, "OpenGroup(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5838                 return false;
5839         }
5840
5841         if (!torture_setting_bool(tctx, "samba3", false)) {
5842                 if (!test_QuerySecurity(b, tctx, &group_handle)) {
5843                         ret = false;
5844                 }
5845         }
5846
5847         if (!test_QueryGroupInfo(b, tctx, &group_handle)) {
5848                 ret = false;
5849         }
5850
5851         if (!test_QueryGroupMember(b, tctx, &group_handle)) {
5852                 ret = false;
5853         }
5854
5855         if (!test_samr_handle_Close(b, tctx, &group_handle)) {
5856                 ret = false;
5857         }
5858
5859         return ret;
5860 }
5861
5862 static bool test_OpenAlias(struct dcerpc_binding_handle *b,
5863                            struct torture_context *tctx,
5864                            struct policy_handle *handle, uint32_t rid)
5865 {
5866         struct samr_OpenAlias r;
5867         struct policy_handle alias_handle;
5868         bool ret = true;
5869
5870         torture_comment(tctx, "Testing OpenAlias(%u)\n", rid);
5871
5872         r.in.domain_handle = handle;
5873         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5874         r.in.rid = rid;
5875         r.out.alias_handle = &alias_handle;
5876
5877         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenAlias_r(b, tctx, &r),
5878                 "OpenAlias failed");
5879         if (!NT_STATUS_IS_OK(r.out.result)) {
5880                 torture_warning(tctx, "OpenAlias(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5881                 return false;
5882         }
5883
5884         if (!torture_setting_bool(tctx, "samba3", false)) {
5885                 if (!test_QuerySecurity(b, tctx, &alias_handle)) {
5886                         ret = false;
5887                 }
5888         }
5889
5890         if (!test_QueryAliasInfo(b, tctx, &alias_handle)) {
5891                 ret = false;
5892         }
5893
5894         if (!test_GetMembersInAlias(b, tctx, &alias_handle)) {
5895                 ret = false;
5896         }
5897
5898         if (!test_samr_handle_Close(b, tctx, &alias_handle)) {
5899                 ret = false;
5900         }
5901
5902         return ret;
5903 }
5904
5905 static bool check_mask(struct dcerpc_binding_handle *b,
5906                        struct torture_context *tctx,
5907                        struct policy_handle *handle, uint32_t rid,
5908                        uint32_t acct_flag_mask)
5909 {
5910         struct samr_OpenUser r;
5911         struct samr_QueryUserInfo q;
5912         union samr_UserInfo *info;
5913         struct policy_handle user_handle;
5914         bool ret = true;
5915
5916         torture_comment(tctx, "Testing OpenUser(%u)\n", rid);
5917
5918         r.in.domain_handle = handle;
5919         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
5920         r.in.rid = rid;
5921         r.out.user_handle = &user_handle;
5922
5923         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
5924                 "OpenUser failed");
5925         if (!NT_STATUS_IS_OK(r.out.result)) {
5926                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", rid, nt_errstr(r.out.result));
5927                 return false;
5928         }
5929
5930         q.in.user_handle = &user_handle;
5931         q.in.level = 16;
5932         q.out.info = &info;
5933
5934         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
5935                 "QueryUserInfo failed");
5936         if (!NT_STATUS_IS_OK(q.out.result)) {
5937                 torture_warning(tctx, "QueryUserInfo level 16 failed - %s\n",
5938                        nt_errstr(q.out.result));
5939                 ret = false;
5940         } else {
5941                 if ((acct_flag_mask & info->info16.acct_flags) == 0) {
5942                         torture_warning(tctx, "Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
5943                                acct_flag_mask, info->info16.acct_flags, rid);
5944                         ret = false;
5945                 }
5946         }
5947
5948         if (!test_samr_handle_Close(b, tctx, &user_handle)) {
5949                 ret = false;
5950         }
5951
5952         return ret;
5953 }
5954
5955 static bool test_EnumDomainUsers_all(struct dcerpc_binding_handle *b,
5956                                      struct torture_context *tctx,
5957                                      struct policy_handle *handle)
5958 {
5959         struct samr_EnumDomainUsers r;
5960         uint32_t mask, resume_handle=0;
5961         int i, mask_idx;
5962         bool ret = true;
5963         struct samr_LookupNames n;
5964         struct samr_LookupRids  lr ;
5965         struct lsa_Strings names;
5966         struct samr_Ids rids, types;
5967         struct samr_SamArray *sam = NULL;
5968         uint32_t num_entries = 0;
5969
5970         uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST,
5971                             ACB_DISABLED, ACB_NORMAL | ACB_DISABLED,
5972                             ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST,
5973                             ACB_PWNOEXP, 0};
5974
5975         torture_comment(tctx, "Testing EnumDomainUsers\n");
5976
5977         for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
5978                 r.in.domain_handle = handle;
5979                 r.in.resume_handle = &resume_handle;
5980                 r.in.acct_flags = mask = masks[mask_idx];
5981                 r.in.max_size = (uint32_t)-1;
5982                 r.out.resume_handle = &resume_handle;
5983                 r.out.num_entries = &num_entries;
5984                 r.out.sam = &sam;
5985
5986                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
5987                         "EnumDomainUsers failed");
5988                 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
5989                     !NT_STATUS_IS_OK(r.out.result)) {
5990                         torture_warning(tctx, "EnumDomainUsers failed - %s\n", nt_errstr(r.out.result));
5991                         return false;
5992                 }
5993
5994                 torture_assert(tctx, sam, "EnumDomainUsers failed: r.out.sam unexpectedly NULL");
5995
5996                 if (sam->count == 0) {
5997                         continue;
5998                 }
5999
6000                 for (i=0;i<sam->count;i++) {
6001                         if (mask) {
6002                                 if (!check_mask(b, tctx, handle, sam->entries[i].idx, mask)) {
6003                                         ret = false;
6004                                 }
6005                         } else if (!test_OpenUser(b, tctx, handle, sam->entries[i].idx)) {
6006                                 ret = false;
6007                         }
6008                 }
6009         }
6010
6011         torture_comment(tctx, "Testing LookupNames\n");
6012         n.in.domain_handle = handle;
6013         n.in.num_names = sam->count;
6014         n.in.names = talloc_array(tctx, struct lsa_String, sam->count);
6015         n.out.rids = &rids;
6016         n.out.types = &types;
6017         for (i=0;i<sam->count;i++) {
6018                 n.in.names[i].string = sam->entries[i].name.string;
6019         }
6020         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupNames_r(b, tctx, &n),
6021                 "LookupNames failed");
6022         if (!NT_STATUS_IS_OK(n.out.result)) {
6023                 torture_warning(tctx, "LookupNames failed - %s\n", nt_errstr(n.out.result));
6024                 ret = false;
6025         }
6026
6027
6028         torture_comment(tctx, "Testing LookupRids\n");
6029         lr.in.domain_handle = handle;
6030         lr.in.num_rids = sam->count;
6031         lr.in.rids = talloc_array(tctx, uint32_t, sam->count);
6032         lr.out.names = &names;
6033         lr.out.types = &types;
6034         for (i=0;i<sam->count;i++) {
6035                 lr.in.rids[i] = sam->entries[i].idx;
6036         }
6037         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupRids_r(b, tctx, &lr),
6038                 "LookupRids failed");
6039         torture_assert_ntstatus_ok(tctx, lr.out.result, "LookupRids");
6040
6041         return ret;
6042 }
6043
6044 /*
6045   try blasting the server with a bunch of sync requests
6046 */
6047 static bool test_EnumDomainUsers_async(struct dcerpc_pipe *p, struct torture_context *tctx,
6048                                        struct policy_handle *handle)
6049 {
6050         struct samr_EnumDomainUsers r;
6051         uint32_t resume_handle=0;
6052         int i;
6053 #define ASYNC_COUNT 100
6054         struct tevent_req *req[ASYNC_COUNT];
6055
6056         if (!torture_setting_bool(tctx, "dangerous", false)) {
6057                 torture_skip(tctx, "samr async test disabled - enable dangerous tests to use\n");
6058         }
6059
6060         torture_comment(tctx, "Testing EnumDomainUsers_async\n");
6061
6062         r.in.domain_handle = handle;
6063         r.in.resume_handle = &resume_handle;
6064         r.in.acct_flags = 0;
6065         r.in.max_size = (uint32_t)-1;
6066         r.out.resume_handle = &resume_handle;
6067
6068         for (i=0;i<ASYNC_COUNT;i++) {
6069                 req[i] = dcerpc_samr_EnumDomainUsers_r_send(tctx, tctx->ev, p->binding_handle, &r);
6070         }
6071
6072         for (i=0;i<ASYNC_COUNT;i++) {
6073                 tevent_req_poll(req[i], tctx->ev);
6074                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r_recv(req[i], tctx),
6075                         talloc_asprintf(tctx, "EnumDomainUsers[%d] failed - %s\n",
6076                                i, nt_errstr(r.out.result)));
6077         }
6078
6079         torture_comment(tctx, "%d async requests OK\n", i);
6080
6081         return true;
6082 }
6083
6084 static bool test_EnumDomainGroups_all(struct dcerpc_binding_handle *b,
6085                                       struct torture_context *tctx,
6086                                       struct policy_handle *handle)
6087 {
6088         struct samr_EnumDomainGroups r;
6089         uint32_t resume_handle=0;
6090         struct samr_SamArray *sam = NULL;
6091         uint32_t num_entries = 0;
6092         int i;
6093         bool ret = true;
6094         bool universal_group_found = false;
6095
6096         torture_comment(tctx, "Testing EnumDomainGroups\n");
6097
6098         r.in.domain_handle = handle;
6099         r.in.resume_handle = &resume_handle;
6100         r.in.max_size = (uint32_t)-1;
6101         r.out.resume_handle = &resume_handle;
6102         r.out.num_entries = &num_entries;
6103         r.out.sam = &sam;
6104
6105         torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
6106                 "EnumDomainGroups failed");
6107         if (!NT_STATUS_IS_OK(r.out.result)) {
6108                 torture_warning(tctx, "EnumDomainGroups failed - %s\n", nt_errstr(r.out.result));
6109                 return false;
6110         }
6111
6112         if (!sam) {
6113                 return false;
6114         }
6115
6116         for (i=0;i<sam->count;i++) {
6117                 if (!test_OpenGroup(b, tctx, handle, sam->entries[i].idx)) {
6118                         ret = false;
6119                 }
6120                 if ((ret == true) && (strcasecmp(sam->entries[i].name.string,
6121                                                  "Enterprise Admins") == 0)) {
6122                         universal_group_found = true;
6123                 }
6124         }
6125
6126         /* when we are running this on s4 we should get back at least the
6127          * "Enterprise Admins" universal group. If we don't get a group entry
6128          * at all we probably are performing the test on the builtin domain.
6129          * So ignore this case. */
6130         if (torture_setting_bool(tctx, "samba4", false)) {
6131                 if ((sam->count > 0) && (!universal_group_found)) {
6132                         ret = false;
6133                 }
6134         }
6135
6136         return ret;
6137 }
6138
6139 static bool test_EnumDomainAliases_all(struct dcerpc_binding_handle *b,
6140                                        struct torture_context *tctx,
6141                                        struct policy_handle *handle)
6142 {
6143         struct samr_EnumDomainAliases r;
6144         uint32_t resume_handle=0;
6145         struct samr_SamArray *sam = NULL;
6146         uint32_t num_entries = 0;
6147         int i;
6148         bool ret = true;
6149
6150         torture_comment(tctx, "Testing EnumDomainAliases\n");
6151
6152         r.in.domain_handle = handle;
6153         r.in.resume_handle = &resume_handle;
6154         r.in.max_size = (uint32_t)-1;
6155         r.out.sam = &sam;
6156         r.out.num_entries = &num_entries;
6157         r.out.resume_handle = &resume_handle;
6158
6159         torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
6160                 "EnumDomainAliases failed");
6161         if (!NT_STATUS_IS_OK(r.out.result)) {
6162                 torture_warning(tctx, "EnumDomainAliases failed - %s\n", nt_errstr(r.out.result));
6163                 return false;
6164         }
6165
6166         if (!sam) {
6167                 return false;
6168         }
6169
6170         for (i=0;i<sam->count;i++) {
6171                 if (!test_OpenAlias(b, tctx, handle, sam->entries[i].idx)) {
6172                         ret = false;
6173                 }
6174         }
6175
6176         return ret;
6177 }
6178
6179 static bool test_GetDisplayEnumerationIndex(struct dcerpc_binding_handle *b,
6180                                             struct torture_context *tctx,
6181                                             struct policy_handle *handle)
6182 {
6183         struct samr_GetDisplayEnumerationIndex r;
6184         bool ret = true;
6185         uint16_t levels[] = {1, 2, 3, 4, 5};
6186         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6187         struct lsa_String name;
6188         uint32_t idx = 0;
6189         int i;
6190
6191         for (i=0;i<ARRAY_SIZE(levels);i++) {
6192                 torture_comment(tctx, "Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
6193
6194                 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6195
6196                 r.in.domain_handle = handle;
6197                 r.in.level = levels[i];
6198                 r.in.name = &name;
6199                 r.out.idx = &idx;
6200
6201                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6202                         "GetDisplayEnumerationIndex failed");
6203
6204                 if (ok_lvl[i] &&
6205                     !NT_STATUS_IS_OK(r.out.result) &&
6206                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6207                         torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6208                                levels[i], nt_errstr(r.out.result));
6209                         ret = false;
6210                 }
6211
6212                 init_lsa_String(&name, "zzzzzzzz");
6213
6214                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex_r(b, tctx, &r),
6215                         "GetDisplayEnumerationIndex failed");
6216
6217                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6218                         torture_warning(tctx, "GetDisplayEnumerationIndex level %u failed - %s\n",
6219                                levels[i], nt_errstr(r.out.result));
6220                         ret = false;
6221                 }
6222         }
6223
6224         return ret;
6225 }
6226
6227 static bool test_GetDisplayEnumerationIndex2(struct dcerpc_binding_handle *b,
6228                                              struct torture_context *tctx,
6229                                              struct policy_handle *handle)
6230 {
6231         struct samr_GetDisplayEnumerationIndex2 r;
6232         bool ret = true;
6233         uint16_t levels[] = {1, 2, 3, 4, 5};
6234         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
6235         struct lsa_String name;
6236         uint32_t idx = 0;
6237         int i;
6238
6239         for (i=0;i<ARRAY_SIZE(levels);i++) {
6240                 torture_comment(tctx, "Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
6241
6242                 init_lsa_String(&name, TEST_ACCOUNT_NAME);
6243
6244                 r.in.domain_handle = handle;
6245                 r.in.level = levels[i];
6246                 r.in.name = &name;
6247                 r.out.idx = &idx;
6248
6249                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6250                         "GetDisplayEnumerationIndex2 failed");
6251                 if (ok_lvl[i] &&
6252                     !NT_STATUS_IS_OK(r.out.result) &&
6253                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6254                         torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6255                                levels[i], nt_errstr(r.out.result));
6256                         ret = false;
6257                 }
6258
6259                 init_lsa_String(&name, "zzzzzzzz");
6260
6261                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDisplayEnumerationIndex2_r(b, tctx, &r),
6262                         "GetDisplayEnumerationIndex2 failed");
6263                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, r.out.result)) {
6264                         torture_warning(tctx, "GetDisplayEnumerationIndex2 level %u failed - %s\n",
6265                                levels[i], nt_errstr(r.out.result));
6266                         ret = false;
6267                 }
6268         }
6269
6270         return ret;
6271 }
6272
6273 #define STRING_EQUAL_QUERY(s1, s2, user)                                        \
6274         if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
6275                 /* odd, but valid */                                            \
6276         } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
6277                         torture_warning(tctx, "%s mismatch for %s: %s != %s (%s)\n", \
6278                                #s1, user.string,  s1.string, s2.string, __location__);   \
6279                         ret = false; \
6280         }
6281 #define INT_EQUAL_QUERY(s1, s2, user)           \
6282                 if (s1 != s2) { \
6283                         torture_warning(tctx, "%s mismatch for %s: 0x%llx != 0x%llx (%s)\n", \
6284                                #s1, user.string, (unsigned long long)s1, (unsigned long long)s2, __location__); \
6285                         ret = false; \
6286                 }
6287
6288 static bool test_each_DisplayInfo_user(struct dcerpc_binding_handle *b,
6289                                        struct torture_context *tctx,
6290                                        struct samr_QueryDisplayInfo *querydisplayinfo,
6291                                        bool *seen_testuser)
6292 {
6293         struct samr_OpenUser r;
6294         struct samr_QueryUserInfo q;
6295         union samr_UserInfo *info;
6296         struct policy_handle user_handle;
6297         int i, ret = true;
6298         r.in.domain_handle = querydisplayinfo->in.domain_handle;
6299         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
6300         for (i = 0; ; i++) {
6301                 switch (querydisplayinfo->in.level) {
6302                 case 1:
6303                         if (i >= querydisplayinfo->out.info->info1.count) {
6304                                 return ret;
6305                         }
6306                         r.in.rid = querydisplayinfo->out.info->info1.entries[i].rid;
6307                         break;
6308                 case 2:
6309                         if (i >= querydisplayinfo->out.info->info2.count) {
6310                                 return ret;
6311                         }
6312                         r.in.rid = querydisplayinfo->out.info->info2.entries[i].rid;
6313                         break;
6314                 case 3:
6315                         /* Groups */
6316                 case 4:
6317                 case 5:
6318                         /* Not interested in validating just the account name */
6319                         return true;
6320                 }
6321
6322                 r.out.user_handle = &user_handle;
6323
6324                 switch (querydisplayinfo->in.level) {
6325                 case 1:
6326                 case 2:
6327                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenUser_r(b, tctx, &r),
6328                                 "OpenUser failed");
6329                         if (!NT_STATUS_IS_OK(r.out.result)) {
6330                                 torture_warning(tctx, "OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6331                                 return false;
6332                         }
6333                 }
6334
6335                 q.in.user_handle = &user_handle;
6336                 q.in.level = 21;
6337                 q.out.info = &info;
6338                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &q),
6339                         "QueryUserInfo failed");
6340                 if (!NT_STATUS_IS_OK(r.out.result)) {
6341                         torture_warning(tctx, "QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(r.out.result));
6342                         return false;
6343                 }
6344
6345                 switch (querydisplayinfo->in.level) {
6346                 case 1:
6347                         if (seen_testuser && strcmp(info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
6348                                 *seen_testuser = true;
6349                         }
6350                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].full_name,
6351                                            info->info21.full_name, info->info21.account_name);
6352                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].account_name,
6353                                            info->info21.account_name, info->info21.account_name);
6354                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].description,
6355                                            info->info21.description, info->info21.account_name);
6356                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].rid,
6357                                         info->info21.rid, info->info21.account_name);
6358                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info1.entries[i].acct_flags,
6359                                         info->info21.acct_flags, info->info21.account_name);
6360
6361                         break;
6362                 case 2:
6363                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].account_name,
6364                                            info->info21.account_name, info->info21.account_name);
6365                         STRING_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].description,
6366                                            info->info21.description, info->info21.account_name);
6367                         INT_EQUAL_QUERY(querydisplayinfo->out.info->info2.entries[i].rid,
6368                                         info->info21.rid, info->info21.account_name);
6369                         INT_EQUAL_QUERY((querydisplayinfo->out.info->info2.entries[i].acct_flags & ~ACB_NORMAL),
6370                                         info->info21.acct_flags, info->info21.account_name);
6371
6372                         if (!(querydisplayinfo->out.info->info2.entries[i].acct_flags & ACB_NORMAL)) {
6373                                 torture_warning(tctx, "Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n",
6374                                        info->info21.account_name.string);
6375                         }
6376
6377                         if (!(info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
6378                                 torture_warning(tctx, "Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
6379                                        info->info21.account_name.string,
6380                                        querydisplayinfo->out.info->info2.entries[i].acct_flags,
6381                                        info->info21.acct_flags);
6382                                 return false;
6383                         }
6384
6385                         break;
6386                 }
6387
6388                 if (!test_samr_handle_Close(b, tctx, &user_handle)) {
6389                         return false;
6390                 }
6391         }
6392         return ret;
6393 }
6394
6395 static bool test_QueryDisplayInfo(struct dcerpc_binding_handle *b,
6396                                   struct torture_context *tctx,
6397                                   struct policy_handle *handle)
6398 {
6399         struct samr_QueryDisplayInfo r;
6400         struct samr_QueryDomainInfo dom_info;
6401         union samr_DomainInfo *info = NULL;
6402         bool ret = true;
6403         uint16_t levels[] = {1, 2, 3, 4, 5};
6404         int i;
6405         bool seen_testuser = false;
6406         uint32_t total_size;
6407         uint32_t returned_size;
6408         union samr_DispInfo disp_info;
6409
6410
6411         for (i=0;i<ARRAY_SIZE(levels);i++) {
6412                 torture_comment(tctx, "Testing QueryDisplayInfo level %u\n", levels[i]);
6413
6414                 r.in.start_idx = 0;
6415                 r.out.result = STATUS_MORE_ENTRIES;
6416                 while (NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES)) {
6417                         r.in.domain_handle = handle;
6418                         r.in.level = levels[i];
6419                         r.in.max_entries = 2;
6420                         r.in.buf_size = (uint32_t)-1;
6421                         r.out.total_size = &total_size;
6422                         r.out.returned_size = &returned_size;
6423                         r.out.info = &disp_info;
6424
6425                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6426                                 "QueryDisplayInfo failed");
6427                         if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(r.out.result)) {
6428                                 torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6429                                        levels[i], nt_errstr(r.out.result));
6430                                 ret = false;
6431                         }
6432                         switch (r.in.level) {
6433                         case 1:
6434                                 if (!test_each_DisplayInfo_user(b, tctx, &r, &seen_testuser)) {
6435                                         ret = false;
6436                                 }
6437                                 r.in.start_idx += r.out.info->info1.count;
6438                                 break;
6439                         case 2:
6440                                 if (!test_each_DisplayInfo_user(b, tctx, &r, NULL)) {
6441                                         ret = false;
6442                                 }
6443                                 r.in.start_idx += r.out.info->info2.count;
6444                                 break;
6445                         case 3:
6446                                 r.in.start_idx += r.out.info->info3.count;
6447                                 break;
6448                         case 4:
6449                                 r.in.start_idx += r.out.info->info4.count;
6450                                 break;
6451                         case 5:
6452                                 r.in.start_idx += r.out.info->info5.count;
6453                                 break;
6454                         }
6455                 }
6456                 dom_info.in.domain_handle = handle;
6457                 dom_info.in.level = 2;
6458                 dom_info.out.info = &info;
6459
6460                 /* Check number of users returned is correct */
6461                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &dom_info),
6462                         "QueryDomainInfo failed");
6463                 if (!NT_STATUS_IS_OK(dom_info.out.result)) {
6464                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6465                                r.in.level, nt_errstr(dom_info.out.result));
6466                         ret = false;
6467                         break;
6468                 }
6469                 switch (r.in.level) {
6470                 case 1:
6471                 case 4:
6472                         if (info->general.num_users < r.in.start_idx) {
6473                                 /* On AD deployments this numbers don't match
6474                                  * since QueryDisplayInfo returns universal and
6475                                  * global groups, QueryDomainInfo only global
6476                                  * ones. */
6477                                 if (torture_setting_bool(tctx, "samba3", false)) {
6478                                         torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
6479                                                r.in.start_idx, info->general.num_groups,
6480                                                info->general.domain_name.string);
6481                                         ret = false;
6482                                 }
6483                         }
6484                         if (!seen_testuser) {
6485                                 struct policy_handle user_handle;
6486                                 if (NT_STATUS_IS_OK(test_OpenUser_byname(b, tctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
6487                                         torture_warning(tctx, "Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
6488                                                info->general.domain_name.string);
6489                                         ret = false;
6490                                         test_samr_handle_Close(b, tctx, &user_handle);
6491                                 }
6492                         }
6493                         break;
6494                 case 3:
6495                 case 5:
6496                         if (info->general.num_groups != r.in.start_idx) {
6497                                 /* On AD deployments this numbers don't match
6498                                  * since QueryDisplayInfo returns universal and
6499                                  * global groups, QueryDomainInfo only global
6500                                  * ones. */
6501                                 if (torture_setting_bool(tctx, "samba3", false)) {
6502                                         torture_warning(tctx, "QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
6503                                                r.in.start_idx, info->general.num_groups,
6504                                                info->general.domain_name.string);
6505                                         ret = false;
6506                                 }
6507                         }
6508
6509                         break;
6510                 }
6511
6512         }
6513
6514         return ret;
6515 }
6516
6517 static bool test_QueryDisplayInfo2(struct dcerpc_binding_handle *b,
6518                                    struct torture_context *tctx,
6519                                    struct policy_handle *handle)
6520 {
6521         struct samr_QueryDisplayInfo2 r;
6522         bool ret = true;
6523         uint16_t levels[] = {1, 2, 3, 4, 5};
6524         int i;
6525         uint32_t total_size;
6526         uint32_t returned_size;
6527         union samr_DispInfo info;
6528
6529         for (i=0;i<ARRAY_SIZE(levels);i++) {
6530                 torture_comment(tctx, "Testing QueryDisplayInfo2 level %u\n", levels[i]);
6531
6532                 r.in.domain_handle = handle;
6533                 r.in.level = levels[i];
6534                 r.in.start_idx = 0;
6535                 r.in.max_entries = 1000;
6536                 r.in.buf_size = (uint32_t)-1;
6537                 r.out.total_size = &total_size;
6538                 r.out.returned_size = &returned_size;
6539                 r.out.info = &info;
6540
6541                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo2_r(b, tctx, &r),
6542                         "QueryDisplayInfo2 failed");
6543                 if (!NT_STATUS_IS_OK(r.out.result)) {
6544                         torture_warning(tctx, "QueryDisplayInfo2 level %u failed - %s\n",
6545                                levels[i], nt_errstr(r.out.result));
6546                         ret = false;
6547                 }
6548         }
6549
6550         return ret;
6551 }
6552
6553 static bool test_QueryDisplayInfo3(struct dcerpc_binding_handle *b,
6554                                    struct torture_context *tctx,
6555                                    struct policy_handle *handle)
6556 {
6557         struct samr_QueryDisplayInfo3 r;
6558         bool ret = true;
6559         uint16_t levels[] = {1, 2, 3, 4, 5};
6560         int i;
6561         uint32_t total_size;
6562         uint32_t returned_size;
6563         union samr_DispInfo info;
6564
6565         for (i=0;i<ARRAY_SIZE(levels);i++) {
6566                 torture_comment(tctx, "Testing QueryDisplayInfo3 level %u\n", levels[i]);
6567
6568                 r.in.domain_handle = handle;
6569                 r.in.level = levels[i];
6570                 r.in.start_idx = 0;
6571                 r.in.max_entries = 1000;
6572                 r.in.buf_size = (uint32_t)-1;
6573                 r.out.total_size = &total_size;
6574                 r.out.returned_size = &returned_size;
6575                 r.out.info = &info;
6576
6577                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo3_r(b, tctx, &r),
6578                         "QueryDisplayInfo3 failed");
6579                 if (!NT_STATUS_IS_OK(r.out.result)) {
6580                         torture_warning(tctx, "QueryDisplayInfo3 level %u failed - %s\n",
6581                                levels[i], nt_errstr(r.out.result));
6582                         ret = false;
6583                 }
6584         }
6585
6586         return ret;
6587 }
6588
6589
6590 static bool test_QueryDisplayInfo_continue(struct dcerpc_binding_handle *b,
6591                                            struct torture_context *tctx,
6592                                            struct policy_handle *handle)
6593 {
6594         struct samr_QueryDisplayInfo r;
6595         bool ret = true;
6596         uint32_t total_size;
6597         uint32_t returned_size;
6598         union samr_DispInfo info;
6599
6600         torture_comment(tctx, "Testing QueryDisplayInfo continuation\n");
6601
6602         r.in.domain_handle = handle;
6603         r.in.level = 1;
6604         r.in.start_idx = 0;
6605         r.in.max_entries = 1;
6606         r.in.buf_size = (uint32_t)-1;
6607         r.out.total_size = &total_size;
6608         r.out.returned_size = &returned_size;
6609         r.out.info = &info;
6610
6611         do {
6612                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
6613                         "QueryDisplayInfo failed");
6614                 if (NT_STATUS_IS_OK(r.out.result) && *r.out.returned_size != 0) {
6615                         if (r.out.info->info1.entries[0].idx != r.in.start_idx + 1) {
6616                                 torture_warning(tctx, "expected idx %d but got %d\n",
6617                                        r.in.start_idx + 1,
6618                                        r.out.info->info1.entries[0].idx);
6619                                 break;
6620                         }
6621                 }
6622                 if (!NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) &&
6623                     !NT_STATUS_IS_OK(r.out.result)) {
6624                         torture_warning(tctx, "QueryDisplayInfo level %u failed - %s\n",
6625                                r.in.level, nt_errstr(r.out.result));
6626                         ret = false;
6627                         break;
6628                 }
6629                 r.in.start_idx++;
6630         } while ((NT_STATUS_EQUAL(r.out.result, STATUS_MORE_ENTRIES) ||
6631                   NT_STATUS_IS_OK(r.out.result)) &&
6632                  *r.out.returned_size != 0);
6633
6634         return ret;
6635 }
6636
6637 static bool test_QueryDomainInfo(struct dcerpc_pipe *p,
6638                                  struct torture_context *tctx,
6639                                  struct policy_handle *handle)
6640 {
6641         struct samr_QueryDomainInfo r;
6642         union samr_DomainInfo *info = NULL;
6643         struct samr_SetDomainInfo s;
6644         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6645         uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1,  0,  1,  0};
6646         int i;
6647         bool ret = true;
6648         struct dcerpc_binding_handle *b = p->binding_handle;
6649         const char *domain_comment = talloc_asprintf(tctx,
6650                                   "Tortured by Samba4 RPC-SAMR: %s",
6651                                   timestring(tctx, time(NULL)));
6652
6653         s.in.domain_handle = handle;
6654         s.in.level = 4;
6655         s.in.info = talloc(tctx, union samr_DomainInfo);
6656
6657         s.in.info->oem.oem_information.string = domain_comment;
6658         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6659                 "SetDomainInfo failed");
6660         if (!NT_STATUS_IS_OK(s.out.result)) {
6661                 torture_warning(tctx, "SetDomainInfo level %u (set comment) failed - %s\n",
6662                        s.in.level, nt_errstr(s.out.result));
6663                 return false;
6664         }
6665
6666         for (i=0;i<ARRAY_SIZE(levels);i++) {
6667                 torture_comment(tctx, "Testing QueryDomainInfo level %u\n", levels[i]);
6668
6669                 r.in.domain_handle = handle;
6670                 r.in.level = levels[i];
6671                 r.out.info = &info;
6672
6673                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6674                         "QueryDomainInfo failed");
6675                 if (!NT_STATUS_IS_OK(r.out.result)) {
6676                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6677                                r.in.level, nt_errstr(r.out.result));
6678                         ret = false;
6679                         continue;
6680                 }
6681
6682                 switch (levels[i]) {
6683                 case 2:
6684                         if (strcmp(info->general.oem_information.string, domain_comment) != 0) {
6685                                 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6686                                        levels[i], info->general.oem_information.string, domain_comment);
6687                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6688                                         ret = false;
6689                                 }
6690                         }
6691                         if (!info->general.primary.string) {
6692                                 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6693                                        levels[i]);
6694                                 ret = false;
6695                         } else if (info->general.role == SAMR_ROLE_DOMAIN_PDC) {
6696                                 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), info->general.primary.string) != 0) {
6697                                         if (torture_setting_bool(tctx, "samba3", false)) {
6698                                                 torture_warning(tctx, "QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
6699                                                        levels[i], info->general.primary.string, dcerpc_server_name(p));
6700                                         }
6701                                 }
6702                         }
6703                         break;
6704                 case 4:
6705                         if (strcmp(info->oem.oem_information.string, domain_comment) != 0) {
6706                                 torture_warning(tctx, "QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
6707                                        levels[i], info->oem.oem_information.string, domain_comment);
6708                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6709                                         ret = false;
6710                                 }
6711                         }
6712                         break;
6713                 case 6:
6714                         if (!info->info6.primary.string) {
6715                                 torture_warning(tctx, "QueryDomainInfo level %u returned no PDC name\n",
6716                                        levels[i]);
6717                                 ret = false;
6718                         }
6719                         break;
6720                 case 11:
6721                         if (strcmp(info->general2.general.oem_information.string, domain_comment) != 0) {
6722                                 torture_warning(tctx, "QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
6723                                        levels[i], info->general2.general.oem_information.string, domain_comment);
6724                                 if (!torture_setting_bool(tctx, "samba3", false)) {
6725                                         ret = false;
6726                                 }
6727                         }
6728                         break;
6729                 }
6730
6731                 torture_comment(tctx, "Testing SetDomainInfo level %u\n", levels[i]);
6732
6733                 s.in.domain_handle = handle;
6734                 s.in.level = levels[i];
6735                 s.in.info = info;
6736
6737                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetDomainInfo_r(b, tctx, &s),
6738                         "SetDomainInfo failed");
6739                 if (set_ok[i]) {
6740                         if (!NT_STATUS_IS_OK(s.out.result)) {
6741                                 torture_warning(tctx, "SetDomainInfo level %u failed - %s\n",
6742                                        r.in.level, nt_errstr(s.out.result));
6743                                 ret = false;
6744                                 continue;
6745                         }
6746                 } else {
6747                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, s.out.result)) {
6748                                 torture_warning(tctx, "SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n",
6749                                        r.in.level, nt_errstr(s.out.result));
6750                                 ret = false;
6751                                 continue;
6752                         }
6753                 }
6754
6755                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo_r(b, tctx, &r),
6756                         "QueryDomainInfo failed");
6757                 if (!NT_STATUS_IS_OK(r.out.result)) {
6758                         torture_warning(tctx, "QueryDomainInfo level %u failed - %s\n",
6759                                r.in.level, nt_errstr(r.out.result));
6760                         ret = false;
6761                         continue;
6762                 }
6763         }
6764
6765         return ret;
6766 }
6767
6768
6769 static bool test_QueryDomainInfo2(struct dcerpc_binding_handle *b,
6770                                   struct torture_context *tctx,
6771                                   struct policy_handle *handle)
6772 {
6773         struct samr_QueryDomainInfo2 r;
6774         union samr_DomainInfo *info = NULL;
6775         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
6776         int i;
6777         bool ret = true;
6778
6779         for (i=0;i<ARRAY_SIZE(levels);i++) {
6780                 torture_comment(tctx, "Testing QueryDomainInfo2 level %u\n", levels[i]);
6781
6782                 r.in.domain_handle = handle;
6783                 r.in.level = levels[i];
6784                 r.out.info = &info;
6785
6786                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
6787                         "QueryDomainInfo2 failed");
6788                 if (!NT_STATUS_IS_OK(r.out.result)) {
6789                         torture_warning(tctx, "QueryDomainInfo2 level %u failed - %s\n",
6790                                r.in.level, nt_errstr(r.out.result));
6791                         ret = false;
6792                         continue;
6793                 }
6794         }
6795
6796         return true;
6797 }
6798
6799 /* Test whether querydispinfo level 5 and enumdomgroups return the same
6800    set of group names. */
6801 static bool test_GroupList(struct dcerpc_binding_handle *b,
6802                            struct torture_context *tctx,
6803                            struct policy_handle *handle)
6804 {
6805         struct samr_EnumDomainGroups q1;
6806         struct samr_QueryDisplayInfo q2;
6807         NTSTATUS status;
6808         uint32_t resume_handle=0;
6809         struct samr_SamArray *sam = NULL;
6810         uint32_t num_entries = 0;
6811         int i;
6812         bool ret = true;
6813         uint32_t total_size;
6814         uint32_t returned_size;
6815         union samr_DispInfo info;
6816
6817         int num_names = 0;
6818         const char **names = NULL;
6819
6820         torture_comment(tctx, "Testing coherency of querydispinfo vs enumdomgroups\n");
6821
6822         q1.in.domain_handle = handle;
6823         q1.in.resume_handle = &resume_handle;
6824         q1.in.max_size = 5;
6825         q1.out.resume_handle = &resume_handle;
6826         q1.out.num_entries = &num_entries;
6827         q1.out.sam = &sam;
6828
6829         status = STATUS_MORE_ENTRIES;
6830         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6831                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &q1),
6832                         "EnumDomainGroups failed");
6833                 status = q1.out.result;
6834
6835                 if (!NT_STATUS_IS_OK(status) &&
6836                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6837                         break;
6838
6839                 for (i=0; i<*q1.out.num_entries; i++) {
6840                         add_string_to_array(tctx,
6841                                             sam->entries[i].name.string,
6842                                             &names, &num_names);
6843                 }
6844         }
6845
6846         torture_assert_ntstatus_ok(tctx, status, "EnumDomainGroups");
6847
6848         torture_assert(tctx, sam, "EnumDomainGroups failed to return sam");
6849
6850         q2.in.domain_handle = handle;
6851         q2.in.level = 5;
6852         q2.in.start_idx = 0;
6853         q2.in.max_entries = 5;
6854         q2.in.buf_size = (uint32_t)-1;
6855         q2.out.total_size = &total_size;
6856         q2.out.returned_size = &returned_size;
6857         q2.out.info = &info;
6858
6859         status = STATUS_MORE_ENTRIES;
6860         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
6861                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &q2),
6862                         "QueryDisplayInfo failed");
6863                 status = q2.out.result;
6864                 if (!NT_STATUS_IS_OK(status) &&
6865                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
6866                         break;
6867
6868                 for (i=0; i<q2.out.info->info5.count; i++) {
6869                         int j;
6870                         const char *name = q2.out.info->info5.entries[i].account_name.string;
6871                         bool found = false;
6872                         for (j=0; j<num_names; j++) {
6873                                 if (names[j] == NULL)
6874                                         continue;
6875                                 if (strequal(names[j], name)) {
6876                                         names[j] = NULL;
6877                                         found = true;
6878                                         break;
6879                                 }
6880                         }
6881
6882                         if (!found) {
6883                                 torture_warning(tctx, "QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
6884                                        name);
6885                                 ret = false;
6886                         }
6887                 }
6888                 q2.in.start_idx += q2.out.info->info5.count;
6889         }
6890
6891         if (!NT_STATUS_IS_OK(status)) {
6892                 torture_warning(tctx, "QueryDisplayInfo level 5 failed - %s\n",
6893                        nt_errstr(status));
6894                 ret = false;
6895         }
6896
6897         for (i=0; i<num_names; i++) {
6898                 if (names[i] != NULL) {
6899                         torture_warning(tctx, "EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
6900                                names[i]);
6901                         ret = false;
6902                 }
6903         }
6904
6905         return ret;
6906 }
6907
6908 static bool test_DeleteDomainGroup(struct dcerpc_binding_handle *b,
6909                                    struct torture_context *tctx,
6910                                    struct policy_handle *group_handle)
6911 {
6912         struct samr_DeleteDomainGroup d;
6913
6914         torture_comment(tctx, "Testing DeleteDomainGroup\n");
6915
6916         d.in.group_handle = group_handle;
6917         d.out.group_handle = group_handle;
6918
6919         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteDomainGroup_r(b, tctx, &d),
6920                 "DeleteDomainGroup failed");
6921         torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteDomainGroup");
6922
6923         return true;
6924 }
6925
6926 static bool test_TestPrivateFunctionsDomain(struct dcerpc_binding_handle *b,
6927                                             struct torture_context *tctx,
6928                                             struct policy_handle *domain_handle)
6929 {
6930         struct samr_TestPrivateFunctionsDomain r;
6931         bool ret = true;
6932
6933         torture_comment(tctx, "Testing TestPrivateFunctionsDomain\n");
6934
6935         r.in.domain_handle = domain_handle;
6936
6937         torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsDomain_r(b, tctx, &r),
6938                 "TestPrivateFunctionsDomain failed");
6939         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsDomain");
6940
6941         return ret;
6942 }
6943
6944 static bool test_RidToSid(struct dcerpc_binding_handle *b,
6945                           struct torture_context *tctx,
6946                           struct dom_sid *domain_sid,
6947                           struct policy_handle *domain_handle)
6948 {
6949         struct samr_RidToSid r;
6950         bool ret = true;
6951         struct dom_sid *calc_sid, *out_sid;
6952         int rids[] = { 0, 42, 512, 10200 };
6953         int i;
6954
6955         for (i=0;i<ARRAY_SIZE(rids);i++) {
6956                 torture_comment(tctx, "Testing RidToSid\n");
6957
6958                 calc_sid = dom_sid_dup(tctx, domain_sid);
6959                 r.in.domain_handle = domain_handle;
6960                 r.in.rid = rids[i];
6961                 r.out.sid = &out_sid;
6962
6963                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_RidToSid_r(b, tctx, &r),
6964                         "RidToSid failed");
6965                 if (!NT_STATUS_IS_OK(r.out.result)) {
6966                         torture_warning(tctx, "RidToSid for %d failed - %s\n", rids[i], nt_errstr(r.out.result));
6967                         ret = false;
6968                 } else {
6969                         calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
6970
6971                         if (!dom_sid_equal(calc_sid, out_sid)) {
6972                                 torture_warning(tctx, "RidToSid for %d failed - got %s, expected %s\n", rids[i],
6973                                        dom_sid_string(tctx, out_sid),
6974                                        dom_sid_string(tctx, calc_sid));
6975                                 ret = false;
6976                         }
6977                 }
6978         }
6979
6980         return ret;
6981 }
6982
6983 static bool test_GetBootKeyInformation(struct dcerpc_binding_handle *b,
6984                                        struct torture_context *tctx,
6985                                        struct policy_handle *domain_handle)
6986 {
6987         struct samr_GetBootKeyInformation r;
6988         bool ret = true;
6989         uint32_t unknown = 0;
6990         NTSTATUS status;
6991
6992         torture_comment(tctx, "Testing GetBootKeyInformation\n");
6993
6994         r.in.domain_handle = domain_handle;
6995         r.out.unknown = &unknown;
6996
6997         status = dcerpc_samr_GetBootKeyInformation_r(b, tctx, &r);
6998         if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(r.out.result)) {
6999                 status = r.out.result;
7000         }
7001         if (!NT_STATUS_IS_OK(status)) {
7002                 /* w2k3 seems to fail this sometimes and pass it sometimes */
7003                 torture_comment(tctx, "GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
7004         }
7005
7006         return ret;
7007 }
7008
7009 static bool test_AddGroupMember(struct dcerpc_binding_handle *b,
7010                                 struct torture_context *tctx,
7011                                 struct policy_handle *domain_handle,
7012                                 struct policy_handle *group_handle)
7013 {
7014         NTSTATUS status;
7015         struct samr_AddGroupMember r;
7016         struct samr_DeleteGroupMember d;
7017         struct samr_QueryGroupMember q;
7018         struct samr_RidAttrArray *rids = NULL;
7019         struct samr_SetMemberAttributesOfGroup s;
7020         uint32_t rid;
7021         bool found_member = false;
7022         int i;
7023
7024         status = test_LookupName(b, tctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
7025         torture_assert_ntstatus_ok(tctx, status, "test_AddGroupMember looking up name " TEST_ACCOUNT_NAME);
7026
7027         r.in.group_handle = group_handle;
7028         r.in.rid = rid;
7029         r.in.flags = 0; /* ??? */
7030
7031         torture_comment(tctx, "Testing AddGroupMember, QueryGroupMember and DeleteGroupMember\n");
7032
7033         d.in.group_handle = group_handle;
7034         d.in.rid = rid;
7035
7036         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7037                 "DeleteGroupMember failed");
7038         torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_NOT_IN_GROUP, d.out.result, "DeleteGroupMember");
7039
7040         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7041                 "AddGroupMember failed");
7042         torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7043
7044         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7045                 "AddGroupMember failed");
7046         torture_assert_ntstatus_equal(tctx, NT_STATUS_MEMBER_IN_GROUP, r.out.result, "AddGroupMember");
7047
7048         if (torture_setting_bool(tctx, "samba4", false) ||
7049             torture_setting_bool(tctx, "samba3", false)) {
7050                 torture_comment(tctx, "skipping SetMemberAttributesOfGroup test against Samba\n");
7051         } else {
7052                 /* this one is quite strange. I am using random inputs in the
7053                    hope of triggering an error that might give us a clue */
7054
7055                 s.in.group_handle = group_handle;
7056                 s.in.unknown1 = random();
7057                 s.in.unknown2 = random();
7058
7059                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetMemberAttributesOfGroup_r(b, tctx, &s),
7060                         "SetMemberAttributesOfGroup failed");
7061                 torture_assert_ntstatus_ok(tctx, s.out.result, "SetMemberAttributesOfGroup");
7062         }
7063
7064         q.in.group_handle = group_handle;
7065         q.out.rids = &rids;
7066
7067         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7068                 "QueryGroupMember failed");
7069         torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7070         torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7071
7072         for (i=0; i < rids->count; i++) {
7073                 if (rids->rids[i] == rid) {
7074                         found_member = true;
7075                 }
7076         }
7077
7078         torture_assert(tctx, found_member, "QueryGroupMember did not list newly added member");
7079
7080         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteGroupMember_r(b, tctx, &d),
7081                 "DeleteGroupMember failed");
7082         torture_assert_ntstatus_ok(tctx, d.out.result, "DeleteGroupMember");
7083
7084         rids = NULL;
7085         found_member = false;
7086
7087         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryGroupMember_r(b, tctx, &q),
7088                 "QueryGroupMember failed");
7089         torture_assert_ntstatus_ok(tctx, q.out.result, "QueryGroupMember");
7090         torture_assert(tctx, rids, "QueryGroupMember did not fill in rids structure");
7091
7092         for (i=0; i < rids->count; i++) {
7093                 if (rids->rids[i] == rid) {
7094                         found_member = true;
7095                 }
7096         }
7097
7098         torture_assert(tctx, !found_member, "QueryGroupMember does still list removed member");
7099
7100         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddGroupMember_r(b, tctx, &r),
7101                 "AddGroupMember failed");
7102         torture_assert_ntstatus_ok(tctx, r.out.result, "AddGroupMember");
7103
7104         return true;
7105 }
7106
7107
7108 static bool test_CreateDomainGroup(struct dcerpc_binding_handle *b,
7109                                    struct torture_context *tctx,
7110                                    struct policy_handle *domain_handle,
7111                                    const char *group_name,
7112                                    struct policy_handle *group_handle,
7113                                    struct dom_sid *domain_sid,
7114                                    bool test_group)
7115 {
7116         struct samr_CreateDomainGroup r;
7117         uint32_t rid;
7118         struct lsa_String name;
7119         bool ret = true;
7120
7121         init_lsa_String(&name, group_name);
7122
7123         r.in.domain_handle = domain_handle;
7124         r.in.name = &name;
7125         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7126         r.out.group_handle = group_handle;
7127         r.out.rid = &rid;
7128
7129         torture_comment(tctx, "Testing CreateDomainGroup(%s)\n", r.in.name->string);
7130
7131         torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7132                 "CreateDomainGroup failed");
7133
7134         if (dom_sid_equal(domain_sid, dom_sid_parse_talloc(tctx, SID_BUILTIN))) {
7135                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_ACCESS_DENIED)) {
7136                         torture_comment(tctx, "Server correctly refused create of '%s'\n", r.in.name->string);
7137                         return true;
7138                 } else {
7139                         torture_warning(tctx, "Server should have refused create of '%s', got %s instead\n", r.in.name->string,
7140                                nt_errstr(r.out.result));
7141                         return false;
7142                 }
7143         }
7144
7145         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_GROUP_EXISTS)) {
7146                 if (!test_DeleteGroup_byname(b, tctx, domain_handle, r.in.name->string)) {
7147                         torture_warning(tctx, "CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string,
7148                                nt_errstr(r.out.result));
7149                         return false;
7150                 }
7151                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7152                         "CreateDomainGroup failed");
7153         }
7154         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_USER_EXISTS)) {
7155                 if (!test_DeleteUser_byname(b, tctx, domain_handle, r.in.name->string)) {
7156
7157                         torture_warning(tctx, "CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string,
7158                                nt_errstr(r.out.result));
7159                         return false;
7160                 }
7161                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_CreateDomainGroup_r(b, tctx, &r),
7162                         "CreateDomainGroup failed");
7163         }
7164         torture_assert_ntstatus_ok(tctx, r.out.result, "CreateDomainGroup");
7165
7166         if (!test_group) {
7167                 return ret;
7168         }
7169
7170         if (!test_AddGroupMember(b, tctx, domain_handle, group_handle)) {
7171                 torture_warning(tctx, "CreateDomainGroup failed - %s\n", nt_errstr(r.out.result));
7172                 ret = false;
7173         }
7174
7175         if (!test_SetGroupInfo(b, tctx, group_handle)) {
7176                 ret = false;
7177         }
7178
7179         return ret;
7180 }
7181
7182
7183 /*
7184   its not totally clear what this does. It seems to accept any sid you like.
7185 */
7186 static bool test_RemoveMemberFromForeignDomain(struct dcerpc_binding_handle *b,
7187                                                struct torture_context *tctx,
7188                                                struct policy_handle *domain_handle)
7189 {
7190         struct samr_RemoveMemberFromForeignDomain r;
7191
7192         r.in.domain_handle = domain_handle;
7193         r.in.sid = dom_sid_parse_talloc(tctx, "S-1-5-32-12-34-56-78");
7194
7195         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMemberFromForeignDomain_r(b, tctx, &r),
7196                 "RemoveMemberFromForeignDomain failed");
7197         torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMemberFromForeignDomain");
7198
7199         return true;
7200 }
7201
7202 static bool test_EnumDomainUsers(struct dcerpc_binding_handle *b,
7203                                  struct torture_context *tctx,
7204                                  struct policy_handle *domain_handle,
7205                                  uint32_t *total_num_entries_p)
7206 {
7207         NTSTATUS status;
7208         struct samr_EnumDomainUsers r;
7209         uint32_t resume_handle = 0;
7210         uint32_t num_entries = 0;
7211         uint32_t total_num_entries = 0;
7212         struct samr_SamArray *sam;
7213
7214         r.in.domain_handle = domain_handle;
7215         r.in.acct_flags = 0;
7216         r.in.max_size = (uint32_t)-1;
7217         r.in.resume_handle = &resume_handle;
7218
7219         r.out.sam = &sam;
7220         r.out.num_entries = &num_entries;
7221         r.out.resume_handle = &resume_handle;
7222
7223         torture_comment(tctx, "Testing EnumDomainUsers\n");
7224
7225         do {
7226                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainUsers_r(b, tctx, &r),
7227                         "EnumDomainUsers failed");
7228                 if (NT_STATUS_IS_ERR(r.out.result)) {
7229                         torture_assert_ntstatus_ok(tctx, r.out.result,
7230                                 "failed to enumerate users");
7231                 }
7232                 status = r.out.result;
7233
7234                 total_num_entries += num_entries;
7235         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7236
7237         if (total_num_entries_p) {
7238                 *total_num_entries_p = total_num_entries;
7239         }
7240
7241         return true;
7242 }
7243
7244 static bool test_EnumDomainGroups(struct dcerpc_binding_handle *b,
7245                                   struct torture_context *tctx,
7246                                   struct policy_handle *domain_handle,
7247                                   uint32_t *total_num_entries_p)
7248 {
7249         NTSTATUS status;
7250         struct samr_EnumDomainGroups r;
7251         uint32_t resume_handle = 0;
7252         uint32_t num_entries = 0;
7253         uint32_t total_num_entries = 0;
7254         struct samr_SamArray *sam;
7255
7256         r.in.domain_handle = domain_handle;
7257         r.in.max_size = (uint32_t)-1;
7258         r.in.resume_handle = &resume_handle;
7259
7260         r.out.sam = &sam;
7261         r.out.num_entries = &num_entries;
7262         r.out.resume_handle = &resume_handle;
7263
7264         torture_comment(tctx, "Testing EnumDomainGroups\n");
7265
7266         do {
7267                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainGroups_r(b, tctx, &r),
7268                         "EnumDomainGroups failed");
7269                 if (NT_STATUS_IS_ERR(r.out.result)) {
7270                         torture_assert_ntstatus_ok(tctx, r.out.result,
7271                                 "failed to enumerate groups");
7272                 }
7273                 status = r.out.result;
7274
7275                 total_num_entries += num_entries;
7276         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7277
7278         if (total_num_entries_p) {
7279                 *total_num_entries_p = total_num_entries;
7280         }
7281
7282         return true;
7283 }
7284
7285 static bool test_EnumDomainAliases(struct dcerpc_binding_handle *b,
7286                                    struct torture_context *tctx,
7287                                    struct policy_handle *domain_handle,
7288                                    uint32_t *total_num_entries_p)
7289 {
7290         NTSTATUS status;
7291         struct samr_EnumDomainAliases r;
7292         uint32_t resume_handle = 0;
7293         uint32_t num_entries = 0;
7294         uint32_t total_num_entries = 0;
7295         struct samr_SamArray *sam;
7296
7297         r.in.domain_handle = domain_handle;
7298         r.in.max_size = (uint32_t)-1;
7299         r.in.resume_handle = &resume_handle;
7300
7301         r.out.sam = &sam;
7302         r.out.num_entries = &num_entries;
7303         r.out.resume_handle = &resume_handle;
7304
7305         torture_comment(tctx, "Testing EnumDomainAliases\n");
7306
7307         do {
7308                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomainAliases_r(b, tctx, &r),
7309                         "EnumDomainAliases failed");
7310                 if (NT_STATUS_IS_ERR(r.out.result)) {
7311                         torture_assert_ntstatus_ok(tctx, r.out.result,
7312                                 "failed to enumerate aliases");
7313                 }
7314                 status = r.out.result;
7315
7316                 total_num_entries += num_entries;
7317         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7318
7319         if (total_num_entries_p) {
7320                 *total_num_entries_p = total_num_entries;
7321         }
7322
7323         return true;
7324 }
7325
7326 static bool test_QueryDisplayInfo_level(struct dcerpc_binding_handle *b,
7327                                         struct torture_context *tctx,
7328                                         struct policy_handle *handle,
7329                                         uint16_t level,
7330                                         uint32_t *total_num_entries_p)
7331 {
7332         NTSTATUS status;
7333         struct samr_QueryDisplayInfo r;
7334         uint32_t total_num_entries = 0;
7335
7336         r.in.domain_handle = handle;
7337         r.in.level = level;
7338         r.in.start_idx = 0;
7339         r.in.max_entries = (uint32_t)-1;
7340         r.in.buf_size = (uint32_t)-1;
7341
7342         torture_comment(tctx, "Testing QueryDisplayInfo\n");
7343
7344         do {
7345                 uint32_t total_size;
7346                 uint32_t returned_size;
7347                 union samr_DispInfo info;
7348
7349                 r.out.total_size = &total_size;
7350                 r.out.returned_size = &returned_size;
7351                 r.out.info = &info;
7352
7353                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDisplayInfo_r(b, tctx, &r),
7354                         "failed to query displayinfo");
7355                 if (NT_STATUS_IS_ERR(r.out.result)) {
7356                         torture_assert_ntstatus_ok(tctx, r.out.result,
7357                                 "failed to query displayinfo");
7358                 }
7359                 status = r.out.result;
7360
7361                 if (*r.out.returned_size == 0) {
7362                         break;
7363                 }
7364
7365                 switch (r.in.level) {
7366                 case 1:
7367                         total_num_entries += info.info1.count;
7368                         r.in.start_idx += info.info1.entries[info.info1.count - 1].idx + 1;
7369                         break;
7370                 case 2:
7371                         total_num_entries += info.info2.count;
7372                         r.in.start_idx += info.info2.entries[info.info2.count - 1].idx + 1;
7373                         break;
7374                 case 3:
7375                         total_num_entries += info.info3.count;
7376                         r.in.start_idx += info.info3.entries[info.info3.count - 1].idx + 1;
7377                         break;
7378                 case 4:
7379                         total_num_entries += info.info4.count;
7380                         r.in.start_idx += info.info4.entries[info.info4.count - 1].idx + 1;
7381                         break;
7382                 case 5:
7383                         total_num_entries += info.info5.count;
7384                         r.in.start_idx += info.info5.entries[info.info5.count - 1].idx + 1;
7385                         break;
7386                 default:
7387                         return false;
7388                 }
7389
7390         } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
7391
7392         if (total_num_entries_p) {
7393                 *total_num_entries_p = total_num_entries;
7394         }
7395
7396         return true;
7397 }
7398
7399 static bool test_ManyObjects(struct dcerpc_pipe *p,
7400                              struct torture_context *tctx,
7401                              struct policy_handle *domain_handle,
7402                              struct dom_sid *domain_sid,
7403                              struct torture_samr_context *ctx)
7404 {
7405         uint32_t num_total = ctx->num_objects_large_dc;
7406         uint32_t num_enum = 0;
7407         uint32_t num_disp = 0;
7408         uint32_t num_created = 0;
7409         uint32_t num_anounced = 0;
7410         bool ret = true;
7411         uint32_t i;
7412         struct dcerpc_binding_handle *b = p->binding_handle;
7413
7414         struct policy_handle *handles = talloc_zero_array(tctx, struct policy_handle, num_total);
7415
7416         /* query */
7417
7418         {
7419                 struct samr_QueryDomainInfo2 r;
7420                 union samr_DomainInfo *info;
7421                 r.in.domain_handle = domain_handle;
7422                 r.in.level = 2;
7423                 r.out.info = &info;
7424
7425                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryDomainInfo2_r(b, tctx, &r),
7426                         "QueryDomainInfo2 failed");
7427                 torture_assert_ntstatus_ok(tctx, r.out.result,
7428                         "failed to query domain info");
7429
7430                 switch (ctx->choice) {
7431                 case TORTURE_SAMR_MANY_ACCOUNTS:
7432                         num_anounced = info->general.num_users;
7433                         break;
7434                 case TORTURE_SAMR_MANY_GROUPS:
7435                         num_anounced = info->general.num_groups;
7436                         break;
7437                 case TORTURE_SAMR_MANY_ALIASES:
7438                         num_anounced = info->general.num_aliases;
7439                         break;
7440                 default:
7441                         return false;
7442                 }
7443         }
7444
7445         /* create */
7446
7447         for (i=0; i < num_total; i++) {
7448
7449                 const char *name = NULL;
7450
7451                 switch (ctx->choice) {
7452                 case TORTURE_SAMR_MANY_ACCOUNTS:
7453                         name = talloc_asprintf(tctx, "%s%04d", TEST_ACCOUNT_NAME, i);
7454                         ret &= test_CreateUser(p, tctx, domain_handle, name, &handles[i], domain_sid, 0, NULL, false);
7455                         break;
7456                 case TORTURE_SAMR_MANY_GROUPS:
7457                         name = talloc_asprintf(tctx, "%s%04d", TEST_GROUPNAME, i);
7458                         ret &= test_CreateDomainGroup(b, tctx, domain_handle, name, &handles[i], domain_sid, false);
7459                         break;
7460                 case TORTURE_SAMR_MANY_ALIASES:
7461                         name = talloc_asprintf(tctx, "%s%04d", TEST_ALIASNAME, i);
7462                         ret &= test_CreateAlias(b, tctx, domain_handle, name, &handles[i], domain_sid, false);
7463                         break;
7464                 default:
7465                         return false;
7466                 }
7467                 if (!policy_handle_empty(&handles[i])) {
7468                         num_created++;
7469                 }
7470         }
7471
7472         /* enum */
7473
7474         switch (ctx->choice) {
7475         case TORTURE_SAMR_MANY_ACCOUNTS:
7476                 ret &= test_EnumDomainUsers(b, tctx, domain_handle, &num_enum);
7477                 break;
7478         case TORTURE_SAMR_MANY_GROUPS:
7479                 ret &= test_EnumDomainGroups(b, tctx, domain_handle, &num_enum);
7480                 break;
7481         case TORTURE_SAMR_MANY_ALIASES:
7482                 ret &= test_EnumDomainAliases(b, tctx, domain_handle, &num_enum);
7483                 break;
7484         default:
7485                 return false;
7486         }
7487
7488         /* dispinfo */
7489
7490         switch (ctx->choice) {
7491         case TORTURE_SAMR_MANY_ACCOUNTS:
7492                 ret &= test_QueryDisplayInfo_level(b, tctx, domain_handle, 1, &num_disp);
7493                 break;
7494         case TORTURE_SAMR_MANY_GROUPS:
7495                 ret &= test_QueryDisplayInfo_level(b, tctx, domain_handle, 3, &num_disp);
7496                 break;
7497         case TORTURE_SAMR_MANY_ALIASES:
7498                 /* no aliases in dispinfo */
7499                 break;
7500         default:
7501                 return false;
7502         }
7503
7504         /* close or delete */
7505
7506         for (i=0; i < num_total; i++) {
7507
7508                 if (policy_handle_empty(&handles[i])) {
7509                         continue;
7510                 }
7511
7512                 if (torture_setting_bool(tctx, "samba3", false)) {
7513                         ret &= test_samr_handle_Close(b, tctx, &handles[i]);
7514                 } else {
7515                         switch (ctx->choice) {
7516                         case TORTURE_SAMR_MANY_ACCOUNTS:
7517                                 ret &= test_DeleteUser(b, tctx, &handles[i]);
7518                                 break;
7519                         case TORTURE_SAMR_MANY_GROUPS:
7520                                 ret &= test_DeleteDomainGroup(b, tctx, &handles[i]);
7521                                 break;
7522                         case TORTURE_SAMR_MANY_ALIASES:
7523                                 ret &= test_DeleteAlias(b, tctx, &handles[i]);
7524                                 break;
7525                         default:
7526                                 return false;
7527                         }
7528                 }
7529         }
7530
7531         talloc_free(handles);
7532
7533         if (ctx->choice == TORTURE_SAMR_MANY_ACCOUNTS && num_enum != num_anounced + num_created) {
7534                 torture_comment(tctx,
7535                                 "unexpected number of results (%u) returned in enum call, expected %u\n",
7536                                 num_enum, num_anounced + num_created);
7537
7538                 torture_comment(tctx,
7539                                 "unexpected number of results (%u) returned in dispinfo, call, expected %u\n",
7540                                 num_disp, num_anounced + num_created);
7541         }
7542         return ret;
7543 }
7544
7545 static bool test_Connect(struct dcerpc_binding_handle *b,
7546                          struct torture_context *tctx,
7547                          struct policy_handle *handle);
7548
7549 static bool test_OpenDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7550                             struct torture_samr_context *ctx, struct dom_sid *sid)
7551 {
7552         struct samr_OpenDomain r;
7553         struct policy_handle domain_handle;
7554         struct policy_handle alias_handle;
7555         struct policy_handle user_handle;
7556         struct policy_handle group_handle;
7557         bool ret = true;
7558         struct dcerpc_binding_handle *b = p->binding_handle;
7559
7560         ZERO_STRUCT(alias_handle);
7561         ZERO_STRUCT(user_handle);
7562         ZERO_STRUCT(group_handle);
7563         ZERO_STRUCT(domain_handle);
7564
7565         torture_comment(tctx, "Testing OpenDomain of %s\n", dom_sid_string(tctx, sid));
7566
7567         r.in.connect_handle = &ctx->handle;
7568         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7569         r.in.sid = sid;
7570         r.out.domain_handle = &domain_handle;
7571
7572         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OpenDomain_r(b, tctx, &r),
7573                 "OpenDomain failed");
7574         torture_assert_ntstatus_ok(tctx, r.out.result, "OpenDomain failed");
7575
7576         /* run the domain tests with the main handle closed - this tests
7577            the servers reference counting */
7578         torture_assert(tctx, test_samr_handle_Close(b, tctx, &ctx->handle), "Failed to close SAMR handle");
7579
7580         switch (ctx->choice) {
7581         case TORTURE_SAMR_PASSWORDS:
7582         case TORTURE_SAMR_USER_PRIVILEGES:
7583                 if (!torture_setting_bool(tctx, "samba3", false)) {
7584                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7585                 }
7586                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7587                 if (!ret) {
7588                         torture_warning(tctx, "Testing PASSWORDS or PRIVILEGES on domain %s failed!\n", dom_sid_string(tctx, sid));
7589                 }
7590                 break;
7591         case TORTURE_SAMR_USER_ATTRIBUTES:
7592                 if (!torture_setting_bool(tctx, "samba3", false)) {
7593                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, NULL);
7594                 }
7595                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7596                 /* This test needs 'complex' users to validate */
7597                 ret &= test_QueryDisplayInfo(b, tctx, &domain_handle);
7598                 if (!ret) {
7599                         torture_warning(tctx, "Testing ATTRIBUTES on domain %s failed!\n", dom_sid_string(tctx, sid));
7600                 }
7601                 break;
7602         case TORTURE_SAMR_PASSWORDS_PWDLASTSET:
7603         case TORTURE_SAMR_PASSWORDS_BADPWDCOUNT:
7604         case TORTURE_SAMR_PASSWORDS_LOCKOUT:
7605                 if (!torture_setting_bool(tctx, "samba3", false)) {
7606                         ret &= test_CreateUser2(p, tctx, &domain_handle, sid, ctx->choice, ctx->machine_credentials);
7607                 }
7608                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, ctx->machine_credentials, true);
7609                 if (!ret) {
7610                         torture_warning(tctx, "Testing PASSWORDS PWDLASTSET or BADPWDCOUNT on domain %s failed!\n", dom_sid_string(tctx, sid));
7611                 }
7612                 break;
7613         case TORTURE_SAMR_MANY_ACCOUNTS:
7614         case TORTURE_SAMR_MANY_GROUPS:
7615         case TORTURE_SAMR_MANY_ALIASES:
7616                 ret &= test_ManyObjects(p, tctx, &domain_handle, sid, ctx);
7617                 if (!ret) {
7618                         torture_warning(tctx, "Testing MANY-{ACCOUNTS,GROUPS,ALIASES} on domain %s failed!\n", dom_sid_string(tctx, sid));
7619                 }
7620                 break;
7621         case TORTURE_SAMR_OTHER:
7622                 ret &= test_CreateUser(p, tctx, &domain_handle, TEST_ACCOUNT_NAME, &user_handle, sid, ctx->choice, NULL, true);
7623                 if (!ret) {
7624                         torture_warning(tctx, "Failed to CreateUser in SAMR-OTHER on domain %s!\n", dom_sid_string(tctx, sid));
7625                 }
7626                 if (!torture_setting_bool(tctx, "samba3", false)) {
7627                         ret &= test_QuerySecurity(b, tctx, &domain_handle);
7628                 }
7629                 ret &= test_RemoveMemberFromForeignDomain(b, tctx, &domain_handle);
7630                 ret &= test_CreateAlias(b, tctx, &domain_handle, TEST_ALIASNAME, &alias_handle, sid, true);
7631                 ret &= test_CreateDomainGroup(b, tctx, &domain_handle, TEST_GROUPNAME, &group_handle, sid, true);
7632                 ret &= test_GetAliasMembership(b, tctx, &domain_handle);
7633                 ret &= test_QueryDomainInfo(p, tctx, &domain_handle);
7634                 ret &= test_QueryDomainInfo2(b, tctx, &domain_handle);
7635                 ret &= test_EnumDomainUsers_all(b, tctx, &domain_handle);
7636                 ret &= test_EnumDomainUsers_async(p, tctx, &domain_handle);
7637                 ret &= test_EnumDomainGroups_all(b, tctx, &domain_handle);
7638                 ret &= test_EnumDomainAliases_all(b, tctx, &domain_handle);
7639                 ret &= test_QueryDisplayInfo2(b, tctx, &domain_handle);
7640                 ret &= test_QueryDisplayInfo3(b, tctx, &domain_handle);
7641                 ret &= test_QueryDisplayInfo_continue(b, tctx, &domain_handle);
7642
7643                 if (torture_setting_bool(tctx, "samba4", false)) {
7644                         torture_comment(tctx, "skipping GetDisplayEnumerationIndex test against Samba4\n");
7645                 } else {
7646                         ret &= test_GetDisplayEnumerationIndex(b, tctx, &domain_handle);
7647                         ret &= test_GetDisplayEnumerationIndex2(b, tctx, &domain_handle);
7648                 }
7649                 ret &= test_GroupList(b, tctx, &domain_handle);
7650                 ret &= test_TestPrivateFunctionsDomain(b, tctx, &domain_handle);
7651                 ret &= test_RidToSid(b, tctx, sid, &domain_handle);
7652                 ret &= test_GetBootKeyInformation(b, tctx, &domain_handle);
7653                 if (!ret) {
7654                         torture_comment(tctx, "Testing SAMR-OTHER on domain %s failed!\n", dom_sid_string(tctx, sid));
7655                 }
7656                 break;
7657         }
7658
7659         if (!policy_handle_empty(&user_handle) &&
7660             !test_DeleteUser(b, tctx, &user_handle)) {
7661                 ret = false;
7662         }
7663
7664         if (!policy_handle_empty(&alias_handle) &&
7665             !test_DeleteAlias(b, tctx, &alias_handle)) {
7666                 ret = false;
7667         }
7668
7669         if (!policy_handle_empty(&group_handle) &&
7670             !test_DeleteDomainGroup(b, tctx, &group_handle)) {
7671                 ret = false;
7672         }
7673
7674         torture_assert(tctx, test_samr_handle_Close(b, tctx, &domain_handle), "Failed to close SAMR domain handle");
7675
7676         torture_assert(tctx, test_Connect(b, tctx, &ctx->handle), "Faile to re-connect SAMR handle");
7677         /* reconnect the main handle */
7678
7679         if (!ret) {
7680                 torture_warning(tctx, "Testing domain %s failed!\n", dom_sid_string(tctx, sid));
7681         }
7682
7683         return ret;
7684 }
7685
7686 static bool test_LookupDomain(struct dcerpc_pipe *p, struct torture_context *tctx,
7687                               struct torture_samr_context *ctx, const char *domain)
7688 {
7689         struct samr_LookupDomain r;
7690         struct dom_sid2 *sid = NULL;
7691         struct lsa_String n1;
7692         struct lsa_String n2;
7693         bool ret = true;
7694         struct dcerpc_binding_handle *b = p->binding_handle;
7695
7696         torture_comment(tctx, "Testing LookupDomain(%s)\n", domain);
7697
7698         /* check for correct error codes */
7699         r.in.connect_handle = &ctx->handle;
7700         r.in.domain_name = &n2;
7701         r.out.sid = &sid;
7702         n2.string = NULL;
7703
7704         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7705                 "LookupDomain failed");
7706         torture_assert_ntstatus_equal(tctx, NT_STATUS_INVALID_PARAMETER, r.out.result, "LookupDomain expected NT_STATUS_INVALID_PARAMETER");
7707
7708         init_lsa_String(&n2, "xxNODOMAINxx");
7709
7710         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7711                 "LookupDomain failed");
7712         torture_assert_ntstatus_equal(tctx, NT_STATUS_NO_SUCH_DOMAIN, r.out.result, "LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN");
7713
7714         r.in.connect_handle = &ctx->handle;
7715
7716         init_lsa_String(&n1, domain);
7717         r.in.domain_name = &n1;
7718
7719         torture_assert_ntstatus_ok(tctx, dcerpc_samr_LookupDomain_r(b, tctx, &r),
7720                 "LookupDomain failed");
7721         torture_assert_ntstatus_ok(tctx, r.out.result, "LookupDomain");
7722
7723         if (!test_GetDomPwInfo(p, tctx, &n1)) {
7724                 ret = false;
7725         }
7726
7727         if (!test_OpenDomain(p, tctx, ctx, *r.out.sid)) {
7728                 ret = false;
7729         }
7730
7731         return ret;
7732 }
7733
7734
7735 static bool test_EnumDomains(struct dcerpc_pipe *p, struct torture_context *tctx,
7736                              struct torture_samr_context *ctx)
7737 {
7738         struct samr_EnumDomains r;
7739         uint32_t resume_handle = 0;
7740         uint32_t num_entries = 0;
7741         struct samr_SamArray *sam = NULL;
7742         int i;
7743         bool ret = true;
7744         struct dcerpc_binding_handle *b = p->binding_handle;
7745
7746         r.in.connect_handle = &ctx->handle;
7747         r.in.resume_handle = &resume_handle;
7748         r.in.buf_size = (uint32_t)-1;
7749         r.out.resume_handle = &resume_handle;
7750         r.out.num_entries = &num_entries;
7751         r.out.sam = &sam;
7752
7753         torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7754                 "EnumDomains failed");
7755         torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7756
7757         if (!*r.out.sam) {
7758                 return false;
7759         }
7760
7761         for (i=0;i<sam->count;i++) {
7762                 if (!test_LookupDomain(p, tctx, ctx,
7763                                        sam->entries[i].name.string)) {
7764                         ret = false;
7765                 }
7766         }
7767
7768         torture_assert_ntstatus_ok(tctx, dcerpc_samr_EnumDomains_r(b, tctx, &r),
7769                 "EnumDomains failed");
7770         torture_assert_ntstatus_ok(tctx, r.out.result, "EnumDomains failed");
7771
7772         return ret;
7773 }
7774
7775
7776 static bool test_Connect(struct dcerpc_binding_handle *b,
7777                          struct torture_context *tctx,
7778                          struct policy_handle *handle)
7779 {
7780         struct samr_Connect r;
7781         struct samr_Connect2 r2;
7782         struct samr_Connect3 r3;
7783         struct samr_Connect4 r4;
7784         struct samr_Connect5 r5;
7785         union samr_ConnectInfo info;
7786         struct policy_handle h;
7787         uint32_t level_out = 0;
7788         bool ret = true, got_handle = false;
7789
7790         torture_comment(tctx, "Testing samr_Connect\n");
7791
7792         r.in.system_name = 0;
7793         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7794         r.out.connect_handle = &h;
7795
7796         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect_r(b, tctx, &r),
7797                 "Connect failed");
7798         if (!NT_STATUS_IS_OK(r.out.result)) {
7799                 torture_comment(tctx, "Connect failed - %s\n", nt_errstr(r.out.result));
7800                 ret = false;
7801         } else {
7802                 got_handle = true;
7803                 *handle = h;
7804         }
7805
7806         torture_comment(tctx, "Testing samr_Connect2\n");
7807
7808         r2.in.system_name = NULL;
7809         r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7810         r2.out.connect_handle = &h;
7811
7812         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect2_r(b, tctx, &r2),
7813                 "Connect2 failed");
7814         if (!NT_STATUS_IS_OK(r2.out.result)) {
7815                 torture_comment(tctx, "Connect2 failed - %s\n", nt_errstr(r2.out.result));
7816                 ret = false;
7817         } else {
7818                 if (got_handle) {
7819                         test_samr_handle_Close(b, tctx, handle);
7820                 }
7821                 got_handle = true;
7822                 *handle = h;
7823         }
7824
7825         torture_comment(tctx, "Testing samr_Connect3\n");
7826
7827         r3.in.system_name = NULL;
7828         r3.in.unknown = 0;
7829         r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7830         r3.out.connect_handle = &h;
7831
7832         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect3_r(b, tctx, &r3),
7833                 "Connect3 failed");
7834         if (!NT_STATUS_IS_OK(r3.out.result)) {
7835                 torture_warning(tctx, "Connect3 failed - %s\n", nt_errstr(r3.out.result));
7836                 ret = false;
7837         } else {
7838                 if (got_handle) {
7839                         test_samr_handle_Close(b, tctx, handle);
7840                 }
7841                 got_handle = true;
7842                 *handle = h;
7843         }
7844
7845         torture_comment(tctx, "Testing samr_Connect4\n");
7846
7847         r4.in.system_name = "";
7848         r4.in.client_version = 0;
7849         r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7850         r4.out.connect_handle = &h;
7851
7852         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect4_r(b, tctx, &r4),
7853                 "Connect4 failed");
7854         if (!NT_STATUS_IS_OK(r4.out.result)) {
7855                 torture_warning(tctx, "Connect4 failed - %s\n", nt_errstr(r4.out.result));
7856                 ret = false;
7857         } else {
7858                 if (got_handle) {
7859                         test_samr_handle_Close(b, tctx, handle);
7860                 }
7861                 got_handle = true;
7862                 *handle = h;
7863         }
7864
7865         torture_comment(tctx, "Testing samr_Connect5\n");
7866
7867         info.info1.client_version = 0;
7868         info.info1.unknown2 = 0;
7869
7870         r5.in.system_name = "";
7871         r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
7872         r5.in.level_in = 1;
7873         r5.out.level_out = &level_out;
7874         r5.in.info_in = &info;
7875         r5.out.info_out = &info;
7876         r5.out.connect_handle = &h;
7877
7878         torture_assert_ntstatus_ok(tctx, dcerpc_samr_Connect5_r(b, tctx, &r5),
7879                 "Connect5 failed");
7880         if (!NT_STATUS_IS_OK(r5.out.result)) {
7881                 torture_warning(tctx, "Connect5 failed - %s\n", nt_errstr(r5.out.result));
7882                 ret = false;
7883         } else {
7884                 if (got_handle) {
7885                         test_samr_handle_Close(b, tctx, handle);
7886                 }
7887                 got_handle = true;
7888                 *handle = h;
7889         }
7890
7891         return ret;
7892 }
7893
7894
7895 static bool test_samr_ValidatePassword(struct dcerpc_pipe *p,
7896                                        struct torture_context *tctx)
7897 {
7898         struct samr_ValidatePassword r;
7899         union samr_ValidatePasswordReq req;
7900         union samr_ValidatePasswordRep *repp = NULL;
7901         NTSTATUS status;
7902         const char *passwords[] = { "penguin", "p@ssw0rd", "p@ssw0rd123$", NULL };
7903         int i;
7904         struct dcerpc_binding_handle *b = p->binding_handle;
7905
7906         torture_comment(tctx, "Testing samr_ValidatePassword\n");
7907
7908         ZERO_STRUCT(r);
7909         r.in.level = NetValidatePasswordReset;
7910         r.in.req = &req;
7911         r.out.rep = &repp;
7912
7913         ZERO_STRUCT(req);
7914         req.req3.account.string = "non-existant-account-aklsdji";
7915
7916         for (i=0; passwords[i]; i++) {
7917                 req.req3.password.string = passwords[i];
7918
7919                 status = dcerpc_samr_ValidatePassword_r(b, tctx, &r);
7920                 if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
7921                         torture_skip(tctx, "ValidatePassword not supported by server\n");
7922                 }
7923                 torture_assert_ntstatus_ok(tctx, status,
7924                                            "samr_ValidatePassword failed");
7925                 torture_assert_ntstatus_ok(tctx, r.out.result,
7926                                            "samr_ValidatePassword failed");
7927                 torture_comment(tctx, "Server %s password '%s' with code %i\n",
7928                                 repp->ctr3.status==SAMR_VALIDATION_STATUS_SUCCESS?"allowed":"refused",
7929                                 req.req3.password.string, repp->ctr3.status);
7930         }
7931
7932         return true;
7933 }
7934
7935 bool torture_rpc_samr(struct torture_context *torture)
7936 {
7937         NTSTATUS status;
7938         struct dcerpc_pipe *p;
7939         bool ret = true;
7940         struct torture_samr_context *ctx;
7941         struct dcerpc_binding_handle *b;
7942
7943         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7944         if (!NT_STATUS_IS_OK(status)) {
7945                 return false;
7946         }
7947         b = p->binding_handle;
7948
7949         ctx = talloc_zero(torture, struct torture_samr_context);
7950
7951         ctx->choice = TORTURE_SAMR_OTHER;
7952
7953         ret &= test_Connect(b, torture, &ctx->handle);
7954
7955         if (!torture_setting_bool(torture, "samba3", false)) {
7956                 ret &= test_QuerySecurity(b, torture, &ctx->handle);
7957         }
7958
7959         ret &= test_EnumDomains(p, torture, ctx);
7960
7961         ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
7962
7963         ret &= test_Shutdown(b, torture, &ctx->handle);
7964
7965         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
7966
7967         return ret;
7968 }
7969
7970
7971 bool torture_rpc_samr_users(struct torture_context *torture)
7972 {
7973         NTSTATUS status;
7974         struct dcerpc_pipe *p;
7975         bool ret = true;
7976         struct torture_samr_context *ctx;
7977         struct dcerpc_binding_handle *b;
7978
7979         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
7980         if (!NT_STATUS_IS_OK(status)) {
7981                 return false;
7982         }
7983         b = p->binding_handle;
7984
7985         ctx = talloc_zero(torture, struct torture_samr_context);
7986
7987         ctx->choice = TORTURE_SAMR_USER_ATTRIBUTES;
7988
7989         ret &= test_Connect(b, torture, &ctx->handle);
7990
7991         if (!torture_setting_bool(torture, "samba3", false)) {
7992                 ret &= test_QuerySecurity(b, torture, &ctx->handle);
7993         }
7994
7995         ret &= test_EnumDomains(p, torture, ctx);
7996
7997         ret &= test_SetDsrmPassword(b, torture, &ctx->handle);
7998
7999         ret &= test_Shutdown(b, torture, &ctx->handle);
8000
8001         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8002
8003         return ret;
8004 }
8005
8006
8007 bool torture_rpc_samr_passwords(struct torture_context *torture)
8008 {
8009         NTSTATUS status;
8010         struct dcerpc_pipe *p;
8011         bool ret = true;
8012         struct torture_samr_context *ctx;
8013         struct dcerpc_binding_handle *b;
8014
8015         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8016         if (!NT_STATUS_IS_OK(status)) {
8017                 return false;
8018         }
8019         b = p->binding_handle;
8020
8021         ctx = talloc_zero(torture, struct torture_samr_context);
8022
8023         ctx->choice = TORTURE_SAMR_PASSWORDS;
8024
8025         ret &= test_Connect(b, torture, &ctx->handle);
8026
8027         ret &= test_EnumDomains(p, torture, ctx);
8028
8029         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8030
8031         ret &= test_samr_ValidatePassword(p, torture);
8032
8033         return ret;
8034 }
8035
8036 static bool torture_rpc_samr_pwdlastset(struct torture_context *torture,
8037                                         struct dcerpc_pipe *p2,
8038                                         struct cli_credentials *machine_credentials)
8039 {
8040         NTSTATUS status;
8041         struct dcerpc_pipe *p;
8042         bool ret = true;
8043         struct torture_samr_context *ctx;
8044         struct dcerpc_binding_handle *b;
8045
8046         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8047         if (!NT_STATUS_IS_OK(status)) {
8048                 return false;
8049         }
8050         b = p->binding_handle;
8051
8052         ctx = talloc_zero(torture, struct torture_samr_context);
8053
8054         ctx->choice = TORTURE_SAMR_PASSWORDS_PWDLASTSET;
8055         ctx->machine_credentials = machine_credentials;
8056
8057         ret &= test_Connect(b, torture, &ctx->handle);
8058
8059         ret &= test_EnumDomains(p, torture, ctx);
8060
8061         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8062
8063         return ret;
8064 }
8065
8066 struct torture_suite *torture_rpc_samr_passwords_pwdlastset(TALLOC_CTX *mem_ctx)
8067 {
8068         struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.pwdlastset");
8069         struct torture_rpc_tcase *tcase;
8070
8071         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8072                                                           &ndr_table_samr,
8073                                                           TEST_ACCOUNT_NAME_PWD);
8074
8075         torture_rpc_tcase_add_test_creds(tcase, "pwdLastSet",
8076                                          torture_rpc_samr_pwdlastset);
8077
8078         return suite;
8079 }
8080
8081 static bool torture_rpc_samr_users_privileges_delete_user(struct torture_context *torture,
8082                                                           struct dcerpc_pipe *p2,
8083                                                           struct cli_credentials *machine_credentials)
8084 {
8085         NTSTATUS status;
8086         struct dcerpc_pipe *p;
8087         bool ret = true;
8088         struct torture_samr_context *ctx;
8089         struct dcerpc_binding_handle *b;
8090
8091         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8092         if (!NT_STATUS_IS_OK(status)) {
8093                 return false;
8094         }
8095         b = p->binding_handle;
8096
8097         ctx = talloc_zero(torture, struct torture_samr_context);
8098
8099         ctx->choice = TORTURE_SAMR_USER_PRIVILEGES;
8100         ctx->machine_credentials = machine_credentials;
8101
8102         ret &= test_Connect(b, torture, &ctx->handle);
8103
8104         ret &= test_EnumDomains(p, torture, ctx);
8105
8106         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8107
8108         return ret;
8109 }
8110
8111 struct torture_suite *torture_rpc_samr_user_privileges(TALLOC_CTX *mem_ctx)
8112 {
8113         struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.users.privileges");
8114         struct torture_rpc_tcase *tcase;
8115
8116         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8117                                                           &ndr_table_samr,
8118                                                           TEST_ACCOUNT_NAME_PWD);
8119
8120         torture_rpc_tcase_add_test_creds(tcase, "delete_privileged_user",
8121                                          torture_rpc_samr_users_privileges_delete_user);
8122
8123         return suite;
8124 }
8125
8126 static bool torture_rpc_samr_many_accounts(struct torture_context *torture,
8127                                            struct dcerpc_pipe *p2,
8128                                            void *data)
8129 {
8130         NTSTATUS status;
8131         struct dcerpc_pipe *p;
8132         bool ret = true;
8133         struct torture_samr_context *ctx =
8134                 talloc_get_type_abort(data, struct torture_samr_context);
8135         struct dcerpc_binding_handle *b;
8136
8137         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8138         if (!NT_STATUS_IS_OK(status)) {
8139                 return false;
8140         }
8141         b = p->binding_handle;
8142
8143         ctx->choice = TORTURE_SAMR_MANY_ACCOUNTS;
8144         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8145                                                         ctx->num_objects_large_dc);
8146
8147         ret &= test_Connect(b, torture, &ctx->handle);
8148
8149         ret &= test_EnumDomains(p, torture, ctx);
8150
8151         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8152
8153         return ret;
8154 }
8155
8156 static bool torture_rpc_samr_many_groups(struct torture_context *torture,
8157                                          struct dcerpc_pipe *p2,
8158                                          void *data)
8159 {
8160         NTSTATUS status;
8161         struct dcerpc_pipe *p;
8162         bool ret = true;
8163         struct torture_samr_context *ctx =
8164                 talloc_get_type_abort(data, struct torture_samr_context);
8165         struct dcerpc_binding_handle *b;
8166
8167         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8168         if (!NT_STATUS_IS_OK(status)) {
8169                 return false;
8170         }
8171         b = p->binding_handle;
8172
8173         ctx->choice = TORTURE_SAMR_MANY_GROUPS;
8174         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8175                                                         ctx->num_objects_large_dc);
8176
8177         ret &= test_Connect(b, torture, &ctx->handle);
8178
8179         ret &= test_EnumDomains(p, torture, ctx);
8180
8181         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8182
8183         return ret;
8184 }
8185
8186 static bool torture_rpc_samr_many_aliases(struct torture_context *torture,
8187                                           struct dcerpc_pipe *p2,
8188                                           void *data)
8189 {
8190         NTSTATUS status;
8191         struct dcerpc_pipe *p;
8192         bool ret = true;
8193         struct torture_samr_context *ctx =
8194                 talloc_get_type_abort(data, struct torture_samr_context);
8195         struct dcerpc_binding_handle *b;
8196
8197         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8198         if (!NT_STATUS_IS_OK(status)) {
8199                 return false;
8200         }
8201         b = p->binding_handle;
8202
8203         ctx->choice = TORTURE_SAMR_MANY_ALIASES;
8204         ctx->num_objects_large_dc = torture_setting_int(torture, "large_dc",
8205                                                         ctx->num_objects_large_dc);
8206
8207         ret &= test_Connect(b, torture, &ctx->handle);
8208
8209         ret &= test_EnumDomains(p, torture, ctx);
8210
8211         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8212
8213         return ret;
8214 }
8215
8216 struct torture_suite *torture_rpc_samr_large_dc(TALLOC_CTX *mem_ctx)
8217 {
8218         struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.large-dc");
8219         struct torture_rpc_tcase *tcase;
8220         struct torture_samr_context *ctx;
8221
8222         tcase = torture_suite_add_rpc_iface_tcase(suite, "samr", &ndr_table_samr);
8223
8224         ctx = talloc_zero(suite, struct torture_samr_context);
8225         ctx->num_objects_large_dc = 150;
8226
8227         torture_rpc_tcase_add_test_ex(tcase, "many_aliases",
8228                                       torture_rpc_samr_many_aliases, ctx);
8229         torture_rpc_tcase_add_test_ex(tcase, "many_groups",
8230                                       torture_rpc_samr_many_groups, ctx);
8231         torture_rpc_tcase_add_test_ex(tcase, "many_accounts",
8232                                       torture_rpc_samr_many_accounts, ctx);
8233
8234         return suite;
8235 }
8236
8237 static bool torture_rpc_samr_badpwdcount(struct torture_context *torture,
8238                                          struct dcerpc_pipe *p2,
8239                                          struct cli_credentials *machine_credentials)
8240 {
8241         NTSTATUS status;
8242         struct dcerpc_pipe *p;
8243         bool ret = true;
8244         struct torture_samr_context *ctx;
8245         struct dcerpc_binding_handle *b;
8246
8247         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8248         if (!NT_STATUS_IS_OK(status)) {
8249                 return false;
8250         }
8251         b = p->binding_handle;
8252
8253         ctx = talloc_zero(torture, struct torture_samr_context);
8254
8255         ctx->choice = TORTURE_SAMR_PASSWORDS_BADPWDCOUNT;
8256         ctx->machine_credentials = machine_credentials;
8257
8258         ret &= test_Connect(b, torture, &ctx->handle);
8259
8260         ret &= test_EnumDomains(p, torture, ctx);
8261
8262         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8263
8264         return ret;
8265 }
8266
8267 struct torture_suite *torture_rpc_samr_passwords_badpwdcount(TALLOC_CTX *mem_ctx)
8268 {
8269         struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.badpwdcount");
8270         struct torture_rpc_tcase *tcase;
8271
8272         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8273                                                           &ndr_table_samr,
8274                                                           TEST_ACCOUNT_NAME_PWD);
8275
8276         torture_rpc_tcase_add_test_creds(tcase, "badPwdCount",
8277                                          torture_rpc_samr_badpwdcount);
8278
8279         return suite;
8280 }
8281
8282 static bool torture_rpc_samr_lockout(struct torture_context *torture,
8283                                      struct dcerpc_pipe *p2,
8284                                      struct cli_credentials *machine_credentials)
8285 {
8286         NTSTATUS status;
8287         struct dcerpc_pipe *p;
8288         bool ret = true;
8289         struct torture_samr_context *ctx;
8290         struct dcerpc_binding_handle *b;
8291
8292         status = torture_rpc_connection(torture, &p, &ndr_table_samr);
8293         if (!NT_STATUS_IS_OK(status)) {
8294                 return false;
8295         }
8296         b = p->binding_handle;
8297
8298         ctx = talloc_zero(torture, struct torture_samr_context);
8299
8300         ctx->choice = TORTURE_SAMR_PASSWORDS_LOCKOUT;
8301         ctx->machine_credentials = machine_credentials;
8302
8303         ret &= test_Connect(b, torture, &ctx->handle);
8304
8305         ret &= test_EnumDomains(p, torture, ctx);
8306
8307         ret &= test_samr_handle_Close(b, torture, &ctx->handle);
8308
8309         return ret;
8310 }
8311
8312 struct torture_suite *torture_rpc_samr_passwords_lockout(TALLOC_CTX *mem_ctx)
8313 {
8314         struct torture_suite *suite = torture_suite_create(mem_ctx, "samr.passwords.lockout");
8315         struct torture_rpc_tcase *tcase;
8316
8317         tcase = torture_suite_add_machine_bdc_rpc_iface_tcase(suite, "samr",
8318                                                           &ndr_table_samr,
8319                                                           TEST_ACCOUNT_NAME_PWD);
8320
8321         torture_rpc_tcase_add_test_creds(tcase, "lockout",
8322                                          torture_rpc_samr_lockout);
8323
8324         return suite;
8325 }
8326
8327