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