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