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