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