8545df76ea291a52a767208b3eda7c472468ed4e
[garming/samba-autobuild/.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_samr_c.h"
27 #include "lib/crypto/crypto.h"
28 #include "libcli/auth/libcli_auth.h"
29 #include "libcli/security/security.h"
30 #include "torture/rpc/rpc.h"
31
32 #define TEST_ACCOUNT_NAME "samrtorturetest"
33 #define TEST_ALIASNAME "samrtorturetestalias"
34 #define TEST_GROUPNAME "samrtorturetestgroup"
35 #define TEST_MACHINENAME "samrtestmach$"
36 #define TEST_DOMAINNAME "samrtestdom$"
37
38 enum torture_samr_choice {
39         TORTURE_SAMR_PASSWORDS,
40         TORTURE_SAMR_USER_ATTRIBUTES,
41         TORTURE_SAMR_OTHER
42 };
43
44 static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
45                                struct policy_handle *handle);
46
47 static BOOL test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
48                                 struct policy_handle *handle);
49
50 static BOOL test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
51                                struct policy_handle *handle);
52
53 static BOOL test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
54                                 const char *acct_name, 
55                                 struct policy_handle *domain_handle, char **password);
56
57 static void init_lsa_String(struct lsa_String *string, const char *s)
58 {
59         string->string = s;
60 }
61
62 BOOL test_samr_handle_Close(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
63                                    struct policy_handle *handle)
64 {
65         NTSTATUS status;
66         struct samr_Close r;
67
68         r.in.handle = handle;
69         r.out.handle = handle;
70
71         status = dcerpc_samr_Close(p, mem_ctx, &r);
72         if (!NT_STATUS_IS_OK(status)) {
73                 printf("Close handle failed - %s\n", nt_errstr(status));
74                 return False;
75         }
76
77         return True;
78 }
79
80 static BOOL test_Shutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
81                        struct policy_handle *handle)
82 {
83         NTSTATUS status;
84         struct samr_Shutdown r;
85
86         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
87                 printf("samr_Shutdown disabled - enable dangerous tests to use\n");
88                 return True;
89         }
90
91         r.in.connect_handle = handle;
92
93         printf("testing samr_Shutdown\n");
94
95         status = dcerpc_samr_Shutdown(p, mem_ctx, &r);
96         if (!NT_STATUS_IS_OK(status)) {
97                 printf("samr_Shutdown failed - %s\n", nt_errstr(status));
98                 return False;
99         }
100
101         return True;
102 }
103
104 static BOOL test_SetDsrmPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
105                                  struct policy_handle *handle)
106 {
107         NTSTATUS status;
108         struct samr_SetDsrmPassword r;
109         struct lsa_String string;
110         struct samr_Password hash;
111
112         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
113                 printf("samr_SetDsrmPassword disabled - enable dangerous tests to use\n");
114                 return True;
115         }
116
117         E_md4hash("TeSTDSRM123", hash.hash);
118
119         init_lsa_String(&string, "Administrator");
120
121         r.in.name = &string;
122         r.in.unknown = 0;
123         r.in.hash = &hash;
124
125         printf("testing samr_SetDsrmPassword\n");
126
127         status = dcerpc_samr_SetDsrmPassword(p, mem_ctx, &r);
128         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
129                 printf("samr_SetDsrmPassword failed - %s\n", nt_errstr(status));
130                 return False;
131         }
132
133         return True;
134 }
135
136
137 static BOOL test_QuerySecurity(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
138                                struct policy_handle *handle)
139 {
140         NTSTATUS status;
141         struct samr_QuerySecurity r;
142         struct samr_SetSecurity s;
143
144         r.in.handle = handle;
145         r.in.sec_info = 7;
146
147         status = dcerpc_samr_QuerySecurity(p, mem_ctx, &r);
148         if (!NT_STATUS_IS_OK(status)) {
149                 printf("QuerySecurity failed - %s\n", nt_errstr(status));
150                 return False;
151         }
152
153         if (r.out.sdbuf == NULL) {
154                 return False;
155         }
156
157         s.in.handle = handle;
158         s.in.sec_info = 7;
159         s.in.sdbuf = r.out.sdbuf;
160
161         if (lp_parm_bool(-1, "torture", "samba4", False)) {
162                 printf("skipping SetSecurity test against Samba4\n");
163                 return True;
164         }
165
166         status = dcerpc_samr_SetSecurity(p, mem_ctx, &s);
167         if (!NT_STATUS_IS_OK(status)) {
168                 printf("SetSecurity failed - %s\n", nt_errstr(status));
169                 return False;
170         }
171
172         status = dcerpc_samr_QuerySecurity(p, mem_ctx, &r);
173         if (!NT_STATUS_IS_OK(status)) {
174                 printf("QuerySecurity failed - %s\n", nt_errstr(status));
175                 return False;
176         }
177
178         return True;
179 }
180
181
182 static BOOL test_SetUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
183                              struct policy_handle *handle, uint32_t base_acct_flags,
184                              const char *base_account_name)
185 {
186         NTSTATUS status;
187         struct samr_SetUserInfo s;
188         struct samr_SetUserInfo2 s2;
189         struct samr_QueryUserInfo q;
190         struct samr_QueryUserInfo q0;
191         union samr_UserInfo u;
192         BOOL ret = True;
193         const char *test_account_name;
194
195         uint32_t user_extra_flags = 0;
196         if (base_acct_flags == ACB_NORMAL) {
197                 /* When created, accounts are expired by default */
198                 user_extra_flags = ACB_PW_EXPIRED;
199         }
200
201         s.in.user_handle = handle;
202         s.in.info = &u;
203
204         s2.in.user_handle = handle;
205         s2.in.info = &u;
206
207         q.in.user_handle = handle;
208         q.out.info = &u;
209         q0 = q;
210
211 #define TESTCALL(call, r) \
212                 status = dcerpc_samr_ ##call(p, mem_ctx, &r); \
213                 if (!NT_STATUS_IS_OK(status)) { \
214                         printf(#call " level %u failed - %s (%s)\n", \
215                                r.in.level, nt_errstr(status), __location__); \
216                         ret = False; \
217                         break; \
218                 }
219
220 #define STRING_EQUAL(s1, s2, field) \
221                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
222                         printf("Failed to set %s to '%s' (%s)\n", \
223                                #field, s2, __location__); \
224                         ret = False; \
225                         break; \
226                 }
227
228 #define INT_EQUAL(i1, i2, field) \
229                 if (i1 != i2) { \
230                         printf("Failed to set %s to 0x%x - got 0x%x (%s)\n", \
231                                #field, i2, i1, __location__); \
232                         ret = False; \
233                         break; \
234                 }
235
236 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
237                 printf("field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
238                 q.in.level = lvl1; \
239                 TESTCALL(QueryUserInfo, q) \
240                 s.in.level = lvl1; \
241                 s2.in.level = lvl1; \
242                 u = *q.out.info; \
243                 if (lvl1 == 21) { \
244                         ZERO_STRUCT(u.info21); \
245                         u.info21.fields_present = fpval; \
246                 } \
247                 init_lsa_String(&u.info ## lvl1.field1, value); \
248                 TESTCALL(SetUserInfo, s) \
249                 TESTCALL(SetUserInfo2, s2) \
250                 init_lsa_String(&u.info ## lvl1.field1, ""); \
251                 TESTCALL(QueryUserInfo, q); \
252                 u = *q.out.info; \
253                 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
254                 q.in.level = lvl2; \
255                 TESTCALL(QueryUserInfo, q) \
256                 u = *q.out.info; \
257                 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
258         } while (0)
259
260 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
261                 printf("field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
262                 q.in.level = lvl1; \
263                 TESTCALL(QueryUserInfo, q) \
264                 s.in.level = lvl1; \
265                 s2.in.level = lvl1; \
266                 u = *q.out.info; \
267                 if (lvl1 == 21) { \
268                         uint8_t *bits = u.info21.logon_hours.bits; \
269                         ZERO_STRUCT(u.info21); \
270                         if (fpval == SAMR_FIELD_LOGON_HOURS) { \
271                                 u.info21.logon_hours.units_per_week = 168; \
272                                 u.info21.logon_hours.bits = bits; \
273                         } \
274                         u.info21.fields_present = fpval; \
275                 } \
276                 u.info ## lvl1.field1 = value; \
277                 TESTCALL(SetUserInfo, s) \
278                 TESTCALL(SetUserInfo2, s2) \
279                 u.info ## lvl1.field1 = 0; \
280                 TESTCALL(QueryUserInfo, q); \
281                 u = *q.out.info; \
282                 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
283                 q.in.level = lvl2; \
284                 TESTCALL(QueryUserInfo, q) \
285                 u = *q.out.info; \
286                 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
287         } while (0)
288
289 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
290         TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
291         } while (0)
292
293         q0.in.level = 12;
294         do { TESTCALL(QueryUserInfo, q0) } while (0);
295
296         TEST_USERINFO_STRING(2, comment,  1, comment, "xx2-1 comment", 0);
297         TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
298         TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment", 
299                            SAMR_FIELD_COMMENT);
300
301         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-1", base_account_name);
302         TEST_USERINFO_STRING(7, account_name,  1, account_name, base_account_name, 0);
303         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-3", base_account_name);
304         TEST_USERINFO_STRING(7, account_name,  3, account_name, base_account_name, 0);
305         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-5", base_account_name);
306         TEST_USERINFO_STRING(7, account_name,  5, account_name, base_account_name, 0);
307         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-6", base_account_name);
308         TEST_USERINFO_STRING(7, account_name,  6, account_name, base_account_name, 0);
309         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-7", base_account_name);
310         TEST_USERINFO_STRING(7, account_name,  7, account_name, base_account_name, 0);
311         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-21", base_account_name);
312         TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
313         test_account_name = base_account_name;
314         TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name, 
315                            SAMR_FIELD_ACCOUNT_NAME);
316
317         TEST_USERINFO_STRING(6, full_name,  1, full_name, "xx6-1 full_name", 0);
318         TEST_USERINFO_STRING(6, full_name,  3, full_name, "xx6-3 full_name", 0);
319         TEST_USERINFO_STRING(6, full_name,  5, full_name, "xx6-5 full_name", 0);
320         TEST_USERINFO_STRING(6, full_name,  6, full_name, "xx6-6 full_name", 0);
321         TEST_USERINFO_STRING(6, full_name,  8, full_name, "xx6-8 full_name", 0);
322         TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
323         TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
324         TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name", 
325                            SAMR_FIELD_FULL_NAME);
326
327         TEST_USERINFO_STRING(6, full_name,  1, full_name, "", 0);
328         TEST_USERINFO_STRING(6, full_name,  3, full_name, "", 0);
329         TEST_USERINFO_STRING(6, full_name,  5, full_name, "", 0);
330         TEST_USERINFO_STRING(6, full_name,  6, full_name, "", 0);
331         TEST_USERINFO_STRING(6, full_name,  8, full_name, "", 0);
332         TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
333         TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
334         TEST_USERINFO_STRING(21, full_name, 21, full_name, "", 
335                            SAMR_FIELD_FULL_NAME);
336
337         TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
338         TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
339         TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
340         TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script", 
341                            SAMR_FIELD_LOGON_SCRIPT);
342
343         TEST_USERINFO_STRING(12, profile_path,  3, profile_path, "xx12-3 profile_path", 0);
344         TEST_USERINFO_STRING(12, profile_path,  5, profile_path, "xx12-5 profile_path", 0);
345         TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
346         TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path", 
347                            SAMR_FIELD_PROFILE_PATH);
348
349         TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
350         TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
351         TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
352         TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
353                              SAMR_FIELD_HOME_DIRECTORY);
354         TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
355                              SAMR_FIELD_HOME_DIRECTORY);
356
357         TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
358         TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
359         TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
360         TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
361                              SAMR_FIELD_HOME_DRIVE);
362         TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
363                              SAMR_FIELD_HOME_DRIVE);
364         
365         TEST_USERINFO_STRING(13, description,  1, description, "xx13-1 description", 0);
366         TEST_USERINFO_STRING(13, description,  5, description, "xx13-5 description", 0);
367         TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
368         TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description", 
369                            SAMR_FIELD_DESCRIPTION);
370
371         TEST_USERINFO_STRING(14, workstations,  3, workstations, "14workstation3", 0);
372         TEST_USERINFO_STRING(14, workstations,  5, workstations, "14workstation4", 0);
373         TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
374         TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21", 
375                            SAMR_FIELD_WORKSTATIONS);
376
377         TEST_USERINFO_STRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
378         TEST_USERINFO_STRING(21, parameters, 21, parameters, "xx21-21 parameters", 
379                            SAMR_FIELD_PARAMETERS);
380
381         TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
382         TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__, 
383                           SAMR_FIELD_COUNTRY_CODE);
384
385         TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
386         TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__, 
387                           SAMR_FIELD_CODE_PAGE);
388
389         TEST_USERINFO_INT(4, logon_hours.bits[3],  3, logon_hours.bits[3], 1, 0);
390         TEST_USERINFO_INT(4, logon_hours.bits[3],  5, logon_hours.bits[3], 2, 0);
391         TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
392         TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4, 
393                           SAMR_FIELD_LOGON_HOURS);
394
395         if (lp_parm_bool(-1, "torture", "samba4", False)) {
396                 printf("skipping Set Account Flag tests against Samba4\n");
397                 return ret;
398         }
399
400         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
401                               (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ), 
402                               (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
403                               0);
404         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
405                               (base_acct_flags  | ACB_DISABLED), 
406                               (base_acct_flags  | ACB_DISABLED | user_extra_flags), 
407                               0);
408         
409         /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
410         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
411                               (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP), 
412                               (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP), 
413                               0);
414         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
415                               (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ), 
416                               (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
417                               0);
418
419
420         /* The 'autolock' flag doesn't stick - check this */
421         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
422                               (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK), 
423                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
424                               0);
425 #if 0
426         /* Removing the 'disabled' flag doesn't stick - check this */
427         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
428                               (base_acct_flags), 
429                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
430                               0);
431 #endif
432         /* The 'store plaintext' flag does stick */
433         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
434                               (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED), 
435                               (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags), 
436                               0);
437         /* The 'use DES' flag does stick */
438         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
439                               (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY), 
440                               (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags), 
441                               0);
442         /* The 'don't require kerberos pre-authentication flag does stick */
443         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
444                               (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH), 
445                               (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags), 
446                               0);
447         /* The 'no kerberos PAC required' flag sticks */
448         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
449                               (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD), 
450                               (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags), 
451                               0);
452
453         TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags, 
454                               (base_acct_flags | ACB_DISABLED), 
455                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
456                               SAMR_FIELD_ACCT_FLAGS);
457
458 #if 0
459         /* these fail with win2003 - it appears you can't set the primary gid?
460            the set succeeds, but the gid isn't changed. Very weird! */
461         TEST_USERINFO_INT(9, primary_gid,  1, primary_gid, 513);
462         TEST_USERINFO_INT(9, primary_gid,  3, primary_gid, 513);
463         TEST_USERINFO_INT(9, primary_gid,  5, primary_gid, 513);
464         TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
465 #endif
466
467         return ret;
468 }
469
470 /*
471   generate a random password for password change tests
472 */
473 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
474 {
475         size_t len = MAX(8, min_len) + (random() % 6);
476         char *s = generate_random_str(mem_ctx, len);
477         printf("Generated password '%s'\n", s);
478         return s;
479 }
480
481 /*
482   generate a random password for password change tests (fixed length)
483 */
484 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
485 {
486         char *s = generate_random_str(mem_ctx, len);
487         printf("Generated password '%s'\n", s);
488         return s;
489 }
490
491 static BOOL test_SetUserPass(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
492                              struct policy_handle *handle, char **password)
493 {
494         NTSTATUS status;
495         struct samr_SetUserInfo s;
496         union samr_UserInfo u;
497         BOOL ret = True;
498         DATA_BLOB session_key;
499         char *newpass;
500         struct samr_GetUserPwInfo pwp;
501         int policy_min_pw_len = 0;
502         pwp.in.user_handle = handle;
503
504         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
505         if (NT_STATUS_IS_OK(status)) {
506                 policy_min_pw_len = pwp.out.info.min_password_length;
507         }
508         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
509
510         s.in.user_handle = handle;
511         s.in.info = &u;
512         s.in.level = 24;
513
514         encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
515         /* w2k3 ignores this length */
516         u.info24.pw_len = strlen_m(newpass) * 2;
517
518         status = dcerpc_fetch_session_key(p, &session_key);
519         if (!NT_STATUS_IS_OK(status)) {
520                 printf("SetUserInfo level %u - no session key - %s\n",
521                        s.in.level, nt_errstr(status));
522                 return False;
523         }
524
525         arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
526
527         printf("Testing SetUserInfo level 24 (set password)\n");
528
529         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
530         if (!NT_STATUS_IS_OK(status)) {
531                 printf("SetUserInfo level %u failed - %s\n",
532                        s.in.level, nt_errstr(status));
533                 ret = False;
534         } else {
535                 *password = newpass;
536         }
537
538         return ret;
539 }
540
541
542 static BOOL test_SetUserPass_23(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
543                                 struct policy_handle *handle, uint32_t fields_present,
544                                 char **password)
545 {
546         NTSTATUS status;
547         struct samr_SetUserInfo s;
548         union samr_UserInfo u;
549         BOOL ret = True;
550         DATA_BLOB session_key;
551         char *newpass;
552         struct samr_GetUserPwInfo pwp;
553         int policy_min_pw_len = 0;
554         pwp.in.user_handle = handle;
555
556         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
557         if (NT_STATUS_IS_OK(status)) {
558                 policy_min_pw_len = pwp.out.info.min_password_length;
559         }
560         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
561
562         s.in.user_handle = handle;
563         s.in.info = &u;
564         s.in.level = 23;
565
566         ZERO_STRUCT(u);
567
568         u.info23.info.fields_present = fields_present;
569
570         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
571
572         status = dcerpc_fetch_session_key(p, &session_key);
573         if (!NT_STATUS_IS_OK(status)) {
574                 printf("SetUserInfo level %u - no session key - %s\n",
575                        s.in.level, nt_errstr(status));
576                 return False;
577         }
578
579         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
580
581         printf("Testing SetUserInfo level 23 (set password)\n");
582
583         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
584         if (!NT_STATUS_IS_OK(status)) {
585                 printf("SetUserInfo level %u failed - %s\n",
586                        s.in.level, nt_errstr(status));
587                 ret = False;
588         } else {
589                 *password = newpass;
590         }
591
592         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
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         /* This should break the key nicely */
602         session_key.length--;
603         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
604
605         printf("Testing SetUserInfo level 23 (set password) with wrong password\n");
606
607         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
608         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
609                 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
610                        s.in.level, nt_errstr(status));
611                 ret = False;
612         }
613
614         return ret;
615 }
616
617
618 static BOOL test_SetUserPassEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
619                                struct policy_handle *handle, char **password)
620 {
621         NTSTATUS status;
622         struct samr_SetUserInfo s;
623         union samr_UserInfo u;
624         BOOL ret = True;
625         DATA_BLOB session_key;
626         DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
627         uint8_t confounder[16];
628         char *newpass;
629         struct MD5Context ctx;
630         struct samr_GetUserPwInfo pwp;
631         int policy_min_pw_len = 0;
632         pwp.in.user_handle = handle;
633
634         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &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(mem_ctx, policy_min_pw_len);
639
640         s.in.user_handle = handle;
641         s.in.info = &u;
642         s.in.level = 26;
643
644         encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
645         u.info26.pw_len = strlen(newpass);
646
647         status = dcerpc_fetch_session_key(p, &session_key);
648         if (!NT_STATUS_IS_OK(status)) {
649                 printf("SetUserInfo level %u - no session key - %s\n",
650                        s.in.level, nt_errstr(status));
651                 return False;
652         }
653
654         generate_random_buffer((uint8_t *)confounder, 16);
655
656         MD5Init(&ctx);
657         MD5Update(&ctx, confounder, 16);
658         MD5Update(&ctx, session_key.data, session_key.length);
659         MD5Final(confounded_session_key.data, &ctx);
660
661         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
662         memcpy(&u.info26.password.data[516], confounder, 16);
663
664         printf("Testing SetUserInfo level 26 (set password ex)\n");
665
666         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
667         if (!NT_STATUS_IS_OK(status)) {
668                 printf("SetUserInfo level %u failed - %s\n",
669                        s.in.level, nt_errstr(status));
670                 ret = False;
671         } else {
672                 *password = newpass;
673         }
674
675         /* This should break the key nicely */
676         confounded_session_key.data[0]++;
677
678         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
679         memcpy(&u.info26.password.data[516], confounder, 16);
680
681         printf("Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
682
683         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
684         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
685                 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
686                        s.in.level, nt_errstr(status));
687                 ret = False;
688         } else {
689                 *password = newpass;
690         }
691
692         return ret;
693 }
694
695 static BOOL test_SetUserPass_25(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
696                                 struct policy_handle *handle, uint32_t fields_present,
697                                 char **password)
698 {
699         NTSTATUS status;
700         struct samr_SetUserInfo s;
701         union samr_UserInfo u;
702         BOOL ret = True;
703         DATA_BLOB session_key;
704         DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
705         struct MD5Context ctx;
706         uint8_t confounder[16];
707         char *newpass;
708         struct samr_GetUserPwInfo pwp;
709         int policy_min_pw_len = 0;
710         pwp.in.user_handle = handle;
711
712         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
713         if (NT_STATUS_IS_OK(status)) {
714                 policy_min_pw_len = pwp.out.info.min_password_length;
715         }
716         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
717
718         s.in.user_handle = handle;
719         s.in.info = &u;
720         s.in.level = 25;
721
722         ZERO_STRUCT(u);
723
724         u.info25.info.fields_present = fields_present;
725
726         encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
727
728         status = dcerpc_fetch_session_key(p, &session_key);
729         if (!NT_STATUS_IS_OK(status)) {
730                 printf("SetUserInfo level %u - no session key - %s\n",
731                        s.in.level, nt_errstr(status));
732                 return False;
733         }
734
735         generate_random_buffer((uint8_t *)confounder, 16);
736
737         MD5Init(&ctx);
738         MD5Update(&ctx, confounder, 16);
739         MD5Update(&ctx, session_key.data, session_key.length);
740         MD5Final(confounded_session_key.data, &ctx);
741
742         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
743         memcpy(&u.info25.password.data[516], confounder, 16);
744
745         printf("Testing SetUserInfo level 25 (set password ex)\n");
746
747         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
748         if (!NT_STATUS_IS_OK(status)) {
749                 printf("SetUserInfo level %u failed - %s\n",
750                        s.in.level, nt_errstr(status));
751                 ret = False;
752         } else {
753                 *password = newpass;
754         }
755
756         /* This should break the key nicely */
757         confounded_session_key.data[0]++;
758
759         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
760         memcpy(&u.info25.password.data[516], confounder, 16);
761
762         printf("Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
763
764         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
765         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
766                 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
767                        s.in.level, nt_errstr(status));
768                 ret = False;
769         }
770
771         return ret;
772 }
773
774 static BOOL test_SetAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
775                                struct policy_handle *handle)
776 {
777         NTSTATUS status;
778         struct samr_SetAliasInfo r;
779         struct samr_QueryAliasInfo q;
780         uint16_t levels[] = {2, 3};
781         int i;
782         BOOL ret = True;
783
784         /* Ignoring switch level 1, as that includes the number of members for the alias
785          * and setting this to a wrong value might have negative consequences
786          */
787
788         for (i=0;i<ARRAY_SIZE(levels);i++) {
789                 printf("Testing SetAliasInfo level %u\n", levels[i]);
790
791                 r.in.alias_handle = handle;
792                 r.in.level = levels[i];
793                 r.in.info  = talloc(mem_ctx, union samr_AliasInfo);
794                 switch (r.in.level) {
795                     case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
796                     case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
797                                 "Test Description, should test I18N as well"); break;
798                 }
799
800                 status = dcerpc_samr_SetAliasInfo(p, mem_ctx, &r);
801                 if (!NT_STATUS_IS_OK(status)) {
802                         printf("SetAliasInfo level %u failed - %s\n",
803                                levels[i], nt_errstr(status));
804                         ret = False;
805                 }
806
807                 q.in.alias_handle = handle;
808                 q.in.level = levels[i];
809
810                 status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &q);
811                 if (!NT_STATUS_IS_OK(status)) {
812                         printf("QueryAliasInfo level %u failed - %s\n",
813                                levels[i], nt_errstr(status));
814                         ret = False;
815                 }
816         }
817
818         return ret;
819 }
820
821 static BOOL test_GetGroupsForUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
822                                   struct policy_handle *user_handle)
823 {
824         struct samr_GetGroupsForUser r;
825         NTSTATUS status;
826         BOOL ret = True;
827
828         printf("testing GetGroupsForUser\n");
829
830         r.in.user_handle = user_handle;
831
832         status = dcerpc_samr_GetGroupsForUser(p, mem_ctx, &r);
833         if (!NT_STATUS_IS_OK(status)) {
834                 printf("GetGroupsForUser failed - %s\n",nt_errstr(status));
835                 ret = False;
836         }
837
838         return ret;
839
840 }
841
842 static BOOL test_GetDomPwInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
843                               struct lsa_String *domain_name)
844 {
845         NTSTATUS status;
846         struct samr_GetDomPwInfo r;
847         BOOL ret = True;
848
849         r.in.domain_name = domain_name;
850         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
851
852         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
853         if (!NT_STATUS_IS_OK(status)) {
854                 printf("GetDomPwInfo failed - %s\n", nt_errstr(status));
855                 ret = False;
856         }
857
858         r.in.domain_name->string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
859         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
860
861         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
862         if (!NT_STATUS_IS_OK(status)) {
863                 printf("GetDomPwInfo failed - %s\n", nt_errstr(status));
864                 ret = False;
865         }
866
867         r.in.domain_name->string = "\\\\__NONAME__";
868         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
869
870         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
871         if (!NT_STATUS_IS_OK(status)) {
872                 printf("GetDomPwInfo failed - %s\n", nt_errstr(status));
873                 ret = False;
874         }
875
876         r.in.domain_name->string = "\\\\Builtin";
877         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
878
879         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
880         if (!NT_STATUS_IS_OK(status)) {
881                 printf("GetDomPwInfo failed - %s\n", nt_errstr(status));
882                 ret = False;
883         }
884
885
886         return ret;
887 }
888
889 static BOOL test_GetUserPwInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
890                                struct policy_handle *handle)
891 {
892         NTSTATUS status;
893         struct samr_GetUserPwInfo r;
894         BOOL ret = True;
895
896         printf("Testing GetUserPwInfo\n");
897
898         r.in.user_handle = handle;
899
900         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &r);
901         if (!NT_STATUS_IS_OK(status)) {
902                 printf("GetUserPwInfo failed - %s\n", nt_errstr(status));
903                 ret = False;
904         }
905
906         return ret;
907 }
908
909 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
910                                 struct policy_handle *domain_handle, const char *name,
911                                 uint32_t *rid)
912 {
913         NTSTATUS status;
914         struct samr_LookupNames n;
915         struct lsa_String sname[2];
916
917         init_lsa_String(&sname[0], name);
918
919         n.in.domain_handle = domain_handle;
920         n.in.num_names = 1;
921         n.in.names = sname;
922         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
923         if (NT_STATUS_IS_OK(status)) {
924                 *rid = n.out.rids.ids[0];
925         } else {
926                 return status;
927         }
928
929         init_lsa_String(&sname[1], "xxNONAMExx");
930         n.in.num_names = 2;
931         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
932         if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
933                 printf("LookupNames[2] failed - %s\n", nt_errstr(status));              
934                 if (NT_STATUS_IS_OK(status)) {
935                         return NT_STATUS_UNSUCCESSFUL;
936                 }
937                 return status;
938         }
939
940         n.in.num_names = 0;
941         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
942         if (!NT_STATUS_IS_OK(status)) {
943                 printf("LookupNames[0] failed - %s\n", nt_errstr(status));              
944                 return status;
945         }
946
947         init_lsa_String(&sname[0], "xxNONAMExx");
948         n.in.num_names = 1;
949         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
950         if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
951                 printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));             
952                 if (NT_STATUS_IS_OK(status)) {
953                         return NT_STATUS_UNSUCCESSFUL;
954                 }
955                 return status;
956         }
957
958         init_lsa_String(&sname[0], "xxNONAMExx");
959         init_lsa_String(&sname[1], "xxNONAME2xx");
960         n.in.num_names = 2;
961         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
962         if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
963                 printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));            
964                 if (NT_STATUS_IS_OK(status)) {
965                         return NT_STATUS_UNSUCCESSFUL;
966                 }
967                 return status;
968         }
969
970         return NT_STATUS_OK;
971 }
972
973 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
974                                      struct policy_handle *domain_handle,
975                                      const char *name, struct policy_handle *user_handle)
976 {
977         NTSTATUS status;
978         struct samr_OpenUser r;
979         uint32_t rid;
980
981         status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
982         if (!NT_STATUS_IS_OK(status)) {
983                 return status;
984         }
985
986         r.in.domain_handle = domain_handle;
987         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
988         r.in.rid = rid;
989         r.out.user_handle = user_handle;
990         status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
991         if (!NT_STATUS_IS_OK(status)) {
992                 printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
993         }
994
995         return status;
996 }
997
998 #if 0
999 static BOOL test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1000                                    struct policy_handle *handle)
1001 {
1002         NTSTATUS status;
1003         struct samr_ChangePasswordUser r;
1004         BOOL ret = True;
1005         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1006         struct policy_handle user_handle;
1007         char *oldpass = "test";
1008         char *newpass = "test2";
1009         uint8_t old_nt_hash[16], new_nt_hash[16];
1010         uint8_t old_lm_hash[16], new_lm_hash[16];
1011
1012         status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
1013         if (!NT_STATUS_IS_OK(status)) {
1014                 return False;
1015         }
1016
1017         printf("Testing ChangePasswordUser for user 'testuser'\n");
1018
1019         printf("old password: %s\n", oldpass);
1020         printf("new password: %s\n", newpass);
1021
1022         E_md4hash(oldpass, old_nt_hash);
1023         E_md4hash(newpass, new_nt_hash);
1024         E_deshash(oldpass, old_lm_hash);
1025         E_deshash(newpass, new_lm_hash);
1026
1027         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1028         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1029         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1030         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1031         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1032         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1033
1034         r.in.handle = &user_handle;
1035         r.in.lm_present = 1;
1036         r.in.old_lm_crypted = &hash1;
1037         r.in.new_lm_crypted = &hash2;
1038         r.in.nt_present = 1;
1039         r.in.old_nt_crypted = &hash3;
1040         r.in.new_nt_crypted = &hash4;
1041         r.in.cross1_present = 1;
1042         r.in.nt_cross = &hash5;
1043         r.in.cross2_present = 1;
1044         r.in.lm_cross = &hash6;
1045
1046         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1047         if (!NT_STATUS_IS_OK(status)) {
1048                 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1049                 ret = False;
1050         }
1051
1052         if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
1053                 ret = False;
1054         }
1055
1056         return ret;
1057 }
1058 #endif
1059
1060 static BOOL test_ChangePasswordUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1061                                     const char *acct_name, 
1062                                     struct policy_handle *handle, char **password)
1063 {
1064         NTSTATUS status;
1065         struct samr_ChangePasswordUser r;
1066         BOOL ret = True;
1067         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1068         struct policy_handle user_handle;
1069         char *oldpass;
1070         uint8_t old_nt_hash[16], new_nt_hash[16];
1071         uint8_t old_lm_hash[16], new_lm_hash[16];
1072         BOOL changed = True;
1073
1074         char *newpass;
1075         struct samr_GetUserPwInfo pwp;
1076         int policy_min_pw_len = 0;
1077
1078         status = test_OpenUser_byname(p, mem_ctx, handle, acct_name, &user_handle);
1079         if (!NT_STATUS_IS_OK(status)) {
1080                 return False;
1081         }
1082         pwp.in.user_handle = &user_handle;
1083
1084         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
1085         if (NT_STATUS_IS_OK(status)) {
1086                 policy_min_pw_len = pwp.out.info.min_password_length;
1087         }
1088         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
1089
1090         printf("Testing ChangePasswordUser\n");
1091
1092         if (!*password) {
1093                 printf("Failing ChangePasswordUser as old password was NULL.  Previous test failed?\n");
1094                 return False;
1095         }
1096
1097         oldpass = *password;
1098
1099         E_md4hash(oldpass, old_nt_hash);
1100         E_md4hash(newpass, new_nt_hash);
1101         E_deshash(oldpass, old_lm_hash);
1102         E_deshash(newpass, new_lm_hash);
1103
1104         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1105         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1106         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1107         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1108         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1109         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1110
1111         r.in.user_handle = &user_handle;
1112         r.in.lm_present = 1;
1113         r.in.old_lm_crypted = &hash1;
1114         r.in.new_lm_crypted = &hash2;
1115         r.in.nt_present = 1;
1116         r.in.old_nt_crypted = &hash3;
1117         r.in.new_nt_crypted = &hash4;
1118         r.in.cross1_present = 1;
1119         r.in.nt_cross = &hash5;
1120         r.in.cross2_present = 0;
1121         r.in.lm_cross = NULL;
1122
1123         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1124         if (!NT_STATUS_EQUAL(status, NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED)) {
1125                 printf("ChangePasswordUser failed: expected NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1126                 ret = False;
1127         }
1128
1129         
1130         r.in.user_handle = &user_handle;
1131         r.in.lm_present = 1;
1132         r.in.old_lm_crypted = &hash1;
1133         r.in.new_lm_crypted = &hash2;
1134         r.in.nt_present = 1;
1135         r.in.old_nt_crypted = &hash3;
1136         r.in.new_nt_crypted = &hash4;
1137         r.in.cross1_present = 0;
1138         r.in.nt_cross = NULL;
1139         r.in.cross2_present = 1;
1140         r.in.lm_cross = &hash6;
1141
1142         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1143         if (!NT_STATUS_EQUAL(status, NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED)) {
1144                 printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1145                 ret = False;
1146         }
1147
1148         r.in.user_handle = &user_handle;
1149         r.in.lm_present = 1;
1150         /* Break the LM hash */
1151         hash1.hash[0]++;
1152         r.in.old_lm_crypted = &hash1;
1153         r.in.new_lm_crypted = &hash2;
1154         r.in.nt_present = 1;
1155         r.in.old_nt_crypted = &hash3;
1156         r.in.new_nt_crypted = &hash4;
1157         r.in.cross1_present = 1;
1158         r.in.nt_cross = &hash5;
1159         r.in.cross2_present = 1;
1160         r.in.lm_cross = &hash6;
1161
1162         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1163         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1164                 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash, got %s\n", nt_errstr(status));
1165                 ret = False;
1166         }
1167
1168         /* Unbreak the LM hash */
1169         hash1.hash[0]--;
1170
1171         r.in.user_handle = &user_handle;
1172         r.in.lm_present = 1;
1173         r.in.old_lm_crypted = &hash1;
1174         r.in.new_lm_crypted = &hash2;
1175         /* Break the NT hash */
1176         hash3.hash[0]--;
1177         r.in.nt_present = 1;
1178         r.in.old_nt_crypted = &hash3;
1179         r.in.new_nt_crypted = &hash4;
1180         r.in.cross1_present = 1;
1181         r.in.nt_cross = &hash5;
1182         r.in.cross2_present = 1;
1183         r.in.lm_cross = &hash6;
1184
1185         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1186         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1187                 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash, got %s\n", nt_errstr(status));
1188                 ret = False;
1189         }
1190
1191         /* Unbreak the NT hash */
1192         hash3.hash[0]--;
1193
1194         r.in.user_handle = &user_handle;
1195         r.in.lm_present = 1;
1196         r.in.old_lm_crypted = &hash1;
1197         r.in.new_lm_crypted = &hash2;
1198         r.in.nt_present = 1;
1199         r.in.old_nt_crypted = &hash3;
1200         r.in.new_nt_crypted = &hash4;
1201         r.in.cross1_present = 1;
1202         r.in.nt_cross = &hash5;
1203         r.in.cross2_present = 1;
1204         /* Break the LM cross */
1205         hash6.hash[0]++;
1206         r.in.lm_cross = &hash6;
1207
1208         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1209         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1210                 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1211                 ret = False;
1212         }
1213
1214         /* Unbreak the LM cross */
1215         hash6.hash[0]--;
1216
1217         r.in.user_handle = &user_handle;
1218         r.in.lm_present = 1;
1219         r.in.old_lm_crypted = &hash1;
1220         r.in.new_lm_crypted = &hash2;
1221         r.in.nt_present = 1;
1222         r.in.old_nt_crypted = &hash3;
1223         r.in.new_nt_crypted = &hash4;
1224         r.in.cross1_present = 1;
1225         /* Break the NT cross */
1226         hash5.hash[0]++;
1227         r.in.nt_cross = &hash5;
1228         r.in.cross2_present = 1;
1229         r.in.lm_cross = &hash6;
1230
1231         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1232         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1233                 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1234                 ret = False;
1235         }
1236
1237         /* Unbreak the NT cross */
1238         hash5.hash[0]--;
1239
1240         /* Reset the hashes to not broken values */
1241         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1242         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1243         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1244         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1245         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1246         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1247
1248         r.in.user_handle = &user_handle;
1249         r.in.lm_present = 1;
1250         r.in.old_lm_crypted = &hash1;
1251         r.in.new_lm_crypted = &hash2;
1252         r.in.nt_present = 1;
1253         r.in.old_nt_crypted = &hash3;
1254         r.in.new_nt_crypted = &hash4;
1255         r.in.cross1_present = 1;
1256         r.in.nt_cross = &hash5;
1257         r.in.cross2_present = 1;
1258         r.in.lm_cross = &hash6;
1259
1260         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1261         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1262                 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1263         } else  if (!NT_STATUS_IS_OK(status)) {
1264                 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1265                 ret = False;
1266         } else {
1267                 changed = True;
1268                 *password = newpass;
1269         }
1270
1271         r.in.user_handle = &user_handle;
1272         r.in.lm_present = 1;
1273         r.in.old_lm_crypted = &hash1;
1274         r.in.new_lm_crypted = &hash2;
1275         r.in.nt_present = 1;
1276         r.in.old_nt_crypted = &hash3;
1277         r.in.new_nt_crypted = &hash4;
1278         r.in.cross1_present = 1;
1279         r.in.nt_cross = &hash5;
1280         r.in.cross2_present = 1;
1281         r.in.lm_cross = &hash6;
1282
1283         if (changed) {
1284                 status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1285                 if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1286                         printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1287                         ret = False;
1288                 }
1289         }
1290
1291         if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
1292                 ret = False;
1293         }
1294
1295         return ret;
1296 }
1297
1298
1299 static BOOL test_OemChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1300                                         const char *acct_name,
1301                                         struct policy_handle *handle, char **password)
1302 {
1303         NTSTATUS status;
1304         struct samr_OemChangePasswordUser2 r;
1305         BOOL ret = True;
1306         struct samr_Password lm_verifier;
1307         struct samr_CryptPassword lm_pass;
1308         struct lsa_AsciiString server, account, account_bad;
1309         char *oldpass;
1310         char *newpass;
1311         uint8_t old_lm_hash[16], new_lm_hash[16];
1312
1313         struct samr_GetDomPwInfo dom_pw_info;
1314         int policy_min_pw_len = 0;
1315
1316         struct lsa_String domain_name;
1317
1318         domain_name.string = "";
1319         dom_pw_info.in.domain_name = &domain_name;
1320
1321         printf("Testing OemChangePasswordUser2\n");
1322
1323         if (!*password) {
1324                 printf("Failing OemChangePasswordUser2 as old password was NULL.  Previous test failed?\n");
1325                 return False;
1326         }
1327
1328         oldpass = *password;
1329
1330         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &dom_pw_info);
1331         if (NT_STATUS_IS_OK(status)) {
1332                 policy_min_pw_len = dom_pw_info.out.info.min_password_length;
1333         }
1334
1335         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
1336
1337         server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1338         account.string = acct_name;
1339
1340         E_deshash(oldpass, old_lm_hash);
1341         E_deshash(newpass, new_lm_hash);
1342
1343         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1344         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1345         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1346
1347         r.in.server = &server;
1348         r.in.account = &account;
1349         r.in.password = &lm_pass;
1350         r.in.hash = &lm_verifier;
1351
1352         /* Break the verification */
1353         lm_verifier.hash[0]++;
1354
1355         status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
1356
1357         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1358             && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1359                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1360                         nt_errstr(status));
1361                 ret = False;
1362         }
1363
1364         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1365         /* Break the old password */
1366         old_lm_hash[0]++;
1367         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1368         /* unbreak it for the next operation */
1369         old_lm_hash[0]--;
1370         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1371
1372         r.in.server = &server;
1373         r.in.account = &account;
1374         r.in.password = &lm_pass;
1375         r.in.hash = &lm_verifier;
1376
1377         status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
1378
1379         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1380             && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1381                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1382                         nt_errstr(status));
1383                 ret = False;
1384         }
1385
1386         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1387         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1388
1389         r.in.server = &server;
1390         r.in.account = &account;
1391         r.in.password = &lm_pass;
1392         r.in.hash = NULL;
1393
1394         status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
1395
1396         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1397             && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1398                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1399                         nt_errstr(status));
1400                 ret = False;
1401         }
1402
1403         /* This shouldn't be a valid name */
1404         account_bad.string = TEST_ACCOUNT_NAME "XX";
1405         r.in.account = &account_bad;
1406
1407         status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
1408
1409         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1410                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1411                         nt_errstr(status));
1412                 ret = False;
1413         }
1414
1415         E_deshash(oldpass, old_lm_hash);
1416         E_deshash(newpass, new_lm_hash);
1417
1418         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1419         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1420         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1421
1422         r.in.server = &server;
1423         r.in.account = &account;
1424         r.in.password = &lm_pass;
1425         r.in.hash = &lm_verifier;
1426
1427         status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
1428         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1429                 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1430         } else if (!NT_STATUS_IS_OK(status)) {
1431                 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
1432                 ret = False;
1433         } else {
1434                 *password = newpass;
1435         }
1436
1437         return ret;
1438 }
1439
1440
1441 static BOOL test_ChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1442                                      const char *acct_name,
1443                                      struct policy_handle *handle, char **password)
1444 {
1445         NTSTATUS status;
1446         struct samr_ChangePasswordUser2 r;
1447         BOOL ret = True;
1448         struct lsa_String server, account;
1449         struct samr_CryptPassword nt_pass, lm_pass;
1450         struct samr_Password nt_verifier, lm_verifier;
1451         char *oldpass;
1452         char *newpass;
1453         uint8_t old_nt_hash[16], new_nt_hash[16];
1454         uint8_t old_lm_hash[16], new_lm_hash[16];
1455
1456         struct samr_GetDomPwInfo dom_pw_info;
1457         int policy_min_pw_len = 0;
1458
1459         struct lsa_String domain_name;
1460
1461
1462         domain_name.string = "";
1463         dom_pw_info.in.domain_name = &domain_name;
1464
1465         printf("Testing ChangePasswordUser2\n");
1466
1467         if (!*password) {
1468                 printf("Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?\n");
1469                 return False;
1470         }
1471         oldpass = *password;
1472
1473         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &dom_pw_info);
1474         if (NT_STATUS_IS_OK(status)) {
1475                 policy_min_pw_len = dom_pw_info.out.info.min_password_length;
1476         }
1477
1478         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
1479
1480         server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1481         init_lsa_String(&account, acct_name);
1482
1483         E_md4hash(oldpass, old_nt_hash);
1484         E_md4hash(newpass, new_nt_hash);
1485
1486         E_deshash(oldpass, old_lm_hash);
1487         E_deshash(newpass, new_lm_hash);
1488
1489         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
1490         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1491         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1492
1493         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1494         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1495         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1496
1497         r.in.server = &server;
1498         r.in.account = &account;
1499         r.in.nt_password = &nt_pass;
1500         r.in.nt_verifier = &nt_verifier;
1501         r.in.lm_change = 1;
1502         r.in.lm_password = &lm_pass;
1503         r.in.lm_verifier = &lm_verifier;
1504
1505         status = dcerpc_samr_ChangePasswordUser2(p, mem_ctx, &r);
1506         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1507                 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1508         } else if (!NT_STATUS_IS_OK(status)) {
1509                 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
1510                 ret = False;
1511         } else {
1512                 *password = newpass;
1513         }
1514
1515         return ret;
1516 }
1517
1518
1519 BOOL test_ChangePasswordUser3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1520                               const char *account_string,
1521                               int policy_min_pw_len,
1522                               char **password,
1523                               const char *newpass,
1524                               NTTIME last_password_change,
1525                               BOOL handle_reject_reason)
1526 {
1527         NTSTATUS status;
1528         struct samr_ChangePasswordUser3 r;
1529         BOOL ret = True;
1530         struct lsa_String server, account, account_bad;
1531         struct samr_CryptPassword nt_pass, lm_pass;
1532         struct samr_Password nt_verifier, lm_verifier;
1533         char *oldpass;
1534         uint8_t old_nt_hash[16], new_nt_hash[16];
1535         uint8_t old_lm_hash[16], new_lm_hash[16];
1536         NTTIME t;
1537
1538         printf("Testing ChangePasswordUser3\n");
1539
1540         if (newpass == NULL) {
1541                 do {
1542                         if (policy_min_pw_len == 0) {
1543                                 newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
1544                         } else {
1545                                 newpass = samr_rand_pass_fixed_len(mem_ctx, policy_min_pw_len);
1546                         }
1547                 } while (check_password_quality(newpass) == False);
1548         } else {
1549                 printf("Using password '%s'\n", newpass);
1550         }
1551
1552         if (!*password) {
1553                 printf("Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?\n");
1554                 return False;
1555         }
1556
1557         oldpass = *password;
1558         server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1559         init_lsa_String(&account, account_string);
1560
1561         E_md4hash(oldpass, old_nt_hash);
1562         E_md4hash(newpass, new_nt_hash);
1563
1564         E_deshash(oldpass, old_lm_hash);
1565         E_deshash(newpass, new_lm_hash);
1566
1567         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
1568         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
1569         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1570
1571         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1572         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1573         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1574         
1575         /* Break the verification */
1576         nt_verifier.hash[0]++;
1577
1578         r.in.server = &server;
1579         r.in.account = &account;
1580         r.in.nt_password = &nt_pass;
1581         r.in.nt_verifier = &nt_verifier;
1582         r.in.lm_change = 1;
1583         r.in.lm_password = &lm_pass;
1584         r.in.lm_verifier = &lm_verifier;
1585         r.in.password3 = NULL;
1586
1587         status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
1588         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
1589             (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
1590                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1591                         nt_errstr(status));
1592                 ret = False;
1593         }
1594         
1595         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
1596         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
1597         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1598
1599         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1600         /* Break the NT hash */
1601         old_nt_hash[0]++;
1602         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1603         /* Unbreak it again */
1604         old_nt_hash[0]--;
1605         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1606         
1607         r.in.server = &server;
1608         r.in.account = &account;
1609         r.in.nt_password = &nt_pass;
1610         r.in.nt_verifier = &nt_verifier;
1611         r.in.lm_change = 1;
1612         r.in.lm_password = &lm_pass;
1613         r.in.lm_verifier = &lm_verifier;
1614         r.in.password3 = NULL;
1615
1616         status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
1617         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
1618             (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
1619                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1620                         nt_errstr(status));
1621                 ret = False;
1622         }
1623         
1624         /* This shouldn't be a valid name */
1625         init_lsa_String(&account_bad, talloc_asprintf(mem_ctx, "%sXX", account_string));
1626
1627         r.in.account = &account_bad;
1628         status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
1629         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1630                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
1631                         nt_errstr(status));
1632                 ret = False;
1633         }
1634
1635         E_md4hash(oldpass, old_nt_hash);
1636         E_md4hash(newpass, new_nt_hash);
1637
1638         E_deshash(oldpass, old_lm_hash);
1639         E_deshash(newpass, new_lm_hash);
1640
1641         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
1642         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
1643         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1644
1645         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1646         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1647         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1648
1649         r.in.server = &server;
1650         r.in.account = &account;
1651         r.in.nt_password = &nt_pass;
1652         r.in.nt_verifier = &nt_verifier;
1653         r.in.lm_change = 1;
1654         r.in.lm_password = &lm_pass;
1655         r.in.lm_verifier = &lm_verifier;
1656         r.in.password3 = NULL;
1657
1658         unix_to_nt_time(&t, time(NULL));
1659
1660         status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
1661
1662         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) && 
1663            r.out.dominfo && r.out.reject && handle_reject_reason) {
1664
1665                 if (r.out.dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
1666
1667                         if (r.out.reject && (r.out.reject->reason != SAMR_REJECT_OTHER)) {
1668                                 printf("expected SAMR_REJECT_OTHER (%d), got %d\n", 
1669                                         SAMR_REJECT_OTHER, r.out.reject->reason);
1670                                 return False;
1671                         }
1672                 }
1673
1674                 /* We tested the order of precendence which is as follows:
1675                 
1676                 * pwd min_age 
1677                 * pwd length
1678                 * pwd complexity
1679                 * pwd history
1680
1681                 Guenther */
1682
1683                 if ((r.out.dominfo->min_password_age > 0) && !null_nttime(last_password_change) && 
1684                            (last_password_change + r.out.dominfo->min_password_age > t)) {
1685
1686                         if (r.out.reject->reason != SAMR_REJECT_OTHER) {
1687                                 printf("expected SAMR_REJECT_OTHER (%d), got %d\n", 
1688                                         SAMR_REJECT_OTHER, r.out.reject->reason);
1689                                 return False;
1690                         }
1691
1692                 } else if ((r.out.dominfo->min_password_length > 0) && 
1693                            (strlen(newpass) < r.out.dominfo->min_password_length)) {
1694
1695                         if (r.out.reject->reason != SAMR_REJECT_TOO_SHORT) {
1696                                 printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n", 
1697                                         SAMR_REJECT_TOO_SHORT, r.out.reject->reason);
1698                                 return False;
1699                         }
1700
1701                 } else if ((r.out.dominfo->password_history_length > 0) && 
1702                             strequal(oldpass, newpass)) {
1703
1704                         if (r.out.reject->reason != SAMR_REJECT_IN_HISTORY) {
1705                                 printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n", 
1706                                         SAMR_REJECT_IN_HISTORY, r.out.reject->reason);
1707                                 return False;
1708                         }
1709                 } else if (r.out.dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
1710
1711                         if (r.out.reject->reason != SAMR_REJECT_COMPLEXITY) {
1712                                 printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n", 
1713                                         SAMR_REJECT_COMPLEXITY, r.out.reject->reason);
1714                                 return False;
1715                         }
1716
1717                 }
1718
1719                 if (r.out.reject->reason == SAMR_REJECT_TOO_SHORT) {
1720                         /* retry with adjusted size */
1721                         return test_ChangePasswordUser3(p, mem_ctx, account_string, 
1722                                                         r.out.dominfo->min_password_length, 
1723                                                         password, NULL, 0, False); 
1724
1725                 }
1726
1727         } else if (!NT_STATUS_IS_OK(status)) {
1728                 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
1729                 ret = False;
1730         } else {
1731                 *password = talloc_strdup(mem_ctx, newpass);
1732         }
1733
1734         return ret;
1735 }
1736
1737
1738 static BOOL test_GetMembersInAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1739                                   struct policy_handle *alias_handle)
1740 {
1741         struct samr_GetMembersInAlias r;
1742         struct lsa_SidArray sids;
1743         NTSTATUS status;
1744         BOOL     ret = True;
1745
1746         printf("Testing GetMembersInAlias\n");
1747
1748         r.in.alias_handle = alias_handle;
1749         r.out.sids = &sids;
1750
1751         status = dcerpc_samr_GetMembersInAlias(p, mem_ctx, &r);
1752         if (!NT_STATUS_IS_OK(status)) {
1753                 printf("GetMembersInAlias failed - %s\n",
1754                        nt_errstr(status));
1755                 ret = False;
1756         }
1757
1758         return ret;
1759 }
1760
1761 static BOOL test_AddMemberToAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1762                                   struct policy_handle *alias_handle,
1763                                   const struct dom_sid *domain_sid)
1764 {
1765         struct samr_AddAliasMember r;
1766         struct samr_DeleteAliasMember d;
1767         NTSTATUS status;
1768         BOOL ret = True;
1769         struct dom_sid *sid;
1770
1771         sid = dom_sid_add_rid(mem_ctx, domain_sid, 512);
1772
1773         printf("testing AddAliasMember\n");
1774         r.in.alias_handle = alias_handle;
1775         r.in.sid = sid;
1776
1777         status = dcerpc_samr_AddAliasMember(p, mem_ctx, &r);
1778         if (!NT_STATUS_IS_OK(status)) {
1779                 printf("AddAliasMember failed - %s\n", nt_errstr(status));
1780                 ret = False;
1781         }
1782
1783         d.in.alias_handle = alias_handle;
1784         d.in.sid = sid;
1785
1786         status = dcerpc_samr_DeleteAliasMember(p, mem_ctx, &d);
1787         if (!NT_STATUS_IS_OK(status)) {
1788                 printf("DelAliasMember failed - %s\n", nt_errstr(status));
1789                 ret = False;
1790         }
1791
1792         return ret;
1793 }
1794
1795 static BOOL test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1796                                            struct policy_handle *alias_handle)
1797 {
1798         struct samr_AddMultipleMembersToAlias a;
1799         struct samr_RemoveMultipleMembersFromAlias r;
1800         NTSTATUS status;
1801         BOOL ret = True;
1802         struct lsa_SidArray sids;
1803
1804         printf("testing AddMultipleMembersToAlias\n");
1805         a.in.alias_handle = alias_handle;
1806         a.in.sids = &sids;
1807
1808         sids.num_sids = 3;
1809         sids.sids = talloc_array(mem_ctx, struct lsa_SidPtr, 3);
1810
1811         sids.sids[0].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-1");
1812         sids.sids[1].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-2");
1813         sids.sids[2].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-3");
1814
1815         status = dcerpc_samr_AddMultipleMembersToAlias(p, mem_ctx, &a);
1816         if (!NT_STATUS_IS_OK(status)) {
1817                 printf("AddMultipleMembersToAlias failed - %s\n", nt_errstr(status));
1818                 ret = False;
1819         }
1820
1821
1822         printf("testing RemoveMultipleMembersFromAlias\n");
1823         r.in.alias_handle = alias_handle;
1824         r.in.sids = &sids;
1825
1826         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
1827         if (!NT_STATUS_IS_OK(status)) {
1828                 printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
1829                 ret = False;
1830         }
1831
1832         /* strange! removing twice doesn't give any error */
1833         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
1834         if (!NT_STATUS_IS_OK(status)) {
1835                 printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
1836                 ret = False;
1837         }
1838
1839         /* but removing an alias that isn't there does */
1840         sids.sids[2].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-4");
1841
1842         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
1843         if (!NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
1844                 printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
1845                 ret = False;
1846         }
1847
1848         return ret;
1849 }
1850
1851 static BOOL test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1852                                             struct policy_handle *user_handle)
1853 {
1854         struct samr_TestPrivateFunctionsUser r;
1855         NTSTATUS status;
1856         BOOL ret = True;
1857
1858         printf("Testing TestPrivateFunctionsUser\n");
1859
1860         r.in.user_handle = user_handle;
1861
1862         status = dcerpc_samr_TestPrivateFunctionsUser(p, mem_ctx, &r);
1863         if (!NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
1864                 printf("TestPrivateFunctionsUser failed - %s\n", nt_errstr(status));
1865                 ret = False;
1866         }
1867
1868         return ret;
1869 }
1870
1871
1872 static BOOL test_user_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1873                           struct policy_handle *user_handle, 
1874                           struct policy_handle *domain_handle, 
1875                           uint32_t base_acct_flags, 
1876                           const char *base_acct_name, enum torture_samr_choice which_ops)
1877 {
1878         TALLOC_CTX *user_ctx;
1879         char *password = NULL;
1880
1881         BOOL ret = True;
1882         int i;
1883         const uint32_t password_fields[] = {
1884                 SAMR_FIELD_PASSWORD,
1885                 SAMR_FIELD_PASSWORD2,
1886                 SAMR_FIELD_PASSWORD | SAMR_FIELD_PASSWORD2,
1887                 0
1888         };
1889         
1890         user_ctx = talloc_named(mem_ctx, 0, "test_user_ops per-user context");
1891         switch (which_ops) {
1892         case TORTURE_SAMR_USER_ATTRIBUTES:
1893                 if (!test_QuerySecurity(p, user_ctx, user_handle)) {
1894                         ret = False;
1895                 }
1896
1897                 if (!test_QueryUserInfo(p, user_ctx, user_handle)) {
1898                         ret = False;
1899                 }
1900
1901                 if (!test_QueryUserInfo2(p, user_ctx, user_handle)) {
1902                         ret = False;
1903                 }
1904
1905                 if (!test_SetUserInfo(p, user_ctx, user_handle, base_acct_flags,
1906                                       base_acct_name)) {
1907                         ret = False;
1908                 }       
1909
1910                 if (!test_GetUserPwInfo(p, user_ctx, user_handle)) {
1911                         ret = False;
1912                 }
1913
1914                 if (!test_TestPrivateFunctionsUser(p, user_ctx, user_handle)) {
1915                         ret = False;
1916                 }
1917
1918                 if (!test_SetUserPass(p, user_ctx, user_handle, &password)) {
1919                         ret = False;
1920                 }
1921                 break;
1922         case TORTURE_SAMR_PASSWORDS:
1923                 for (i = 0; password_fields[i]; i++) {
1924                         if (!test_SetUserPass_23(p, user_ctx, user_handle, password_fields[i], &password)) {
1925                                 ret = False;
1926                         }       
1927                 
1928                         /* check it was set right */
1929                         if (!test_ChangePasswordUser3(p, user_ctx, base_acct_name, 0, &password, NULL, 0, False)) {
1930                                 ret = False;
1931                         }
1932                 }               
1933
1934                 for (i = 0; password_fields[i]; i++) {
1935                         if (!test_SetUserPass_25(p, user_ctx, user_handle, password_fields[i], &password)) {
1936                                 ret = False;
1937                         }       
1938                 
1939                         /* check it was set right */
1940                         if (!test_ChangePasswordUser3(p, user_ctx, base_acct_name, 0, &password, NULL, 0, False)) {
1941                                 ret = False;
1942                         }
1943                 }               
1944
1945                 if (!test_SetUserPassEx(p, user_ctx, user_handle, &password)) {
1946                         ret = False;
1947                 }       
1948
1949                 if (!test_ChangePassword(p, user_ctx, base_acct_name, domain_handle, &password)) {
1950                         ret = False;
1951                 }       
1952                 break;
1953         case TORTURE_SAMR_OTHER:
1954                 /* We just need the account to exist */
1955                 break;
1956         }
1957         talloc_free(user_ctx);
1958         return ret;
1959 }
1960
1961 static BOOL test_alias_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1962                            struct policy_handle *alias_handle,
1963                            const struct dom_sid *domain_sid)
1964 {
1965         BOOL ret = True;
1966
1967         if (!test_QuerySecurity(p, mem_ctx, alias_handle)) {
1968                 ret = False;
1969         }
1970
1971         if (!test_QueryAliasInfo(p, mem_ctx, alias_handle)) {
1972                 ret = False;
1973         }
1974
1975         if (!test_SetAliasInfo(p, mem_ctx, alias_handle)) {
1976                 ret = False;
1977         }
1978
1979         if (!test_AddMemberToAlias(p, mem_ctx, alias_handle, domain_sid)) {
1980                 ret = False;
1981         }
1982
1983         if (lp_parm_bool(-1, "torture", "samba4", False)) {
1984                 printf("skipping MultipleMembers Alias tests against Samba4\n");
1985                 return ret;
1986         }
1987
1988         if (!test_AddMultipleMembersToAlias(p, mem_ctx, alias_handle)) {
1989                 ret = False;
1990         }
1991
1992         return ret;
1993 }
1994
1995
1996 static BOOL test_DeleteUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1997                                      struct policy_handle *user_handle)
1998 {
1999         struct samr_DeleteUser d;
2000         NTSTATUS status;
2001         BOOL ret = True;
2002         printf("Testing DeleteUser\n");
2003
2004         d.in.user_handle = user_handle;
2005         d.out.user_handle = user_handle;
2006
2007         status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
2008         if (!NT_STATUS_IS_OK(status)) {
2009                 printf("DeleteUser failed - %s\n", nt_errstr(status));
2010                 ret = False;
2011         }
2012
2013         return ret;
2014 }
2015
2016 BOOL test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2017                             struct policy_handle *handle, const char *name)
2018 {
2019         NTSTATUS status;
2020         struct samr_DeleteUser d;
2021         struct policy_handle user_handle;
2022         uint32_t rid;
2023
2024         status = test_LookupName(p, mem_ctx, handle, name, &rid);
2025         if (!NT_STATUS_IS_OK(status)) {
2026                 goto failed;
2027         }
2028
2029         status = test_OpenUser_byname(p, mem_ctx, handle, name, &user_handle);
2030         if (!NT_STATUS_IS_OK(status)) {
2031                 goto failed;
2032         }
2033
2034         d.in.user_handle = &user_handle;
2035         d.out.user_handle = &user_handle;
2036         status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
2037         if (!NT_STATUS_IS_OK(status)) {
2038                 goto failed;
2039         }
2040
2041         return True;
2042
2043 failed:
2044         printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
2045         return False;
2046 }
2047
2048
2049 static BOOL test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2050                                     struct policy_handle *handle, const char *name)
2051 {
2052         NTSTATUS status;
2053         struct samr_OpenGroup r;
2054         struct samr_DeleteDomainGroup d;
2055         struct policy_handle group_handle;
2056         uint32_t rid;
2057
2058         status = test_LookupName(p, mem_ctx, handle, name, &rid);
2059         if (!NT_STATUS_IS_OK(status)) {
2060                 goto failed;
2061         }
2062
2063         r.in.domain_handle = handle;
2064         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2065         r.in.rid = rid;
2066         r.out.group_handle = &group_handle;
2067         status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
2068         if (!NT_STATUS_IS_OK(status)) {
2069                 goto failed;
2070         }
2071
2072         d.in.group_handle = &group_handle;
2073         d.out.group_handle = &group_handle;
2074         status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
2075         if (!NT_STATUS_IS_OK(status)) {
2076                 goto failed;
2077         }
2078
2079         return True;
2080
2081 failed:
2082         printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
2083         return False;
2084 }
2085
2086
2087 static BOOL test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2088                                    struct policy_handle *domain_handle, const char *name)
2089 {
2090         NTSTATUS status;
2091         struct samr_OpenAlias r;
2092         struct samr_DeleteDomAlias d;
2093         struct policy_handle alias_handle;
2094         uint32_t rid;
2095
2096         printf("testing DeleteAlias_byname\n");
2097
2098         status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
2099         if (!NT_STATUS_IS_OK(status)) {
2100                 goto failed;
2101         }
2102
2103         r.in.domain_handle = domain_handle;
2104         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2105         r.in.rid = rid;
2106         r.out.alias_handle = &alias_handle;
2107         status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
2108         if (!NT_STATUS_IS_OK(status)) {
2109                 goto failed;
2110         }
2111
2112         d.in.alias_handle = &alias_handle;
2113         d.out.alias_handle = &alias_handle;
2114         status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
2115         if (!NT_STATUS_IS_OK(status)) {
2116                 goto failed;
2117         }
2118
2119         return True;
2120
2121 failed:
2122         printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
2123         return False;
2124 }
2125
2126 static BOOL test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2127                                      struct policy_handle *alias_handle)
2128 {
2129         struct samr_DeleteDomAlias d;
2130         NTSTATUS status;
2131         BOOL ret = True;
2132         printf("Testing DeleteAlias\n");
2133
2134         d.in.alias_handle = alias_handle;
2135         d.out.alias_handle = alias_handle;
2136
2137         status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
2138         if (!NT_STATUS_IS_OK(status)) {
2139                 printf("DeleteAlias failed - %s\n", nt_errstr(status));
2140                 ret = False;
2141         }
2142
2143         return ret;
2144 }
2145
2146 static BOOL test_CreateAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2147                             struct policy_handle *domain_handle, 
2148                              struct policy_handle *alias_handle, 
2149                              const struct dom_sid *domain_sid)
2150 {
2151         NTSTATUS status;
2152         struct samr_CreateDomAlias r;
2153         struct lsa_String name;
2154         uint32_t rid;
2155         BOOL ret = True;
2156
2157         init_lsa_String(&name, TEST_ALIASNAME);
2158         r.in.domain_handle = domain_handle;
2159         r.in.alias_name = &name;
2160         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2161         r.out.alias_handle = alias_handle;
2162         r.out.rid = &rid;
2163
2164         printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
2165
2166         status = dcerpc_samr_CreateDomAlias(p, mem_ctx, &r);
2167
2168         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2169                 printf("Server refused create of '%s'\n", r.in.alias_name->string);
2170                 return True;
2171         }
2172
2173         if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
2174                 if (!test_DeleteAlias_byname(p, mem_ctx, domain_handle, r.in.alias_name->string)) {
2175                         return False;
2176                 }
2177                 status = dcerpc_samr_CreateDomAlias(p, mem_ctx, &r);
2178         }
2179
2180         if (!NT_STATUS_IS_OK(status)) {
2181                 printf("CreateAlias failed - %s\n", nt_errstr(status));
2182                 return False;
2183         }
2184
2185         if (!test_alias_ops(p, mem_ctx, alias_handle, domain_sid)) {
2186                 ret = False;
2187         }
2188
2189         return ret;
2190 }
2191
2192 static BOOL test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2193                                 const char *acct_name,
2194                                 struct policy_handle *domain_handle, char **password)
2195 {
2196         BOOL ret = True;
2197
2198         if (!*password) {
2199                 return False;
2200         }
2201
2202         if (!test_ChangePasswordUser(p, mem_ctx, acct_name, domain_handle, password)) {
2203                 ret = False;
2204         }
2205
2206         if (!test_ChangePasswordUser2(p, mem_ctx, acct_name, domain_handle, password)) {
2207                 ret = False;
2208         }
2209
2210         if (!test_OemChangePasswordUser2(p, mem_ctx, acct_name, domain_handle, password)) {
2211                 ret = False;
2212         }
2213
2214         /* test what happens when setting the old password again */
2215         if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, *password, 0, True)) {
2216                 ret = False;
2217         }
2218
2219         {
2220                 char simple_pass[9];
2221                 char *v = generate_random_str(mem_ctx, 1);
2222
2223                 ZERO_STRUCT(simple_pass);
2224                 memset(simple_pass, *v, sizeof(simple_pass) - 1);
2225
2226                 /* test what happens when picking a simple password */
2227                 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, simple_pass, 0, True)) {
2228                         ret = False;
2229                 }
2230         }
2231
2232         /* set samr_SetDomainInfo level 1 with min_length 5 */
2233         {
2234                 struct samr_QueryDomainInfo r;
2235                 struct samr_SetDomainInfo s;
2236                 uint16_t len_old, len;
2237                 uint32_t pwd_prop_old;
2238                 NTSTATUS status;
2239
2240                 len = 5;
2241
2242                 r.in.domain_handle = domain_handle;
2243                 r.in.level = 1;
2244
2245                 printf("testing samr_QueryDomainInfo level 1\n");
2246                 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
2247                 if (!NT_STATUS_IS_OK(status)) {
2248                         return False;
2249                 }
2250
2251                 s.in.domain_handle = domain_handle;
2252                 s.in.level = 1;
2253                 s.in.info = r.out.info;
2254
2255                 /* remember the old min length, so we can reset it */
2256                 len_old = s.in.info->info1.min_password_length;
2257                 s.in.info->info1.min_password_length = len;
2258                 pwd_prop_old = s.in.info->info1.password_properties;
2259                 /* turn off password complexity checks for this test */
2260                 s.in.info->info1.password_properties &= ~DOMAIN_PASSWORD_COMPLEX;
2261
2262                 printf("testing samr_SetDomainInfo level 1\n");
2263                 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
2264                 if (!NT_STATUS_IS_OK(status)) {
2265                         return False;
2266                 }
2267
2268                 printf("calling test_ChangePasswordUser3 with too short password\n");
2269
2270                 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, len - 1, password, NULL, 0, True)) {
2271                         ret = False;
2272                 }
2273
2274                 s.in.info->info1.min_password_length = len_old;
2275                 s.in.info->info1.password_properties = pwd_prop_old;
2276                 
2277                 printf("testing samr_SetDomainInfo level 1\n");
2278                 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
2279                 if (!NT_STATUS_IS_OK(status)) {
2280                         return False;
2281                 }
2282
2283         }
2284
2285         {
2286                 NTSTATUS status;
2287                 struct samr_OpenUser r;
2288                 struct samr_QueryUserInfo q;
2289                 struct samr_LookupNames n;
2290                 struct policy_handle user_handle;
2291
2292                 n.in.domain_handle = domain_handle;
2293                 n.in.num_names = 1;
2294                 n.in.names = talloc_array(mem_ctx, struct lsa_String, 1);
2295                 n.in.names[0].string = acct_name; 
2296
2297                 status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
2298                 if (!NT_STATUS_IS_OK(status)) {
2299                         printf("LookupNames failed - %s\n", nt_errstr(status));
2300                         return False;
2301                 }
2302
2303                 r.in.domain_handle = domain_handle;
2304                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2305                 r.in.rid = n.out.rids.ids[0];
2306                 r.out.user_handle = &user_handle;
2307
2308                 status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
2309                 if (!NT_STATUS_IS_OK(status)) {
2310                         printf("OpenUser(%u) failed - %s\n", n.out.rids.ids[0], nt_errstr(status));
2311                         return False;
2312                 }
2313
2314                 q.in.user_handle = &user_handle;
2315                 q.in.level = 5;
2316
2317                 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
2318                 if (!NT_STATUS_IS_OK(status)) {
2319                         printf("QueryUserInfo failed - %s\n", nt_errstr(status));
2320                         return False;
2321                 }
2322
2323                 printf("calling test_ChangePasswordUser3 with too early password change\n");
2324
2325                 if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 
2326                                               q.out.info->info5.last_password_change, True)) {
2327                         ret = False;
2328                 }
2329         }
2330
2331         /* we change passwords twice - this has the effect of verifying
2332            they were changed correctly for the final call */
2333         if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, True)) {
2334                 ret = False;
2335         }
2336
2337         if (!test_ChangePasswordUser3(p, mem_ctx, acct_name, 0, password, NULL, 0, True)) {
2338                 ret = False;
2339         }
2340
2341         return ret;
2342 }
2343
2344 static BOOL test_CreateUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2345                             struct policy_handle *domain_handle, 
2346                             struct policy_handle *user_handle_out, 
2347                             enum torture_samr_choice which_ops)
2348 {
2349
2350         TALLOC_CTX *user_ctx;
2351
2352         NTSTATUS status;
2353         struct samr_CreateUser r;
2354         struct samr_QueryUserInfo q;
2355         struct samr_DeleteUser d;
2356         uint32_t rid;
2357
2358         /* This call creates a 'normal' account - check that it really does */
2359         const uint32_t acct_flags = ACB_NORMAL;
2360         struct lsa_String name;
2361         BOOL ret = True;
2362
2363         struct policy_handle user_handle;
2364         user_ctx = talloc_named(mem_ctx, 0, "test_CreateUser2 per-user context");
2365         init_lsa_String(&name, TEST_ACCOUNT_NAME);
2366
2367         r.in.domain_handle = domain_handle;
2368         r.in.account_name = &name;
2369         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2370         r.out.user_handle = &user_handle;
2371         r.out.rid = &rid;
2372
2373         printf("Testing CreateUser(%s)\n", r.in.account_name->string);
2374
2375         status = dcerpc_samr_CreateUser(p, user_ctx, &r);
2376
2377         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2378                 printf("Server refused create of '%s': %s\n", r.in.account_name->string, nt_errstr(status));
2379                 talloc_free(user_ctx);
2380                 return True;
2381         }
2382
2383         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
2384                 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
2385                         talloc_free(user_ctx);
2386                         return False;
2387                 }
2388                 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
2389         }
2390         if (!NT_STATUS_IS_OK(status)) {
2391                 talloc_free(user_ctx);
2392                 printf("CreateUser failed - %s\n", nt_errstr(status));
2393                 return False;
2394         } else {
2395                 q.in.user_handle = &user_handle;
2396                 q.in.level = 16;
2397                 
2398                 status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
2399                 if (!NT_STATUS_IS_OK(status)) {
2400                         printf("QueryUserInfo level %u failed - %s\n", 
2401                                q.in.level, nt_errstr(status));
2402                         ret = False;
2403                 } else {
2404                         if ((q.out.info->info16.acct_flags & acct_flags) != acct_flags) {
2405                                 printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
2406                                        q.out.info->info16.acct_flags, 
2407                                        acct_flags);
2408                                 ret = False;
2409                         }
2410                 }
2411                 
2412                 if (!test_user_ops(p, user_ctx, &user_handle, domain_handle, 
2413                                    acct_flags, name.string, which_ops)) {
2414                         ret = False;
2415                 }
2416                 
2417                 if (user_handle_out) {
2418                         *user_handle_out = user_handle;
2419                 } else {
2420                         printf("Testing DeleteUser (createuser test)\n");
2421                         
2422                         d.in.user_handle = &user_handle;
2423                         d.out.user_handle = &user_handle;
2424                         
2425                         status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
2426                         if (!NT_STATUS_IS_OK(status)) {
2427                                 printf("DeleteUser failed - %s\n", nt_errstr(status));
2428                                 ret = False;
2429                         }
2430                 }
2431                 
2432         }
2433
2434         talloc_free(user_ctx);
2435         
2436         return ret;
2437 }
2438
2439
2440 static BOOL test_CreateUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2441                              struct policy_handle *domain_handle, enum torture_samr_choice which_ops)
2442 {
2443         NTSTATUS status;
2444         struct samr_CreateUser2 r;
2445         struct samr_QueryUserInfo q;
2446         struct samr_DeleteUser d;
2447         struct policy_handle user_handle;
2448         uint32_t rid;
2449         struct lsa_String name;
2450         BOOL ret = True;
2451         int i;
2452
2453         struct {
2454                 uint32_t acct_flags;
2455                 const char *account_name;
2456                 NTSTATUS nt_status;
2457         } account_types[] = {
2458                 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
2459                 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
2460                 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
2461                 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
2462                 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
2463                 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
2464                 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
2465                 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
2466                 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
2467                 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
2468                 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
2469                 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
2470                 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
2471                 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
2472                 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
2473         };
2474
2475         for (i = 0; account_types[i].account_name; i++) {
2476                 TALLOC_CTX *user_ctx;
2477                 uint32_t acct_flags = account_types[i].acct_flags;
2478                 uint32_t access_granted;
2479                 user_ctx = talloc_named(mem_ctx, 0, "test_CreateUser2 per-user context");
2480                 init_lsa_String(&name, account_types[i].account_name);
2481
2482                 r.in.domain_handle = domain_handle;
2483                 r.in.account_name = &name;
2484                 r.in.acct_flags = acct_flags;
2485                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2486                 r.out.user_handle = &user_handle;
2487                 r.out.access_granted = &access_granted;
2488                 r.out.rid = &rid;
2489                 
2490                 printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
2491                 
2492                 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
2493                 
2494                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
2495                         talloc_free(user_ctx);
2496                         printf("Server refused create of '%s'\n", r.in.account_name->string);
2497                         continue;
2498
2499                 } else if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
2500                         if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
2501                                 talloc_free(user_ctx);
2502                                 ret = False;
2503                                 continue;
2504                         }
2505                         status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
2506
2507                 }
2508                 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
2509                         printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n", 
2510                                nt_errstr(status), nt_errstr(account_types[i].nt_status));
2511                         ret = False;
2512                 }
2513                 
2514                 if (NT_STATUS_IS_OK(status)) {
2515                         q.in.user_handle = &user_handle;
2516                         q.in.level = 5;
2517                         
2518                         status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
2519                         if (!NT_STATUS_IS_OK(status)) {
2520                                 printf("QueryUserInfo level %u failed - %s\n", 
2521                                        q.in.level, nt_errstr(status));
2522                                 ret = False;
2523                         } else {
2524                                 if ((q.out.info->info5.acct_flags & acct_flags) != acct_flags) {
2525                                         printf("QuerUserInfo level 5 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
2526                                                q.out.info->info5.acct_flags, 
2527                                                acct_flags);
2528                                         ret = False;
2529                                 } 
2530                                 switch (acct_flags) {
2531                                 case ACB_SVRTRUST:
2532                                         if (q.out.info->info5.primary_gid != DOMAIN_RID_DCS) {
2533                                                 printf("QuerUserInfo level 5: DC should have had Primary Group %d, got %d\n", 
2534                                                        DOMAIN_RID_DCS, q.out.info->info5.primary_gid);
2535                                                 ret = False;
2536                                         }
2537                                         break;
2538                                 case ACB_WSTRUST:
2539                                         if (q.out.info->info5.primary_gid != DOMAIN_RID_DOMAIN_MEMBERS) {
2540                                                 printf("QuerUserInfo level 5: Domain Member should have had Primary Group %d, got %d\n", 
2541                                                        DOMAIN_RID_DOMAIN_MEMBERS, q.out.info->info5.primary_gid);
2542                                                 ret = False;
2543                                         }
2544                                         break;
2545                                 case ACB_NORMAL:
2546                                         if (q.out.info->info5.primary_gid != DOMAIN_RID_USERS) {
2547                                                 printf("QuerUserInfo level 5: Users should have had Primary Group %d, got %d\n", 
2548                                                        DOMAIN_RID_USERS, q.out.info->info5.primary_gid);
2549                                                 ret = False;
2550                                         }
2551                                         break;
2552                                 }
2553                         }
2554                 
2555                         if (!test_user_ops(p, user_ctx, &user_handle, domain_handle, 
2556                                            acct_flags, name.string, which_ops)) {
2557                                 ret = False;
2558                         }
2559
2560                         printf("Testing DeleteUser (createuser2 test)\n");
2561                 
2562                         d.in.user_handle = &user_handle;
2563                         d.out.user_handle = &user_handle;
2564                         
2565                         status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
2566                         if (!NT_STATUS_IS_OK(status)) {
2567                                 printf("DeleteUser failed - %s\n", nt_errstr(status));
2568                                 ret = False;
2569                         }
2570                 }
2571                 talloc_free(user_ctx);
2572         }
2573
2574         return ret;
2575 }
2576
2577 static BOOL test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2578                                 struct policy_handle *handle)
2579 {
2580         NTSTATUS status;
2581         struct samr_QueryAliasInfo r;
2582         uint16_t levels[] = {1, 2, 3};
2583         int i;
2584         BOOL ret = True;
2585
2586         for (i=0;i<ARRAY_SIZE(levels);i++) {
2587                 printf("Testing QueryAliasInfo level %u\n", levels[i]);
2588
2589                 r.in.alias_handle = handle;
2590                 r.in.level = levels[i];
2591
2592                 status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
2593                 if (!NT_STATUS_IS_OK(status)) {
2594                         printf("QueryAliasInfo level %u failed - %s\n", 
2595                                levels[i], nt_errstr(status));
2596                         ret = False;
2597                 }
2598         }
2599
2600         return ret;
2601 }
2602
2603 static BOOL test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2604                                 struct policy_handle *handle)
2605 {
2606         NTSTATUS status;
2607         struct samr_QueryGroupInfo r;
2608         uint16_t levels[] = {1, 2, 3, 4, 5};
2609         int i;
2610         BOOL ret = True;
2611
2612         for (i=0;i<ARRAY_SIZE(levels);i++) {
2613                 printf("Testing QueryGroupInfo level %u\n", levels[i]);
2614
2615                 r.in.group_handle = handle;
2616                 r.in.level = levels[i];
2617
2618                 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
2619                 if (!NT_STATUS_IS_OK(status)) {
2620                         printf("QueryGroupInfo level %u failed - %s\n", 
2621                                levels[i], nt_errstr(status));
2622                         ret = False;
2623                 }
2624         }
2625
2626         return ret;
2627 }
2628
2629 static BOOL test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2630                                   struct policy_handle *handle)
2631 {
2632         NTSTATUS status;
2633         struct samr_QueryGroupMember r;
2634         BOOL ret = True;
2635
2636         printf("Testing QueryGroupMember\n");
2637
2638         r.in.group_handle = handle;
2639
2640         status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r);
2641         if (!NT_STATUS_IS_OK(status)) {
2642                 printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
2643                 ret = False;
2644         }
2645
2646         return ret;
2647 }
2648
2649
2650 static BOOL test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2651                               struct policy_handle *handle)
2652 {
2653         NTSTATUS status;
2654         struct samr_QueryGroupInfo r;
2655         struct samr_SetGroupInfo s;
2656         uint16_t levels[] = {1, 2, 3, 4};
2657         uint16_t set_ok[] = {0, 1, 1, 1};
2658         int i;
2659         BOOL ret = True;
2660
2661         for (i=0;i<ARRAY_SIZE(levels);i++) {
2662                 printf("Testing QueryGroupInfo level %u\n", levels[i]);
2663
2664                 r.in.group_handle = handle;
2665                 r.in.level = levels[i];
2666
2667                 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
2668                 if (!NT_STATUS_IS_OK(status)) {
2669                         printf("QueryGroupInfo level %u failed - %s\n", 
2670                                levels[i], nt_errstr(status));
2671                         ret = False;
2672                 }
2673
2674                 printf("Testing SetGroupInfo level %u\n", levels[i]);
2675
2676                 s.in.group_handle = handle;
2677                 s.in.level = levels[i];
2678                 s.in.info = r.out.info;
2679
2680 #if 0
2681                 /* disabled this, as it changes the name only from the point of view of samr, 
2682                    but leaves the name from the point of view of w2k3 internals (and ldap). This means
2683                    the name is still reserved, so creating the old name fails, but deleting by the old name
2684                    also fails */
2685                 if (s.in.level == 2) {
2686                         init_lsa_String(&s.in.info->string, "NewName");
2687                 }
2688 #endif
2689
2690                 if (s.in.level == 4) {
2691                         init_lsa_String(&s.in.info->description, "test description");
2692                 }
2693
2694                 status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
2695                 if (set_ok[i]) {
2696                         if (!NT_STATUS_IS_OK(status)) {
2697                                 printf("SetGroupInfo level %u failed - %s\n", 
2698                                        r.in.level, nt_errstr(status));
2699                                 ret = False;
2700                                 continue;
2701                         }
2702                 } else {
2703                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
2704                                 printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n", 
2705                                        r.in.level, nt_errstr(status));
2706                                 ret = False;
2707                                 continue;
2708                         }
2709                 }
2710         }
2711
2712         return ret;
2713 }
2714
2715 static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2716                                struct policy_handle *handle)
2717 {
2718         NTSTATUS status;
2719         struct samr_QueryUserInfo r;
2720         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2721                            11, 12, 13, 14, 16, 17, 20, 21};
2722         int i;
2723         BOOL ret = True;
2724
2725         for (i=0;i<ARRAY_SIZE(levels);i++) {
2726                 printf("Testing QueryUserInfo level %u\n", levels[i]);
2727
2728                 r.in.user_handle = handle;
2729                 r.in.level = levels[i];
2730
2731                 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r);
2732                 if (!NT_STATUS_IS_OK(status)) {
2733                         printf("QueryUserInfo level %u failed - %s\n", 
2734                                levels[i], nt_errstr(status));
2735                         ret = False;
2736                 }
2737         }
2738
2739         return ret;
2740 }
2741
2742 static BOOL test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2743                                 struct policy_handle *handle)
2744 {
2745         NTSTATUS status;
2746         struct samr_QueryUserInfo2 r;
2747         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2748                            11, 12, 13, 14, 16, 17, 20, 21};
2749         int i;
2750         BOOL ret = True;
2751
2752         for (i=0;i<ARRAY_SIZE(levels);i++) {
2753                 printf("Testing QueryUserInfo2 level %u\n", levels[i]);
2754
2755                 r.in.user_handle = handle;
2756                 r.in.level = levels[i];
2757
2758                 status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r);
2759                 if (!NT_STATUS_IS_OK(status)) {
2760                         printf("QueryUserInfo2 level %u failed - %s\n", 
2761                                levels[i], nt_errstr(status));
2762                         ret = False;
2763                 }
2764         }
2765
2766         return ret;
2767 }
2768
2769 static BOOL test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2770                           struct policy_handle *handle, uint32_t rid)
2771 {
2772         NTSTATUS status;
2773         struct samr_OpenUser r;
2774         struct policy_handle user_handle;
2775         BOOL ret = True;
2776
2777         printf("Testing OpenUser(%u)\n", rid);
2778
2779         r.in.domain_handle = handle;
2780         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2781         r.in.rid = rid;
2782         r.out.user_handle = &user_handle;
2783
2784         status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
2785         if (!NT_STATUS_IS_OK(status)) {
2786                 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
2787                 return False;
2788         }
2789
2790         if (!test_QuerySecurity(p, mem_ctx, &user_handle)) {
2791                 ret = False;
2792         }
2793
2794         if (!test_QueryUserInfo(p, mem_ctx, &user_handle)) {
2795                 ret = False;
2796         }
2797
2798         if (!test_QueryUserInfo2(p, mem_ctx, &user_handle)) {
2799                 ret = False;
2800         }
2801
2802         if (!test_GetUserPwInfo(p, mem_ctx, &user_handle)) {
2803                 ret = False;
2804         }
2805
2806         if (!test_GetGroupsForUser(p,mem_ctx, &user_handle)) {
2807                 ret = False;
2808         }
2809
2810         if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
2811                 ret = False;
2812         }
2813
2814         return ret;
2815 }
2816
2817 static BOOL test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2818                            struct policy_handle *handle, uint32_t rid)
2819 {
2820         NTSTATUS status;
2821         struct samr_OpenGroup r;
2822         struct policy_handle group_handle;
2823         BOOL ret = True;
2824
2825         printf("Testing OpenGroup(%u)\n", rid);
2826
2827         r.in.domain_handle = handle;
2828         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2829         r.in.rid = rid;
2830         r.out.group_handle = &group_handle;
2831
2832         status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
2833         if (!NT_STATUS_IS_OK(status)) {
2834                 printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
2835                 return False;
2836         }
2837
2838         if (!test_QuerySecurity(p, mem_ctx, &group_handle)) {
2839                 ret = False;
2840         }
2841
2842         if (!test_QueryGroupInfo(p, mem_ctx, &group_handle)) {
2843                 ret = False;
2844         }
2845
2846         if (!test_QueryGroupMember(p, mem_ctx, &group_handle)) {
2847                 ret = False;
2848         }
2849
2850         if (!test_samr_handle_Close(p, mem_ctx, &group_handle)) {
2851                 ret = False;
2852         }
2853
2854         return ret;
2855 }
2856
2857 static BOOL test_OpenAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2858                            struct policy_handle *handle, uint32_t rid)
2859 {
2860         NTSTATUS status;
2861         struct samr_OpenAlias r;
2862         struct policy_handle alias_handle;
2863         BOOL ret = True;
2864
2865         printf("Testing OpenAlias(%u)\n", rid);
2866
2867         r.in.domain_handle = handle;
2868         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2869         r.in.rid = rid;
2870         r.out.alias_handle = &alias_handle;
2871
2872         status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
2873         if (!NT_STATUS_IS_OK(status)) {
2874                 printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
2875                 return False;
2876         }
2877
2878         if (!test_QuerySecurity(p, mem_ctx, &alias_handle)) {
2879                 ret = False;
2880         }
2881
2882         if (!test_QueryAliasInfo(p, mem_ctx, &alias_handle)) {
2883                 ret = False;
2884         }
2885
2886         if (!test_GetMembersInAlias(p, mem_ctx, &alias_handle)) {
2887                 ret = False;
2888         }
2889
2890         if (!test_samr_handle_Close(p, mem_ctx, &alias_handle)) {
2891                 ret = False;
2892         }
2893
2894         return ret;
2895 }
2896
2897 static BOOL check_mask(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2898                        struct policy_handle *handle, uint32_t rid, 
2899                        uint32_t acct_flag_mask)
2900 {
2901         NTSTATUS status;
2902         struct samr_OpenUser r;
2903         struct samr_QueryUserInfo q;
2904         struct policy_handle user_handle;
2905         BOOL ret = True;
2906
2907         printf("Testing OpenUser(%u)\n", rid);
2908
2909         r.in.domain_handle = handle;
2910         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2911         r.in.rid = rid;
2912         r.out.user_handle = &user_handle;
2913
2914         status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
2915         if (!NT_STATUS_IS_OK(status)) {
2916                 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
2917                 return False;
2918         }
2919
2920         q.in.user_handle = &user_handle;
2921         q.in.level = 16;
2922         
2923         status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
2924         if (!NT_STATUS_IS_OK(status)) {
2925                 printf("QueryUserInfo level 16 failed - %s\n", 
2926                        nt_errstr(status));
2927                 ret = False;
2928         } else {
2929                 if ((acct_flag_mask & q.out.info->info16.acct_flags) == 0) {
2930                         printf("Server failed to filter for 0x%x, allowed 0x%x (%d) on EnumDomainUsers\n",
2931                                acct_flag_mask, q.out.info->info16.acct_flags, rid);
2932                         ret = False;
2933                 }
2934         }
2935         
2936         if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
2937                 ret = False;
2938         }
2939
2940         return ret;
2941 }
2942
2943 static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2944                                  struct policy_handle *handle)
2945 {
2946         NTSTATUS status = STATUS_MORE_ENTRIES;
2947         struct samr_EnumDomainUsers r;
2948         uint32_t mask, resume_handle=0;
2949         int i, mask_idx;
2950         BOOL ret = True;
2951         struct samr_LookupNames n;
2952         struct samr_LookupRids  lr ;
2953         uint32_t masks[] = {ACB_NORMAL, ACB_DOMTRUST, ACB_WSTRUST, 
2954                             ACB_DISABLED, ACB_NORMAL | ACB_DISABLED, 
2955                             ACB_SVRTRUST | ACB_DOMTRUST | ACB_WSTRUST, 
2956                             ACB_PWNOEXP, 0};
2957
2958         printf("Testing EnumDomainUsers\n");
2959
2960         for (mask_idx=0;mask_idx<ARRAY_SIZE(masks);mask_idx++) {
2961                 r.in.domain_handle = handle;
2962                 r.in.resume_handle = &resume_handle;
2963                 r.in.acct_flags = mask = masks[mask_idx];
2964                 r.in.max_size = (uint32_t)-1;
2965                 r.out.resume_handle = &resume_handle;
2966
2967                 status = dcerpc_samr_EnumDomainUsers(p, mem_ctx, &r);
2968                 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&  
2969                     !NT_STATUS_IS_OK(status)) {
2970                         printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
2971                         return False;
2972                 }
2973         
2974                 if (!r.out.sam) {
2975                         printf("EnumDomainUsers failed: r.out.sam unexpectedly NULL\n");
2976                         return False;
2977                 }
2978
2979                 if (r.out.sam->count == 0) {
2980                         continue;
2981                 }
2982
2983                 for (i=0;i<r.out.sam->count;i++) {
2984                         if (mask) {
2985                                 if (!check_mask(p, mem_ctx, handle, r.out.sam->entries[i].idx, mask)) {
2986                                         ret = False;
2987                                 }
2988                         } else if (!test_OpenUser(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
2989                                 ret = False;
2990                         }
2991                 }
2992         }
2993
2994         printf("Testing LookupNames\n");
2995         n.in.domain_handle = handle;
2996         n.in.num_names = r.out.sam->count;
2997         n.in.names = talloc_array(mem_ctx, struct lsa_String, r.out.sam->count);
2998         for (i=0;i<r.out.sam->count;i++) {
2999                 n.in.names[i].string = r.out.sam->entries[i].name.string;
3000         }
3001         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
3002         if (!NT_STATUS_IS_OK(status)) {
3003                 printf("LookupNames failed - %s\n", nt_errstr(status));
3004                 ret = False;
3005         }
3006
3007
3008         printf("Testing LookupRids\n");
3009         lr.in.domain_handle = handle;
3010         lr.in.num_rids = r.out.sam->count;
3011         lr.in.rids = talloc_array(mem_ctx, uint32_t, r.out.sam->count);
3012         for (i=0;i<r.out.sam->count;i++) {
3013                 lr.in.rids[i] = r.out.sam->entries[i].idx;
3014         }
3015         status = dcerpc_samr_LookupRids(p, mem_ctx, &lr);
3016         if (!NT_STATUS_IS_OK(status)) {
3017                 printf("LookupRids failed - %s\n", nt_errstr(status));
3018                 ret = False;
3019         }
3020
3021         return ret;     
3022 }
3023
3024 /*
3025   try blasting the server with a bunch of sync requests
3026 */
3027 static BOOL test_EnumDomainUsers_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3028                                        struct policy_handle *handle)
3029 {
3030         NTSTATUS status;
3031         struct samr_EnumDomainUsers r;
3032         uint32_t resume_handle=0;
3033         int i;
3034 #define ASYNC_COUNT 100
3035         struct rpc_request *req[ASYNC_COUNT];
3036
3037         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
3038                 printf("samr async test disabled - enable dangerous tests to use\n");
3039                 return True;
3040         }
3041
3042         printf("Testing EnumDomainUsers_async\n");
3043
3044         r.in.domain_handle = handle;
3045         r.in.resume_handle = &resume_handle;
3046         r.in.acct_flags = 0;
3047         r.in.max_size = (uint32_t)-1;
3048         r.out.resume_handle = &resume_handle;
3049
3050         for (i=0;i<ASYNC_COUNT;i++) {
3051                 req[i] = dcerpc_samr_EnumDomainUsers_send(p, mem_ctx, &r);
3052         }
3053
3054         for (i=0;i<ASYNC_COUNT;i++) {
3055                 status = dcerpc_ndr_request_recv(req[i]);
3056                 if (!NT_STATUS_IS_OK(status)) {
3057                         printf("EnumDomainUsers[%d] failed - %s\n", 
3058                                i, nt_errstr(status));
3059                         return False;
3060                 }
3061         }
3062         
3063         printf("%d async requests OK\n", i);
3064
3065         return True;
3066 }
3067
3068 static BOOL test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3069                                   struct policy_handle *handle)
3070 {
3071         NTSTATUS status;
3072         struct samr_EnumDomainGroups r;
3073         uint32_t resume_handle=0;
3074         int i;
3075         BOOL ret = True;
3076
3077         printf("Testing EnumDomainGroups\n");
3078
3079         r.in.domain_handle = handle;
3080         r.in.resume_handle = &resume_handle;
3081         r.in.max_size = (uint32_t)-1;
3082         r.out.resume_handle = &resume_handle;
3083
3084         status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
3085         if (!NT_STATUS_IS_OK(status)) {
3086                 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
3087                 return False;
3088         }
3089         
3090         if (!r.out.sam) {
3091                 return False;
3092         }
3093
3094         for (i=0;i<r.out.sam->count;i++) {
3095                 if (!test_OpenGroup(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
3096                         ret = False;
3097                 }
3098         }
3099
3100         return ret;
3101 }
3102
3103 static BOOL test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3104                                    struct policy_handle *handle)
3105 {
3106         NTSTATUS status;
3107         struct samr_EnumDomainAliases r;
3108         uint32_t resume_handle=0;
3109         int i;
3110         BOOL ret = True;
3111
3112         printf("Testing EnumDomainAliases\n");
3113
3114         r.in.domain_handle = handle;
3115         r.in.resume_handle = &resume_handle;
3116         r.in.acct_flags = (uint32_t)-1;
3117         r.out.resume_handle = &resume_handle;
3118
3119         status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
3120         if (!NT_STATUS_IS_OK(status)) {
3121                 printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
3122                 return False;
3123         }
3124         
3125         if (!r.out.sam) {
3126                 return False;
3127         }
3128
3129         for (i=0;i<r.out.sam->count;i++) {
3130                 if (!test_OpenAlias(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
3131                         ret = False;
3132                 }
3133         }
3134
3135         return ret;     
3136 }
3137
3138 static BOOL test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3139                                             struct policy_handle *handle)
3140 {
3141         NTSTATUS status;
3142         struct samr_GetDisplayEnumerationIndex r;
3143         BOOL ret = True;
3144         uint16_t levels[] = {1, 2, 3, 4, 5};
3145         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
3146         int i;
3147
3148         for (i=0;i<ARRAY_SIZE(levels);i++) {
3149                 printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
3150
3151                 r.in.domain_handle = handle;
3152                 r.in.level = levels[i];
3153                 init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME);
3154
3155                 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
3156
3157                 if (ok_lvl[i] && 
3158                     !NT_STATUS_IS_OK(status) &&
3159                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
3160                         printf("GetDisplayEnumerationIndex level %u failed - %s\n", 
3161                                levels[i], nt_errstr(status));
3162                         ret = False;
3163                 }
3164
3165                 init_lsa_String(&r.in.name, "zzzzzzzz");
3166
3167                 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
3168                 
3169                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
3170                         printf("GetDisplayEnumerationIndex level %u failed - %s\n", 
3171                                levels[i], nt_errstr(status));
3172                         ret = False;
3173                 }
3174         }
3175         
3176         return ret;     
3177 }
3178
3179 static BOOL test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3180                                              struct policy_handle *handle)
3181 {
3182         NTSTATUS status;
3183         struct samr_GetDisplayEnumerationIndex2 r;
3184         BOOL ret = True;
3185         uint16_t levels[] = {1, 2, 3, 4, 5};
3186         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
3187         int i;
3188
3189         for (i=0;i<ARRAY_SIZE(levels);i++) {
3190                 printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
3191
3192                 r.in.domain_handle = handle;
3193                 r.in.level = levels[i];
3194                 init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME);
3195
3196                 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
3197                 if (ok_lvl[i] && 
3198                     !NT_STATUS_IS_OK(status) && 
3199                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
3200                         printf("GetDisplayEnumerationIndex2 level %u failed - %s\n", 
3201                                levels[i], nt_errstr(status));
3202                         ret = False;
3203                 }
3204
3205                 init_lsa_String(&r.in.name, "zzzzzzzz");
3206
3207                 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
3208                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
3209                         printf("GetDisplayEnumerationIndex2 level %u failed - %s\n", 
3210                                levels[i], nt_errstr(status));
3211                         ret = False;
3212                 }
3213         }
3214         
3215         return ret;     
3216 }
3217
3218 #define STRING_EQUAL_QUERY(s1, s2, user)                                        \
3219         if (s1.string == NULL && s2.string != NULL && s2.string[0] == '\0') { \
3220                 /* odd, but valid */                                            \
3221         } else if ((s1.string && !s2.string) || (s2.string && !s1.string) || strcmp(s1.string, s2.string)) { \
3222                         printf("%s mismatch for %s: %s != %s (%s)\n", \
3223                                #s1, user.string,  s1.string, s2.string, __location__);   \
3224                         ret = False; \
3225         }
3226 #define INT_EQUAL_QUERY(s1, s2, user)           \
3227                 if (s1 != s2) { \
3228                         printf("%s mismatch for %s: 0x%x != 0x%x (%s)\n", \
3229                                #s1, user.string, (unsigned int)s1, (unsigned int)s2, __location__); \
3230                         ret = False; \
3231                 }
3232
3233 static BOOL test_each_DisplayInfo_user(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3234                                        struct samr_QueryDisplayInfo *querydisplayinfo,
3235                                        bool *seen_testuser) 
3236 {
3237         struct samr_OpenUser r;
3238         struct samr_QueryUserInfo q;
3239         struct policy_handle user_handle;
3240         int i, ret = True;
3241         NTSTATUS status;
3242         r.in.domain_handle = querydisplayinfo->in.domain_handle;
3243         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3244         for (i = 0; ; i++) {
3245                 switch (querydisplayinfo->in.level) {
3246                 case 1:
3247                         if (i >= querydisplayinfo->out.info.info1.count) {
3248                                 return ret;
3249                         }
3250                         r.in.rid = querydisplayinfo->out.info.info1.entries[i].rid;
3251                         break;
3252                 case 2:
3253                         if (i >= querydisplayinfo->out.info.info2.count) {
3254                                 return ret;
3255                         }
3256                         r.in.rid = querydisplayinfo->out.info.info2.entries[i].rid;
3257                         break;
3258                 case 3:
3259                         /* Groups */
3260                 case 4:
3261                 case 5:
3262                         /* Not interested in validating just the account name */
3263                         return true;
3264                 }
3265                         
3266                 r.out.user_handle = &user_handle;
3267                 
3268                 switch (querydisplayinfo->in.level) {
3269                 case 1:
3270                 case 2:
3271                         status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
3272                         if (!NT_STATUS_IS_OK(status)) {
3273                                 printf("OpenUser(%u) failed - %s\n", r.in.rid, nt_errstr(status));
3274                                 return False;
3275                         }
3276                 }
3277                 
3278                 q.in.user_handle = &user_handle;
3279                 q.in.level = 21;
3280                 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &q);
3281                 if (!NT_STATUS_IS_OK(status)) {
3282                         printf("QueryUserInfo(%u) failed - %s\n", r.in.rid, nt_errstr(status));
3283                         return False;
3284                 }
3285                 
3286                 switch (querydisplayinfo->in.level) {
3287                 case 1:
3288                         if (seen_testuser && strcmp(q.out.info->info21.account_name.string, TEST_ACCOUNT_NAME) == 0) {
3289                                 *seen_testuser = true;
3290                         }
3291                         STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].full_name, 
3292                                            q.out.info->info21.full_name, q.out.info->info21.account_name);
3293                         STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].account_name, 
3294                                            q.out.info->info21.account_name, q.out.info->info21.account_name);
3295                         STRING_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].description, 
3296                                            q.out.info->info21.description, q.out.info->info21.account_name);
3297                         INT_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].rid, 
3298                                         q.out.info->info21.rid, q.out.info->info21.account_name);
3299                         INT_EQUAL_QUERY(querydisplayinfo->out.info.info1.entries[i].acct_flags, 
3300                                         q.out.info->info21.acct_flags, q.out.info->info21.account_name);
3301                         
3302                         break;
3303                 case 2:
3304                         STRING_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].account_name, 
3305                                            q.out.info->info21.account_name, q.out.info->info21.account_name);
3306                         STRING_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].description, 
3307                                            q.out.info->info21.description, q.out.info->info21.account_name);
3308                         INT_EQUAL_QUERY(querydisplayinfo->out.info.info2.entries[i].rid, 
3309                                         q.out.info->info21.rid, q.out.info->info21.account_name);
3310                         INT_EQUAL_QUERY((querydisplayinfo->out.info.info2.entries[i].acct_flags & ~ACB_NORMAL), 
3311                                         q.out.info->info21.acct_flags, q.out.info->info21.account_name);
3312                         
3313                         if (!(querydisplayinfo->out.info.info2.entries[i].acct_flags & ACB_NORMAL)) {
3314                                 printf("Missing ACB_NORMAL in querydisplayinfo->out.info.info2.entries[i].acct_flags on %s\n", 
3315                                        q.out.info->info21.account_name.string);
3316                         }
3317
3318                         if (!(q.out.info->info21.acct_flags & (ACB_WSTRUST | ACB_SVRTRUST))) {
3319                                 printf("Found non-trust account %s in trust account listing: 0x%x 0x%x\n",
3320                                        q.out.info->info21.account_name.string,
3321                                        querydisplayinfo->out.info.info2.entries[i].acct_flags,
3322                                        q.out.info->info21.acct_flags);
3323                                 return False;
3324                         }
3325                         
3326                         break;
3327                 }
3328                 
3329                 if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
3330                         return False;
3331                 }
3332         }
3333         return ret;
3334 }
3335
3336 static BOOL test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3337                                   struct policy_handle *handle)
3338 {
3339         NTSTATUS status;
3340         struct samr_QueryDisplayInfo r;
3341         struct samr_QueryDomainInfo dom_info;
3342         BOOL ret = True;
3343         uint16_t levels[] = {1, 2, 3, 4, 5};
3344         int i;
3345         bool seen_testuser = false;
3346
3347         for (i=0;i<ARRAY_SIZE(levels);i++) {
3348                 printf("Testing QueryDisplayInfo level %u\n", levels[i]);
3349
3350                 r.in.start_idx = 0;
3351                 status = STATUS_MORE_ENTRIES;
3352                 while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
3353                         r.in.domain_handle = handle;
3354                         r.in.level = levels[i];
3355                         r.in.max_entries = 2;
3356                         r.in.buf_size = (uint32_t)-1;
3357                         
3358                         status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
3359                         if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && !NT_STATUS_IS_OK(status)) {
3360                                 printf("QueryDisplayInfo level %u failed - %s\n", 
3361                                        levels[i], nt_errstr(status));
3362                                 ret = False;
3363                         }
3364                         switch (r.in.level) {
3365                         case 1:
3366                                 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, &seen_testuser)) {
3367                                         ret = False;
3368                                 }
3369                                 r.in.start_idx += r.out.info.info1.count;
3370                                 break;
3371                         case 2:
3372                                 if (!test_each_DisplayInfo_user(p, mem_ctx, &r, NULL)) {
3373                                         ret = False;
3374                                 }
3375                                 r.in.start_idx += r.out.info.info2.count;
3376                                 break;
3377                         case 3:
3378                                 r.in.start_idx += r.out.info.info3.count;
3379                                 break;
3380                         case 4:
3381                                 r.in.start_idx += r.out.info.info4.count;
3382                                 break;
3383                         case 5:
3384                                 r.in.start_idx += r.out.info.info5.count;
3385                                 break;
3386                         }
3387                 }
3388                 dom_info.in.domain_handle = handle;
3389                 dom_info.in.level = 2;
3390                 /* Check number of users returned is correct */
3391                 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &dom_info);
3392                 if (!NT_STATUS_IS_OK(status)) {
3393                         printf("QueryDomainInfo level %u failed - %s\n", 
3394                                r.in.level, nt_errstr(status));
3395                                 ret = False;
3396                                 break;
3397                 }
3398                 switch (r.in.level) {
3399                 case 1:
3400                 case 4:
3401                         if (dom_info.out.info->info2.num_users < r.in.start_idx) {
3402                                 printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
3403                                        r.in.start_idx, dom_info.out.info->info2.num_groups,
3404                                        dom_info.out.info->info2.domain_name.string);
3405                                 ret = False;
3406                         }
3407                         if (!seen_testuser) {
3408                                 struct policy_handle user_handle;
3409                                 if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
3410                                         printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n", 
3411                                                dom_info.out.info->info2.domain_name.string);
3412                                         ret = False;
3413                                         test_samr_handle_Close(p, mem_ctx, &user_handle);
3414                                 }
3415                         }
3416                         break;
3417                 case 3:
3418                 case 5:
3419                         if (dom_info.out.info->info2.num_groups != r.in.start_idx) {
3420                                 printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
3421                                        r.in.start_idx, dom_info.out.info->info2.num_groups,
3422                                        dom_info.out.info->info2.domain_name.string);
3423                                 ret = False;
3424                         }
3425                         
3426                         break;
3427                 }
3428
3429         }
3430         
3431         return ret;     
3432 }
3433
3434 static BOOL test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3435                                   struct policy_handle *handle)
3436 {
3437         NTSTATUS status;
3438         struct samr_QueryDisplayInfo2 r;
3439         BOOL ret = True;
3440         uint16_t levels[] = {1, 2, 3, 4, 5};
3441         int i;
3442
3443         for (i=0;i<ARRAY_SIZE(levels);i++) {
3444                 printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
3445
3446                 r.in.domain_handle = handle;
3447                 r.in.level = levels[i];
3448                 r.in.start_idx = 0;
3449                 r.in.max_entries = 1000;
3450                 r.in.buf_size = (uint32_t)-1;
3451
3452                 status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
3453                 if (!NT_STATUS_IS_OK(status)) {
3454                         printf("QueryDisplayInfo2 level %u failed - %s\n", 
3455                                levels[i], nt_errstr(status));
3456                         ret = False;
3457                 }
3458         }
3459         
3460         return ret;     
3461 }
3462
3463 static BOOL test_QueryDisplayInfo3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3464                                   struct policy_handle *handle)
3465 {
3466         NTSTATUS status;
3467         struct samr_QueryDisplayInfo3 r;
3468         BOOL ret = True;
3469         uint16_t levels[] = {1, 2, 3, 4, 5};
3470         int i;
3471
3472         for (i=0;i<ARRAY_SIZE(levels);i++) {
3473                 printf("Testing QueryDisplayInfo3 level %u\n", levels[i]);
3474
3475                 r.in.domain_handle = handle;
3476                 r.in.level = levels[i];
3477                 r.in.start_idx = 0;
3478                 r.in.max_entries = 1000;
3479                 r.in.buf_size = (uint32_t)-1;
3480
3481                 status = dcerpc_samr_QueryDisplayInfo3(p, mem_ctx, &r);
3482                 if (!NT_STATUS_IS_OK(status)) {
3483                         printf("QueryDisplayInfo3 level %u failed - %s\n", 
3484                                levels[i], nt_errstr(status));
3485                         ret = False;
3486                 }
3487         }
3488         
3489         return ret;     
3490 }
3491
3492
3493 static BOOL test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3494                                            struct policy_handle *handle)
3495 {
3496         NTSTATUS status;
3497         struct samr_QueryDisplayInfo r;
3498         BOOL ret = True;
3499
3500         printf("Testing QueryDisplayInfo continuation\n");
3501
3502         r.in.domain_handle = handle;
3503         r.in.level = 1;
3504         r.in.start_idx = 0;
3505         r.in.max_entries = 1;
3506         r.in.buf_size = (uint32_t)-1;
3507
3508         do {
3509                 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
3510                 if (NT_STATUS_IS_OK(status) && r.out.returned_size != 0) {
3511                         if (r.out.info.info1.entries[0].idx != r.in.start_idx + 1) {
3512                                 printf("expected idx %d but got %d\n",
3513                                        r.in.start_idx + 1,
3514                                        r.out.info.info1.entries[0].idx);
3515                                 break;
3516                         }
3517                 }
3518                 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
3519                     !NT_STATUS_IS_OK(status)) {
3520                         printf("QueryDisplayInfo level %u failed - %s\n", 
3521                                r.in.level, nt_errstr(status));
3522                         ret = False;
3523                         break;
3524                 }
3525                 r.in.start_idx++;
3526         } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
3527                   NT_STATUS_IS_OK(status)) &&
3528                  r.out.returned_size != 0);
3529         
3530         return ret;     
3531 }
3532
3533 static BOOL test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3534                                  struct policy_handle *handle)
3535 {
3536         NTSTATUS status;
3537         struct samr_QueryDomainInfo r;
3538         struct samr_SetDomainInfo s;
3539         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
3540         uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1,  0,  1,  0};
3541         int i;
3542         BOOL ret = True;
3543         const char *domain_comment = talloc_asprintf(mem_ctx, 
3544                                   "Tortured by Samba4 RPC-SAMR: %s", 
3545                                   timestring(mem_ctx, time(NULL)));
3546
3547         s.in.domain_handle = handle;
3548         s.in.level = 4;
3549         s.in.info = talloc(mem_ctx, union samr_DomainInfo);
3550         
3551         s.in.info->info4.comment.string = domain_comment;
3552         status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
3553         if (!NT_STATUS_IS_OK(status)) {
3554                 printf("SetDomainInfo level %u (set comment) failed - %s\n", 
3555                        r.in.level, nt_errstr(status));
3556                 return False;
3557         }
3558
3559         for (i=0;i<ARRAY_SIZE(levels);i++) {
3560                 printf("Testing QueryDomainInfo level %u\n", levels[i]);
3561
3562                 r.in.domain_handle = handle;
3563                 r.in.level = levels[i];
3564
3565                 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
3566                 if (!NT_STATUS_IS_OK(status)) {
3567                         printf("QueryDomainInfo level %u failed - %s\n", 
3568                                r.in.level, nt_errstr(status));
3569                         ret = False;
3570                         continue;
3571                 }
3572
3573                 switch (levels[i]) {
3574                 case 2:
3575                         if (strcmp(r.out.info->info2.comment.string, domain_comment) != 0) {
3576                                 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
3577                                        levels[i], r.out.info->info2.comment.string, domain_comment);
3578                                 ret = False;
3579                         }
3580                         if (!r.out.info->info2.primary.string) {
3581                                 printf("QueryDomainInfo level %u returned no PDC name\n",
3582                                        levels[i]);
3583                                 ret = False;
3584                         } else if (r.out.info->info2.role == SAMR_ROLE_DOMAIN_PDC) {
3585                                 if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), r.out.info->info2.primary.string) != 0) {
3586                                         printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
3587                                                levels[i], r.out.info->info2.primary.string, dcerpc_server_name(p));
3588                                 }
3589                         }
3590                         break;
3591                 case 4:
3592                         if (strcmp(r.out.info->info4.comment.string, domain_comment) != 0) {
3593                                 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
3594                                        levels[i], r.out.info->info4.comment.string, domain_comment);
3595                                 ret = False;
3596                         }
3597                         break;
3598                 case 6:
3599                         if (!r.out.info->info6.primary.string) {
3600                                 printf("QueryDomainInfo level %u returned no PDC name\n",
3601                                        levels[i]);
3602                                 ret = False;
3603                         }
3604                         break;
3605                 case 11:
3606                         if (strcmp(r.out.info->info11.info2.comment.string, domain_comment) != 0) {
3607                                 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
3608                                        levels[i], r.out.info->info11.info2.comment.string, domain_comment);
3609                                 ret = False;
3610                         }
3611                         break;
3612                 }
3613
3614                 printf("Testing SetDomainInfo level %u\n", levels[i]);
3615
3616                 s.in.domain_handle = handle;
3617                 s.in.level = levels[i];
3618                 s.in.info = r.out.info;
3619
3620                 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
3621                 if (set_ok[i]) {
3622                         if (!NT_STATUS_IS_OK(status)) {
3623                                 printf("SetDomainInfo level %u failed - %s\n", 
3624                                        r.in.level, nt_errstr(status));
3625                                 ret = False;
3626                                 continue;
3627                         }
3628                 } else {
3629                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
3630                                 printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n", 
3631                                        r.in.level, nt_errstr(status));
3632                                 ret = False;
3633                                 continue;
3634                         }
3635                 }
3636
3637                 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
3638                 if (!NT_STATUS_IS_OK(status)) {
3639                         printf("QueryDomainInfo level %u failed - %s\n", 
3640                                r.in.level, nt_errstr(status));
3641                         ret = False;
3642                         continue;
3643                 }
3644         }
3645
3646         return ret;     
3647 }
3648
3649
3650 static BOOL test_QueryDomainInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3651                                   struct policy_handle *handle)
3652 {
3653         NTSTATUS status;
3654         struct samr_QueryDomainInfo2 r;
3655         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
3656         int i;
3657         BOOL ret = True;
3658
3659         for (i=0;i<ARRAY_SIZE(levels);i++) {
3660                 printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
3661
3662                 r.in.domain_handle = handle;
3663                 r.in.level = levels[i];
3664
3665                 status = dcerpc_samr_QueryDomainInfo2(p, mem_ctx, &r);
3666                 if (!NT_STATUS_IS_OK(status)) {
3667                         printf("QueryDomainInfo2 level %u failed - %s\n", 
3668                                r.in.level, nt_errstr(status));
3669                         ret = False;
3670                         continue;
3671                 }
3672         }
3673
3674         return True;    
3675 }
3676
3677 /* Test whether querydispinfo level 5 and enumdomgroups return the same
3678    set of group names. */
3679 static BOOL test_GroupList(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3680                            struct policy_handle *handle)
3681 {
3682         struct samr_EnumDomainGroups q1;
3683         struct samr_QueryDisplayInfo q2;
3684         NTSTATUS status;
3685         uint32_t resume_handle=0;
3686         int i;
3687         BOOL ret = True;
3688
3689         int num_names = 0;
3690         const char **names = NULL;
3691
3692         printf("Testing coherency of querydispinfo vs enumdomgroups\n");
3693
3694         q1.in.domain_handle = handle;
3695         q1.in.resume_handle = &resume_handle;
3696         q1.in.max_size = 5;
3697         q1.out.resume_handle = &resume_handle;
3698
3699         status = STATUS_MORE_ENTRIES;
3700         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
3701                 status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &q1);
3702
3703                 if (!NT_STATUS_IS_OK(status) &&
3704                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
3705                         break;
3706
3707                 for (i=0; i<q1.out.num_entries; i++) {
3708                         add_string_to_array(mem_ctx,
3709                                             q1.out.sam->entries[i].name.string,
3710                                             &names, &num_names);
3711                 }
3712         }
3713
3714         if (!NT_STATUS_IS_OK(status)) {
3715                 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
3716                 return False;
3717         }
3718         
3719         if (!q1.out.sam) {
3720                 return False;
3721         }
3722
3723         q2.in.domain_handle = handle;
3724         q2.in.level = 5;
3725         q2.in.start_idx = 0;
3726         q2.in.max_entries = 5;
3727         q2.in.buf_size = (uint32_t)-1;
3728
3729         status = STATUS_MORE_ENTRIES;
3730         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
3731                 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &q2);
3732
3733                 if (!NT_STATUS_IS_OK(status) &&
3734                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
3735                         break;
3736
3737                 for (i=0; i<q2.out.info.info5.count; i++) {
3738                         int j;
3739                         const char *name = q2.out.info.info5.entries[i].account_name.string;
3740                         BOOL found = False;
3741                         for (j=0; j<num_names; j++) {
3742                                 if (names[j] == NULL)
3743                                         continue;
3744                                 /* Hmm. No strequal in samba4 */
3745                                 if (strequal(names[j], name)) {
3746                                         names[j] = NULL;
3747                                         found = True;
3748                                         break;
3749                                 }
3750                         }
3751
3752                         if (!found) {
3753                                 printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
3754                                        name);
3755                                 ret = False;
3756                         }
3757                 }
3758                 q2.in.start_idx += q2.out.info.info5.count;
3759         }
3760
3761         if (!NT_STATUS_IS_OK(status)) {
3762                 printf("QueryDisplayInfo level 5 failed - %s\n",
3763                        nt_errstr(status));
3764                 ret = False;
3765         }
3766
3767         for (i=0; i<num_names; i++) {
3768                 if (names[i] != NULL) {
3769                         printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
3770                                names[i]);
3771                         ret = False;
3772                 }
3773         }
3774
3775         return ret;
3776 }
3777
3778 static BOOL test_DeleteDomainGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3779                                    struct policy_handle *group_handle)
3780 {
3781         struct samr_DeleteDomainGroup d;
3782         NTSTATUS status;
3783         BOOL ret = True;
3784
3785         printf("Testing DeleteDomainGroup\n");
3786
3787         d.in.group_handle = group_handle;
3788         d.out.group_handle = group_handle;
3789
3790         status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
3791         if (!NT_STATUS_IS_OK(status)) {
3792                 printf("DeleteDomainGroup failed - %s\n", nt_errstr(status));
3793                 ret = False;
3794         }
3795
3796         return ret;
3797 }
3798
3799 static BOOL test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3800                                             struct policy_handle *domain_handle)
3801 {
3802         struct samr_TestPrivateFunctionsDomain r;
3803         NTSTATUS status;
3804         BOOL ret = True;
3805
3806         printf("Testing TestPrivateFunctionsDomain\n");
3807
3808         r.in.domain_handle = domain_handle;
3809
3810         status = dcerpc_samr_TestPrivateFunctionsDomain(p, mem_ctx, &r);
3811         if (!NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
3812                 printf("TestPrivateFunctionsDomain failed - %s\n", nt_errstr(status));
3813                 ret = False;
3814         }
3815
3816         return ret;
3817 }
3818
3819 static BOOL test_RidToSid(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3820                           struct dom_sid *domain_sid,
3821                           struct policy_handle *domain_handle)
3822 {
3823         struct samr_RidToSid r;
3824         NTSTATUS status;
3825         BOOL ret = True;
3826         struct dom_sid *calc_sid;
3827         int rids[] = { 0, 42, 512, 10200 };
3828         int i;
3829
3830         for (i=0;i<ARRAY_SIZE(rids);i++) {
3831         
3832                 printf("Testing RidToSid\n");
3833                 
3834                 calc_sid = dom_sid_dup(mem_ctx, domain_sid);
3835                 r.in.domain_handle = domain_handle;
3836                 r.in.rid = rids[i];
3837                 
3838                 status = dcerpc_samr_RidToSid(p, mem_ctx, &r);
3839                 if (!NT_STATUS_IS_OK(status)) {
3840                         printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
3841                         ret = False;
3842                 } else {
3843                         calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
3844
3845                         if (!dom_sid_equal(calc_sid, r.out.sid)) {
3846                                 printf("RidToSid for %d failed - got %s, expected %s\n", rids[i], 
3847                                        dom_sid_string(mem_ctx, r.out.sid), 
3848                                        dom_sid_string(mem_ctx, calc_sid));
3849                                 ret = False;
3850                         }
3851                 }
3852         }
3853
3854         return ret;
3855 }
3856
3857 static BOOL test_GetBootKeyInformation(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
3858                                        struct policy_handle *domain_handle)
3859 {
3860         struct samr_GetBootKeyInformation r;
3861         NTSTATUS status;
3862         BOOL ret = True;
3863
3864         printf("Testing GetBootKeyInformation\n");
3865
3866         r.in.domain_handle = domain_handle;
3867
3868         status = dcerpc_samr_GetBootKeyInformation(p, mem_ctx, &r);
3869         if (!NT_STATUS_IS_OK(status)) {
3870                 /* w2k3 seems to fail this sometimes and pass it sometimes */
3871                 printf("GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
3872         }
3873
3874         return ret;
3875 }
3876
3877 static BOOL test_AddGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3878                                 struct policy_handle *domain_handle,
3879                                 struct policy_handle *group_handle)
3880 {
3881         NTSTATUS status;
3882         struct samr_AddGroupMember r;
3883         struct samr_DeleteGroupMember d;
3884         struct samr_QueryGroupMember q;
3885         struct samr_SetMemberAttributesOfGroup s;
3886         BOOL ret = True;
3887         uint32_t rid;
3888
3889         status = test_LookupName(p, mem_ctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
3890         if (!NT_STATUS_IS_OK(status)) {
3891                 printf("test_AddGroupMember looking up name " TEST_ACCOUNT_NAME " failed - %s\n", nt_errstr(status));
3892                 return False;
3893         }
3894
3895         r.in.group_handle = group_handle;
3896         r.in.rid = rid;
3897         r.in.flags = 0; /* ??? */
3898
3899         printf("Testing AddGroupMember and DeleteGroupMember\n");
3900
3901         d.in.group_handle = group_handle;
3902         d.in.rid = rid;
3903
3904         status = dcerpc_samr_DeleteGroupMember(p, mem_ctx, &d);
3905         if (!NT_STATUS_EQUAL(NT_STATUS_MEMBER_NOT_IN_GROUP, status)) {
3906                 printf("DeleteGroupMember gave %s - should be NT_STATUS_MEMBER_NOT_IN_GROUP\n", 
3907                        nt_errstr(status));
3908                 return False;
3909         }
3910
3911         status = dcerpc_samr_AddGroupMember(p, mem_ctx, &r);
3912         if (!NT_STATUS_IS_OK(status)) {
3913                 printf("AddGroupMember failed - %s\n", nt_errstr(status));
3914                 return False;
3915         }
3916
3917         status = dcerpc_samr_AddGroupMember(p, mem_ctx, &r);
3918         if (!NT_STATUS_EQUAL(NT_STATUS_MEMBER_IN_GROUP, status)) {
3919                 printf("AddGroupMember gave %s - should be NT_STATUS_MEMBER_IN_GROUP\n", 
3920                        nt_errstr(status));
3921                 return False;
3922         }
3923
3924         if (lp_parm_bool(-1, "torture", "samba4", False)) {
3925                 printf("skipping SetMemberAttributesOfGroup test against Samba4\n");
3926         } else {
3927                 /* this one is quite strange. I am using random inputs in the
3928                    hope of triggering an error that might give us a clue */
3929
3930                 s.in.group_handle = group_handle;
3931                 s.in.unknown1 = random();
3932                 s.in.unknown2 = random();
3933
3934                 status = dcerpc_samr_SetMemberAttributesOfGroup(p, mem_ctx, &s);
3935                 if (!NT_STATUS_IS_OK(status)) {
3936                         printf("SetMemberAttributesOfGroup failed - %s\n", nt_errstr(status));
3937                         return False;
3938                 }
3939         }
3940
3941         q.in.group_handle = group_handle;
3942
3943         status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &q);
3944         if (!NT_STATUS_IS_OK(status)) {
3945                 printf("QueryGroupMember failed - %s\n", nt_errstr(status));
3946                 return False;
3947         }
3948
3949         status = dcerpc_samr_DeleteGroupMember(p, mem_ctx, &d);
3950         if (!NT_STATUS_IS_OK(status)) {
3951                 printf("DeleteGroupMember failed - %s\n", nt_errstr(status));
3952                 return False;
3953         }
3954
3955         status = dcerpc_samr_AddGroupMember(p, mem_ctx, &r);
3956         if (!NT_STATUS_IS_OK(status)) {
3957                 printf("AddGroupMember failed - %s\n", nt_errstr(status));
3958                 return False;
3959         }
3960
3961         return ret;
3962 }
3963
3964
3965 static BOOL test_CreateDomainGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3966                                    struct policy_handle *domain_handle, struct policy_handle *group_handle)
3967 {
3968         NTSTATUS status;
3969         struct samr_CreateDomainGroup r;
3970         uint32_t rid;
3971         struct lsa_String name;
3972         BOOL ret = True;
3973
3974         init_lsa_String(&name, TEST_GROUPNAME);
3975
3976         r.in.domain_handle = domain_handle;
3977         r.in.name = &name;
3978         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3979         r.out.group_handle = group_handle;
3980         r.out.rid = &rid;
3981
3982         printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
3983
3984         status = dcerpc_samr_CreateDomainGroup(p, mem_ctx, &r);
3985
3986         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3987                 printf("Server refused create of '%s'\n", r.in.name->string);
3988                 ZERO_STRUCTP(group_handle);
3989                 return True;
3990         }
3991
3992         if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS)) {
3993                 if (!test_DeleteGroup_byname(p, mem_ctx, domain_handle, r.in.name->string)) {
3994                         
3995                         printf("CreateDomainGroup failed: Could not delete domain group %s - %s\n", r.in.name->string, 
3996                                nt_errstr(status));
3997                         return False;
3998                 }
3999                 status = dcerpc_samr_CreateDomainGroup(p, mem_ctx, &r);
4000         }
4001         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
4002                 if (!test_DeleteUser_byname(p, mem_ctx, domain_handle, r.in.name->string)) {
4003                         
4004                         printf("CreateDomainGroup failed: Could not delete user %s - %s\n", r.in.name->string, 
4005                                nt_errstr(status));
4006                         return False;
4007                 }
4008                 status = dcerpc_samr_CreateDomainGroup(p, mem_ctx, &r);
4009         }
4010         if (!NT_STATUS_IS_OK(status)) {
4011                 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
4012                 return False;
4013         }
4014
4015         if (!test_AddGroupMember(p, mem_ctx, domain_handle, group_handle)) {
4016                 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
4017                 ret = False;
4018         }
4019
4020         if (!test_SetGroupInfo(p, mem_ctx, group_handle)) {
4021                 ret = False;
4022         }
4023
4024         return ret;
4025 }
4026
4027
4028 /*
4029   its not totally clear what this does. It seems to accept any sid you like.
4030 */
4031 static BOOL test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p, 
4032                                                TALLOC_CTX *mem_ctx, 
4033                                                struct policy_handle *domain_handle)
4034 {
4035         NTSTATUS status;
4036         struct samr_RemoveMemberFromForeignDomain r;
4037
4038         r.in.domain_handle = domain_handle;
4039         r.in.sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-12-34-56-78");
4040
4041         status = dcerpc_samr_RemoveMemberFromForeignDomain(p, mem_ctx, &r);
4042         if (!NT_STATUS_IS_OK(status)) {
4043                 printf("RemoveMemberFromForeignDomain failed - %s\n", nt_errstr(status));
4044                 return False;
4045         }
4046
4047         return True;
4048 }
4049
4050
4051
4052 static BOOL test_Connect(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
4053                          struct policy_handle *handle);
4054
4055 static BOOL test_OpenDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
4056                             struct policy_handle *handle, struct dom_sid *sid,
4057                             enum torture_samr_choice which_ops)
4058 {
4059         NTSTATUS status;
4060         struct samr_OpenDomain r;
4061         struct policy_handle domain_handle;
4062         struct policy_handle alias_handle;
4063         struct policy_handle user_handle;
4064         struct policy_handle group_handle;
4065         BOOL ret = True;
4066
4067         ZERO_STRUCT(alias_handle);
4068         ZERO_STRUCT(user_handle);
4069         ZERO_STRUCT(group_handle);
4070         ZERO_STRUCT(domain_handle);
4071
4072         printf("Testing OpenDomain\n");
4073
4074         r.in.connect_handle = handle;
4075         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4076         r.in.sid = sid;
4077         r.out.domain_handle = &domain_handle;
4078
4079         status = dcerpc_samr_OpenDomain(p, mem_ctx, &r);
4080         if (!NT_STATUS_IS_OK(status)) {
4081                 printf("OpenDomain failed - %s\n", nt_errstr(status));
4082                 return False;
4083         }
4084
4085         /* run the domain tests with the main handle closed - this tests
4086            the servers reference counting */
4087         ret &= test_samr_handle_Close(p, mem_ctx, handle);
4088
4089         switch (which_ops) {
4090         case TORTURE_SAMR_USER_ATTRIBUTES:
4091         case TORTURE_SAMR_PASSWORDS:
4092                 ret &= test_CreateUser2(p, mem_ctx, &domain_handle, which_ops);
4093                 ret &= test_CreateUser(p, mem_ctx, &domain_handle, &user_handle, which_ops);
4094                 /* This test needs 'complex' users to validate */
4095                 ret &= test_QueryDisplayInfo(p, mem_ctx, &domain_handle);
4096                 break;
4097         case TORTURE_SAMR_OTHER:
4098                 ret &= test_CreateUser(p, mem_ctx, &domain_handle, &user_handle, which_ops);
4099                 ret &= test_QuerySecurity(p, mem_ctx, &domain_handle);
4100                 ret &= test_RemoveMemberFromForeignDomain(p, mem_ctx, &domain_handle);
4101                 ret &= test_CreateAlias(p, mem_ctx, &domain_handle, &alias_handle, sid);
4102                 ret &= test_CreateDomainGroup(p, mem_ctx, &domain_handle, &group_handle);
4103                 ret &= test_QueryDomainInfo(p, mem_ctx, &domain_handle);
4104                 ret &= test_QueryDomainInfo2(p, mem_ctx, &domain_handle);
4105                 ret &= test_EnumDomainUsers(p, mem_ctx, &domain_handle);
4106                 ret &= test_EnumDomainUsers_async(p, mem_ctx, &domain_handle);
4107                 ret &= test_EnumDomainGroups(p, mem_ctx, &domain_handle);
4108                 ret &= test_EnumDomainAliases(p, mem_ctx, &domain_handle);
4109                 ret &= test_QueryDisplayInfo2(p, mem_ctx, &domain_handle);
4110                 ret &= test_QueryDisplayInfo3(p, mem_ctx, &domain_handle);
4111                 ret &= test_QueryDisplayInfo_continue(p, mem_ctx, &domain_handle);
4112                 
4113                 if (lp_parm_bool(-1, "torture", "samba4", False)) {
4114                         printf("skipping GetDisplayEnumerationIndex test against Samba4\n");
4115                 } else {
4116                         ret &= test_GetDisplayEnumerationIndex(p, mem_ctx, &domain_handle);
4117                         ret &= test_GetDisplayEnumerationIndex2(p, mem_ctx, &domain_handle);
4118                 }
4119                 ret &= test_GroupList(p, mem_ctx, &domain_handle);
4120                 ret &= test_TestPrivateFunctionsDomain(p, mem_ctx, &domain_handle);
4121                 ret &= test_RidToSid(p, mem_ctx, sid, &domain_handle);
4122                 ret &= test_GetBootKeyInformation(p, mem_ctx, &domain_handle);
4123                 break;
4124         }
4125
4126         if (!policy_handle_empty(&user_handle) &&
4127             !test_DeleteUser(p, mem_ctx, &user_handle)) {
4128                 ret = False;
4129         }
4130
4131         if (!policy_handle_empty(&alias_handle) &&
4132             !test_DeleteAlias(p, mem_ctx, &alias_handle)) {
4133                 ret = False;
4134         }
4135
4136         if (!policy_handle_empty(&group_handle) &&
4137             !test_DeleteDomainGroup(p, mem_ctx, &group_handle)) {
4138                 ret = False;
4139         }
4140
4141         ret &= test_samr_handle_Close(p, mem_ctx, &domain_handle);
4142
4143         /* reconnect the main handle */
4144         ret &= test_Connect(p, mem_ctx, handle);
4145
4146         if (!ret) {
4147                 printf("Testing domain %s failed!\n", dom_sid_string(mem_ctx, sid));
4148         }
4149
4150         return ret;
4151 }
4152
4153 static BOOL test_LookupDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
4154                               struct policy_handle *handle, const char *domain,
4155                               enum torture_samr_choice which_ops)
4156 {
4157         NTSTATUS status;
4158         struct samr_LookupDomain r;
4159         struct lsa_String n1;
4160         struct lsa_String n2;
4161         BOOL ret = True;
4162
4163         printf("Testing LookupDomain(%s)\n", domain);
4164
4165         /* check for correct error codes */
4166         r.in.connect_handle = handle;
4167         r.in.domain_name = &n2;
4168         n2.string = NULL;
4169
4170         status = dcerpc_samr_LookupDomain(p, mem_ctx, &r);
4171         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_PARAMETER, status)) {
4172                 printf("failed: LookupDomain expected NT_STATUS_INVALID_PARAMETER - %s\n", nt_errstr(status));
4173                 ret = False;
4174         }
4175
4176         init_lsa_String(&n2, "xxNODOMAINxx");
4177
4178         status = dcerpc_samr_LookupDomain(p, mem_ctx, &r);
4179         if (!NT_STATUS_EQUAL(NT_STATUS_NO_SUCH_DOMAIN, status)) {
4180                 printf("failed: LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN - %s\n", nt_errstr(status));
4181                 ret = False;
4182         }
4183
4184         r.in.connect_handle = handle;
4185
4186         init_lsa_String(&n1, domain);
4187         r.in.domain_name = &n1;
4188
4189         status = dcerpc_samr_LookupDomain(p, mem_ctx, &r);
4190         if (!NT_STATUS_IS_OK(status)) {
4191                 printf("LookupDomain failed - %s\n", nt_errstr(status));
4192                 ret = False;
4193         }
4194
4195         if (!test_GetDomPwInfo(p, mem_ctx, &n1)) {
4196                 ret = False;
4197         }
4198
4199         if (!test_OpenDomain(p, mem_ctx, handle, r.out.sid, which_ops)) {
4200                 ret = False;
4201         }
4202
4203         return ret;
4204 }
4205
4206
4207 static BOOL test_EnumDomains(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
4208                              struct policy_handle *handle, enum torture_samr_choice which_ops)
4209 {
4210         NTSTATUS status;
4211         struct samr_EnumDomains r;
4212         uint32_t resume_handle = 0;
4213         int i;
4214         BOOL ret = True;
4215
4216         r.in.connect_handle = handle;
4217         r.in.resume_handle = &resume_handle;
4218         r.in.buf_size = (uint32_t)-1;
4219         r.out.resume_handle = &resume_handle;
4220
4221         status = dcerpc_samr_EnumDomains(p, mem_ctx, &r);
4222         if (!NT_STATUS_IS_OK(status)) {
4223                 printf("EnumDomains failed - %s\n", nt_errstr(status));
4224                 return False;
4225         }
4226
4227         if (!r.out.sam) {
4228                 return False;
4229         }
4230
4231         for (i=0;i<r.out.sam->count;i++) {
4232                 if (!test_LookupDomain(p, mem_ctx, handle, 
4233                                        r.out.sam->entries[i].name.string, which_ops)) {
4234                         ret = False;
4235                 }
4236         }
4237
4238         status = dcerpc_samr_EnumDomains(p, mem_ctx, &r);
4239         if (!NT_STATUS_IS_OK(status)) {
4240                 printf("EnumDomains failed - %s\n", nt_errstr(status));
4241                 return False;
4242         }
4243
4244         return ret;
4245 }
4246
4247
4248 static BOOL test_Connect(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
4249                          struct policy_handle *handle)
4250 {
4251         NTSTATUS status;
4252         struct samr_Connect r;
4253         struct samr_Connect2 r2;
4254         struct samr_Connect3 r3;
4255         struct samr_Connect4 r4;
4256         struct samr_Connect5 r5;
4257         union samr_ConnectInfo info;
4258         struct policy_handle h;
4259         BOOL ret = True, got_handle = False;
4260
4261         printf("testing samr_Connect\n");
4262
4263         r.in.system_name = 0;
4264         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4265         r.out.connect_handle = &h;
4266
4267         status = dcerpc_samr_Connect(p, mem_ctx, &r);
4268         if (!NT_STATUS_IS_OK(status)) {
4269                 printf("Connect failed - %s\n", nt_errstr(status));
4270                 ret = False;
4271         } else {
4272                 got_handle = True;
4273                 *handle = h;
4274         }
4275
4276         printf("testing samr_Connect2\n");
4277
4278         r2.in.system_name = NULL;
4279         r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4280         r2.out.connect_handle = &h;
4281
4282         status = dcerpc_samr_Connect2(p, mem_ctx, &r2);
4283         if (!NT_STATUS_IS_OK(status)) {
4284                 printf("Connect2 failed - %s\n", nt_errstr(status));
4285                 ret = False;
4286         } else {
4287                 if (got_handle) {
4288                         test_samr_handle_Close(p, mem_ctx, handle);
4289                 }
4290                 got_handle = True;
4291                 *handle = h;
4292         }
4293
4294         printf("testing samr_Connect3\n");
4295
4296         r3.in.system_name = NULL;
4297         r3.in.unknown = 0;
4298         r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4299         r3.out.connect_handle = &h;
4300
4301         status = dcerpc_samr_Connect3(p, mem_ctx, &r3);
4302         if (!NT_STATUS_IS_OK(status)) {
4303                 printf("Connect3 failed - %s\n", nt_errstr(status));
4304                 ret = False;
4305         } else {
4306                 if (got_handle) {
4307                         test_samr_handle_Close(p, mem_ctx, handle);
4308                 }
4309                 got_handle = True;
4310                 *handle = h;
4311         }
4312
4313         printf("testing samr_Connect4\n");
4314
4315         r4.in.system_name = "";
4316         r4.in.unknown = 0;
4317         r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4318         r4.out.connect_handle = &h;
4319
4320         status = dcerpc_samr_Connect4(p, mem_ctx, &r4);
4321         if (!NT_STATUS_IS_OK(status)) {
4322                 printf("Connect4 failed - %s\n", nt_errstr(status));
4323                 ret = False;
4324         } else {
4325                 if (got_handle) {
4326                         test_samr_handle_Close(p, mem_ctx, handle);
4327                 }
4328                 got_handle = True;
4329                 *handle = h;
4330         }
4331
4332         printf("testing samr_Connect5\n");
4333
4334         info.info1.unknown1 = 0;
4335         info.info1.unknown2 = 0;
4336
4337         r5.in.system_name = "";
4338         r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
4339         r5.in.level = 1;
4340         r5.in.info = &info;
4341         r5.out.info = &info;
4342         r5.out.connect_handle = &h;
4343
4344         status = dcerpc_samr_Connect5(p, mem_ctx, &r5);
4345         if (!NT_STATUS_IS_OK(status)) {
4346                 printf("Connect5 failed - %s\n", nt_errstr(status));
4347                 ret = False;
4348         } else {
4349                 if (got_handle) {
4350                         test_samr_handle_Close(p, mem_ctx, handle);
4351                 }
4352                 got_handle = True;
4353                 *handle = h;
4354         }
4355
4356         return ret;
4357 }
4358
4359
4360 BOOL torture_rpc_samr(struct torture_context *torture)
4361 {
4362         NTSTATUS status;
4363         struct dcerpc_pipe *p;
4364         BOOL ret = True;
4365         struct policy_handle handle;
4366
4367         status = torture_rpc_connection(torture, &p, &dcerpc_table_samr);
4368         if (!NT_STATUS_IS_OK(status)) {
4369                 return False;
4370         }
4371
4372         ret &= test_Connect(p, torture, &handle);
4373
4374         ret &= test_QuerySecurity(p, torture, &handle);
4375
4376         ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_OTHER);
4377
4378         ret &= test_SetDsrmPassword(p, torture, &handle);
4379
4380         ret &= test_Shutdown(p, torture, &handle);
4381
4382         ret &= test_samr_handle_Close(p, torture, &handle);
4383
4384         return ret;
4385 }
4386
4387
4388 BOOL torture_rpc_samr_users(struct torture_context *torture)
4389 {
4390         NTSTATUS status;
4391         struct dcerpc_pipe *p;
4392         BOOL ret = True;
4393         struct policy_handle handle;
4394
4395         status = torture_rpc_connection(torture, &p, &dcerpc_table_samr);
4396         if (!NT_STATUS_IS_OK(status)) {
4397                 return False;
4398         }
4399
4400         ret &= test_Connect(p, torture, &handle);
4401
4402         ret &= test_QuerySecurity(p, torture, &handle);
4403
4404         ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_USER_ATTRIBUTES);
4405
4406         ret &= test_SetDsrmPassword(p, torture, &handle);
4407
4408         ret &= test_Shutdown(p, torture, &handle);
4409
4410         ret &= test_samr_handle_Close(p, torture, &handle);
4411
4412         return ret;
4413 }
4414
4415
4416 BOOL torture_rpc_samr_passwords(struct torture_context *torture)
4417 {
4418         NTSTATUS status;
4419         struct dcerpc_pipe *p;
4420         BOOL ret = True;
4421         struct policy_handle handle;
4422
4423         status = torture_rpc_connection(torture, &p, &dcerpc_table_samr);
4424         if (!NT_STATUS_IS_OK(status)) {
4425                 return False;
4426         }
4427
4428         ret &= test_Connect(p, torture, &handle);
4429
4430         ret &= test_EnumDomains(p, torture, &handle, TORTURE_SAMR_PASSWORDS);
4431
4432         ret &= test_samr_handle_Close(p, torture, &handle);
4433
4434         return ret;
4435 }
4436