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