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