r16794: Make Samba4 pass it's own RPC-SAMR test, at least in part. There are
[samba.git] / source4 / torture / rpc / samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for samr rpc operations
4
5    Copyright (C) Andrew Tridgell 2003
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "torture/torture.h"
25 #include "system/time.h"
26 #include "librpc/gen_ndr/lsa.h"
27 #include "librpc/gen_ndr/ndr_samr_c.h"
28 #include "smb.h"
29 #include "lib/crypto/crypto.h"
30 #include "libcli/auth/libcli_auth.h"
31 #include "libcli/security/security.h"
32 #include "torture/rpc/rpc.h"
33
34 #define TEST_ACCOUNT_NAME "samrtorturetest"
35 #define TEST_ALIASNAME "samrtorturetestalias"
36 #define TEST_GROUPNAME "samrtorturetestgroup"
37 #define TEST_MACHINENAME "samrtestmach$"
38 #define TEST_DOMAINNAME "samrtestdom$"
39
40
41 static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
42                                struct policy_handle *handle);
43
44 static BOOL test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
45                                 struct policy_handle *handle);
46
47 static BOOL test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
48                                struct policy_handle *handle);
49
50 static void init_lsa_String(struct lsa_String *string, const char *s)
51 {
52         string->string = s;
53 }
54
55 BOOL test_samr_handle_Close(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
56                                    struct policy_handle *handle)
57 {
58         NTSTATUS status;
59         struct samr_Close r;
60
61         r.in.handle = handle;
62         r.out.handle = handle;
63
64         status = dcerpc_samr_Close(p, mem_ctx, &r);
65         if (!NT_STATUS_IS_OK(status)) {
66                 printf("Close handle failed - %s\n", nt_errstr(status));
67                 return False;
68         }
69
70         return True;
71 }
72
73 static BOOL test_Shutdown(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
74                        struct policy_handle *handle)
75 {
76         NTSTATUS status;
77         struct samr_Shutdown r;
78
79         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
80                 printf("samr_Shutdown disabled - enable dangerous tests to use\n");
81                 return True;
82         }
83
84         r.in.connect_handle = handle;
85
86         printf("testing samr_Shutdown\n");
87
88         status = dcerpc_samr_Shutdown(p, mem_ctx, &r);
89         if (!NT_STATUS_IS_OK(status)) {
90                 printf("samr_Shutdown failed - %s\n", nt_errstr(status));
91                 return False;
92         }
93
94         return True;
95 }
96
97 static BOOL test_SetDsrmPassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
98                                  struct policy_handle *handle)
99 {
100         NTSTATUS status;
101         struct samr_SetDsrmPassword r;
102         struct lsa_String string;
103         struct samr_Password hash;
104
105         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
106                 printf("samr_SetDsrmPassword disabled - enable dangerous tests to use\n");
107                 return True;
108         }
109
110         E_md4hash("TeSTDSRM123", hash.hash);
111
112         init_lsa_String(&string, "Administrator");
113
114         r.in.name = &string;
115         r.in.unknown = 0;
116         r.in.hash = &hash;
117
118         printf("testing samr_SetDsrmPassword\n");
119
120         status = dcerpc_samr_SetDsrmPassword(p, mem_ctx, &r);
121         if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
122                 printf("samr_SetDsrmPassword failed - %s\n", nt_errstr(status));
123                 return False;
124         }
125
126         return True;
127 }
128
129
130 static BOOL test_QuerySecurity(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
131                                struct policy_handle *handle)
132 {
133         NTSTATUS status;
134         struct samr_QuerySecurity r;
135         struct samr_SetSecurity s;
136
137         r.in.handle = handle;
138         r.in.sec_info = 7;
139
140         status = dcerpc_samr_QuerySecurity(p, mem_ctx, &r);
141         if (!NT_STATUS_IS_OK(status)) {
142                 printf("QuerySecurity failed - %s\n", nt_errstr(status));
143                 return False;
144         }
145
146         if (r.out.sdbuf == NULL) {
147                 return False;
148         }
149
150         s.in.handle = handle;
151         s.in.sec_info = 7;
152         s.in.sdbuf = r.out.sdbuf;
153
154         if (lp_parm_bool(-1, "target", "samba4", False)) {
155                 printf("skipping SetSecurity test against Samba4\n");
156                 return True;
157         }
158
159         status = dcerpc_samr_SetSecurity(p, mem_ctx, &s);
160         if (!NT_STATUS_IS_OK(status)) {
161                 printf("SetSecurity failed - %s\n", nt_errstr(status));
162                 return False;
163         }
164
165         status = dcerpc_samr_QuerySecurity(p, mem_ctx, &r);
166         if (!NT_STATUS_IS_OK(status)) {
167                 printf("QuerySecurity failed - %s\n", nt_errstr(status));
168                 return False;
169         }
170
171         return True;
172 }
173
174
175 static BOOL test_SetUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
176                              struct policy_handle *handle, uint32_t base_acct_flags,
177                              const char *base_account_name)
178 {
179         NTSTATUS status;
180         struct samr_SetUserInfo s;
181         struct samr_SetUserInfo2 s2;
182         struct samr_QueryUserInfo q;
183         struct samr_QueryUserInfo q0;
184         union samr_UserInfo u;
185         BOOL ret = True;
186         const char *test_account_name;
187
188         uint32_t user_extra_flags = 0;
189         if (base_acct_flags == ACB_NORMAL) {
190                 /* When created, accounts are expired by default */
191                 user_extra_flags = ACB_PW_EXPIRED;
192         }
193
194         s.in.user_handle = handle;
195         s.in.info = &u;
196
197         s2.in.user_handle = handle;
198         s2.in.info = &u;
199
200         q.in.user_handle = handle;
201         q.out.info = &u;
202         q0 = q;
203
204 #define TESTCALL(call, r) \
205                 status = dcerpc_samr_ ##call(p, mem_ctx, &r); \
206                 if (!NT_STATUS_IS_OK(status)) { \
207                         printf(#call " level %u failed - %s (%s)\n", \
208                                r.in.level, nt_errstr(status), __location__); \
209                         ret = False; \
210                         break; \
211                 }
212
213 #define STRING_EQUAL(s1, s2, field) \
214                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
215                         printf("Failed to set %s to '%s' (%s)\n", \
216                                #field, s2, __location__); \
217                         ret = False; \
218                         break; \
219                 }
220
221 #define INT_EQUAL(i1, i2, field) \
222                 if (i1 != i2) { \
223                         printf("Failed to set %s to 0x%x - got 0x%x (%s)\n", \
224                                #field, i2, i1, __location__); \
225                         ret = False; \
226                         break; \
227                 }
228
229 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
230                 printf("field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
231                 q.in.level = lvl1; \
232                 TESTCALL(QueryUserInfo, q) \
233                 s.in.level = lvl1; \
234                 s2.in.level = lvl1; \
235                 u = *q.out.info; \
236                 if (lvl1 == 21) { \
237                         ZERO_STRUCT(u.info21); \
238                         u.info21.fields_present = fpval; \
239                 } \
240                 init_lsa_String(&u.info ## lvl1.field1, value); \
241                 TESTCALL(SetUserInfo, s) \
242                 TESTCALL(SetUserInfo2, s2) \
243                 init_lsa_String(&u.info ## lvl1.field1, ""); \
244                 TESTCALL(QueryUserInfo, q); \
245                 u = *q.out.info; \
246                 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
247                 q.in.level = lvl2; \
248                 TESTCALL(QueryUserInfo, q) \
249                 u = *q.out.info; \
250                 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
251         } while (0)
252
253 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
254                 printf("field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
255                 q.in.level = lvl1; \
256                 TESTCALL(QueryUserInfo, q) \
257                 s.in.level = lvl1; \
258                 s2.in.level = lvl1; \
259                 u = *q.out.info; \
260                 if (lvl1 == 21) { \
261                         uint8_t *bits = u.info21.logon_hours.bits; \
262                         ZERO_STRUCT(u.info21); \
263                         if (fpval == SAMR_FIELD_LOGON_HOURS) { \
264                                 u.info21.logon_hours.units_per_week = 168; \
265                                 u.info21.logon_hours.bits = bits; \
266                         } \
267                         u.info21.fields_present = fpval; \
268                 } \
269                 u.info ## lvl1.field1 = value; \
270                 TESTCALL(SetUserInfo, s) \
271                 TESTCALL(SetUserInfo2, s2) \
272                 u.info ## lvl1.field1 = 0; \
273                 TESTCALL(QueryUserInfo, q); \
274                 u = *q.out.info; \
275                 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
276                 q.in.level = lvl2; \
277                 TESTCALL(QueryUserInfo, q) \
278                 u = *q.out.info; \
279                 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
280         } while (0)
281
282 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
283         TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
284         } while (0)
285
286         q0.in.level = 12;
287         do { TESTCALL(QueryUserInfo, q0) } while (0);
288
289         TEST_USERINFO_STRING(2, comment,  1, comment, "xx2-1 comment", 0);
290         TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
291         TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment", 
292                            SAMR_FIELD_COMMENT);
293
294         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-1", base_account_name);
295         TEST_USERINFO_STRING(7, account_name,  1, account_name, base_account_name, 0);
296         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-3", base_account_name);
297         TEST_USERINFO_STRING(7, account_name,  3, account_name, base_account_name, 0);
298         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-5", base_account_name);
299         TEST_USERINFO_STRING(7, account_name,  5, account_name, base_account_name, 0);
300         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-6", base_account_name);
301         TEST_USERINFO_STRING(7, account_name,  6, account_name, base_account_name, 0);
302         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-7", base_account_name);
303         TEST_USERINFO_STRING(7, account_name,  7, account_name, base_account_name, 0);
304         test_account_name = talloc_asprintf(mem_ctx, "%sxx7-21", base_account_name);
305         TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
306         test_account_name = base_account_name;
307         TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name, 
308                            SAMR_FIELD_ACCOUNT_NAME);
309
310         TEST_USERINFO_STRING(6, full_name,  1, full_name, "xx6-1 full_name", 0);
311         TEST_USERINFO_STRING(6, full_name,  3, full_name, "xx6-3 full_name", 0);
312         TEST_USERINFO_STRING(6, full_name,  5, full_name, "xx6-5 full_name", 0);
313         TEST_USERINFO_STRING(6, full_name,  6, full_name, "xx6-6 full_name", 0);
314         TEST_USERINFO_STRING(6, full_name,  8, full_name, "xx6-8 full_name", 0);
315         TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
316         TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
317         TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name", 
318                            SAMR_FIELD_FULL_NAME);
319
320         TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
321         TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
322         TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
323         TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script", 
324                            SAMR_FIELD_LOGON_SCRIPT);
325
326         TEST_USERINFO_STRING(12, profile_path,  3, profile_path, "xx12-3 profile_path", 0);
327         TEST_USERINFO_STRING(12, profile_path,  5, profile_path, "xx12-5 profile_path", 0);
328         TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
329         TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path", 
330                            SAMR_FIELD_PROFILE_PATH);
331
332         TEST_USERINFO_STRING(13, description,  1, description, "xx13-1 description", 0);
333         TEST_USERINFO_STRING(13, description,  5, description, "xx13-5 description", 0);
334         TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
335         TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description", 
336                            SAMR_FIELD_DESCRIPTION);
337
338         TEST_USERINFO_STRING(14, workstations,  3, workstations, "14workstation3", 0);
339         TEST_USERINFO_STRING(14, workstations,  5, workstations, "14workstation4", 0);
340         TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
341         TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21", 
342                            SAMR_FIELD_WORKSTATIONS);
343
344         TEST_USERINFO_STRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
345         TEST_USERINFO_STRING(21, parameters, 21, parameters, "xx21-21 parameters", 
346                            SAMR_FIELD_PARAMETERS);
347
348         TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
349         TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__, 
350                           SAMR_FIELD_COUNTRY_CODE);
351
352         TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
353         TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__, 
354                           SAMR_FIELD_CODE_PAGE);
355
356         TEST_USERINFO_INT(4, logon_hours.bits[3],  3, logon_hours.bits[3], 1, 0);
357         TEST_USERINFO_INT(4, logon_hours.bits[3],  5, logon_hours.bits[3], 2, 0);
358         TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
359         TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4, 
360                           SAMR_FIELD_LOGON_HOURS);
361
362         if (lp_parm_bool(-1, "target", "samba4", False)) {
363                 printf("skipping Set Account Flag tests against Samba4\n");
364                 return ret;
365         }
366
367         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
368                               (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ), 
369                               (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
370                               0);
371         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
372                               (base_acct_flags  | ACB_DISABLED), 
373                               (base_acct_flags  | ACB_DISABLED | user_extra_flags), 
374                               0);
375         
376         /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
377         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
378                               (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP), 
379                               (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP), 
380                               0);
381         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
382                               (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ), 
383                               (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
384                               0);
385
386
387         /* The 'autolock' flag doesn't stick - check this */
388         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
389                               (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK), 
390                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
391                               0);
392 #if 0
393         /* Removing the 'disabled' flag doesn't stick - check this */
394         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
395                               (base_acct_flags), 
396                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
397                               0);
398 #endif
399         /* The 'store plaintext' flag does stick */
400         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
401                               (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED), 
402                               (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags), 
403                               0);
404         /* The 'use DES' flag does stick */
405         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
406                               (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY), 
407                               (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags), 
408                               0);
409         /* The 'don't require kerberos pre-authentication flag does stick */
410         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
411                               (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH), 
412                               (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags), 
413                               0);
414         /* The 'no kerberos PAC required' flag sticks */
415         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
416                               (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD), 
417                               (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags), 
418                               0);
419
420         TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags, 
421                               (base_acct_flags | ACB_DISABLED), 
422                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
423                               SAMR_FIELD_ACCT_FLAGS);
424
425 #if 0
426         /* these fail with win2003 - it appears you can't set the primary gid?
427            the set succeeds, but the gid isn't changed. Very weird! */
428         TEST_USERINFO_INT(9, primary_gid,  1, primary_gid, 513);
429         TEST_USERINFO_INT(9, primary_gid,  3, primary_gid, 513);
430         TEST_USERINFO_INT(9, primary_gid,  5, primary_gid, 513);
431         TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
432 #endif
433
434         return ret;
435 }
436
437 /*
438   generate a random password for password change tests
439 */
440 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
441 {
442         size_t len = MAX(8, min_len) + (random() % 6);
443         char *s = generate_random_str(mem_ctx, len);
444         printf("Generated password '%s'\n", s);
445         return s;
446 }
447
448 static BOOL test_SetUserPass(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
449                              struct policy_handle *handle, char **password)
450 {
451         NTSTATUS status;
452         struct samr_SetUserInfo s;
453         union samr_UserInfo u;
454         BOOL ret = True;
455         DATA_BLOB session_key;
456         char *newpass;
457         struct samr_GetUserPwInfo pwp;
458         int policy_min_pw_len = 0;
459         pwp.in.user_handle = handle;
460
461         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
462         if (NT_STATUS_IS_OK(status)) {
463                 policy_min_pw_len = pwp.out.info.min_password_length;
464         }
465         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
466
467         s.in.user_handle = handle;
468         s.in.info = &u;
469         s.in.level = 24;
470
471         encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
472         /* w2k3 ignores this length */
473         u.info24.pw_len = strlen_m(newpass) * 2;
474
475         status = dcerpc_fetch_session_key(p, &session_key);
476         if (!NT_STATUS_IS_OK(status)) {
477                 printf("SetUserInfo level %u - no session key - %s\n",
478                        s.in.level, nt_errstr(status));
479                 return False;
480         }
481
482         arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
483
484         printf("Testing SetUserInfo level 24 (set password)\n");
485
486         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
487         if (!NT_STATUS_IS_OK(status)) {
488                 printf("SetUserInfo level %u failed - %s\n",
489                        s.in.level, nt_errstr(status));
490                 ret = False;
491         } else {
492                 *password = newpass;
493         }
494
495         return ret;
496 }
497
498
499 static BOOL test_SetUserPass_23(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
500                                 struct policy_handle *handle, uint32_t fields_present,
501                                 char **password)
502 {
503         NTSTATUS status;
504         struct samr_SetUserInfo s;
505         union samr_UserInfo u;
506         BOOL ret = True;
507         DATA_BLOB session_key;
508         char *newpass;
509         struct samr_GetUserPwInfo pwp;
510         int policy_min_pw_len = 0;
511         pwp.in.user_handle = handle;
512
513         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
514         if (NT_STATUS_IS_OK(status)) {
515                 policy_min_pw_len = pwp.out.info.min_password_length;
516         }
517         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
518
519         s.in.user_handle = handle;
520         s.in.info = &u;
521         s.in.level = 23;
522
523         ZERO_STRUCT(u);
524
525         u.info23.info.fields_present = fields_present;
526
527         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
528
529         status = dcerpc_fetch_session_key(p, &session_key);
530         if (!NT_STATUS_IS_OK(status)) {
531                 printf("SetUserInfo level %u - no session key - %s\n",
532                        s.in.level, nt_errstr(status));
533                 return False;
534         }
535
536         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
537
538         printf("Testing SetUserInfo level 23 (set password)\n");
539
540         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
541         if (!NT_STATUS_IS_OK(status)) {
542                 printf("SetUserInfo level %u failed - %s\n",
543                        s.in.level, nt_errstr(status));
544                 ret = False;
545         } else {
546                 *password = newpass;
547         }
548
549         return ret;
550 }
551
552
553 static BOOL test_SetUserPassEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
554                                struct policy_handle *handle, char **password)
555 {
556         NTSTATUS status;
557         struct samr_SetUserInfo s;
558         union samr_UserInfo u;
559         BOOL ret = True;
560         DATA_BLOB session_key;
561         DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
562         uint8_t confounder[16];
563         char *newpass;
564         struct MD5Context ctx;
565         struct samr_GetUserPwInfo pwp;
566         int policy_min_pw_len = 0;
567         pwp.in.user_handle = handle;
568
569         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
570         if (NT_STATUS_IS_OK(status)) {
571                 policy_min_pw_len = pwp.out.info.min_password_length;
572         }
573         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
574
575         s.in.user_handle = handle;
576         s.in.info = &u;
577         s.in.level = 26;
578
579         encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
580         u.info26.pw_len = strlen(newpass);
581
582         status = dcerpc_fetch_session_key(p, &session_key);
583         if (!NT_STATUS_IS_OK(status)) {
584                 printf("SetUserInfo level %u - no session key - %s\n",
585                        s.in.level, nt_errstr(status));
586                 return False;
587         }
588
589         generate_random_buffer((uint8_t *)confounder, 16);
590
591         MD5Init(&ctx);
592         MD5Update(&ctx, confounder, 16);
593         MD5Update(&ctx, session_key.data, session_key.length);
594         MD5Final(confounded_session_key.data, &ctx);
595
596         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
597         memcpy(&u.info26.password.data[516], confounder, 16);
598
599         printf("Testing SetUserInfo level 26 (set password ex)\n");
600
601         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
602         if (!NT_STATUS_IS_OK(status)) {
603                 printf("SetUserInfo level %u failed - %s\n",
604                        s.in.level, nt_errstr(status));
605                 ret = False;
606         } else {
607                 *password = newpass;
608         }
609
610         return ret;
611 }
612
613 static BOOL test_SetUserPass_25(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
614                                 struct policy_handle *handle, uint32_t fields_present,
615                                 char **password)
616 {
617         NTSTATUS status;
618         struct samr_SetUserInfo s;
619         union samr_UserInfo u;
620         BOOL ret = True;
621         DATA_BLOB session_key;
622         DATA_BLOB confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);
623         struct MD5Context ctx;
624         uint8_t confounder[16];
625         char *newpass;
626         struct samr_GetUserPwInfo pwp;
627         int policy_min_pw_len = 0;
628         pwp.in.user_handle = handle;
629
630         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
631         if (NT_STATUS_IS_OK(status)) {
632                 policy_min_pw_len = pwp.out.info.min_password_length;
633         }
634         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
635
636         s.in.user_handle = handle;
637         s.in.info = &u;
638         s.in.level = 25;
639
640         ZERO_STRUCT(u);
641
642         u.info25.info.fields_present = fields_present;
643
644         encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
645
646         status = dcerpc_fetch_session_key(p, &session_key);
647         if (!NT_STATUS_IS_OK(status)) {
648                 printf("SetUserInfo level %u - no session key - %s\n",
649                        s.in.level, nt_errstr(status));
650                 return False;
651         }
652
653         generate_random_buffer((uint8_t *)confounder, 16);
654
655         MD5Init(&ctx);
656         MD5Update(&ctx, confounder, 16);
657         MD5Update(&ctx, session_key.data, session_key.length);
658         MD5Final(confounded_session_key.data, &ctx);
659
660         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
661         memcpy(&u.info25.password.data[516], confounder, 16);
662
663         printf("Testing SetUserInfo level 25 (set password ex)\n");
664
665         status = dcerpc_samr_SetUserInfo(p, mem_ctx, &s);
666         if (!NT_STATUS_IS_OK(status)) {
667                 printf("SetUserInfo level %u failed - %s\n",
668                        s.in.level, nt_errstr(status));
669                 ret = False;
670         } else {
671                 *password = newpass;
672         }
673
674         return ret;
675 }
676
677 static BOOL test_SetAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
678                                struct policy_handle *handle)
679 {
680         NTSTATUS status;
681         struct samr_SetAliasInfo r;
682         struct samr_QueryAliasInfo q;
683         uint16_t levels[] = {2, 3};
684         int i;
685         BOOL ret = True;
686
687         /* Ignoring switch level 1, as that includes the number of members for the alias
688          * and setting this to a wrong value might have negative consequences
689          */
690
691         for (i=0;i<ARRAY_SIZE(levels);i++) {
692                 printf("Testing SetAliasInfo level %u\n", levels[i]);
693
694                 r.in.alias_handle = handle;
695                 r.in.level = levels[i];
696                 r.in.info  = talloc(mem_ctx, union samr_AliasInfo);
697                 switch (r.in.level) {
698                     case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
699                     case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
700                                 "Test Description, should test I18N as well"); break;
701                 }
702
703                 status = dcerpc_samr_SetAliasInfo(p, mem_ctx, &r);
704                 if (!NT_STATUS_IS_OK(status)) {
705                         printf("SetAliasInfo level %u failed - %s\n",
706                                levels[i], nt_errstr(status));
707                         ret = False;
708                 }
709
710                 q.in.alias_handle = handle;
711                 q.in.level = levels[i];
712
713                 status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &q);
714                 if (!NT_STATUS_IS_OK(status)) {
715                         printf("QueryAliasInfo level %u failed - %s\n",
716                                levels[i], nt_errstr(status));
717                         ret = False;
718                 }
719         }
720
721         return ret;
722 }
723
724 static BOOL test_GetGroupsForUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
725                                   struct policy_handle *user_handle)
726 {
727         struct samr_GetGroupsForUser r;
728         NTSTATUS status;
729         BOOL ret = True;
730
731         printf("testing GetGroupsForUser\n");
732
733         r.in.user_handle = user_handle;
734
735         status = dcerpc_samr_GetGroupsForUser(p, mem_ctx, &r);
736         if (!NT_STATUS_IS_OK(status)) {
737                 printf("GetGroupsForUser failed - %s\n",nt_errstr(status));
738                 ret = False;
739         }
740
741         return ret;
742
743 }
744
745 static BOOL test_GetDomPwInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
746                               struct lsa_String *domain_name)
747 {
748         NTSTATUS status;
749         struct samr_GetDomPwInfo r;
750         BOOL ret = True;
751
752         r.in.domain_name = domain_name;
753         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
754
755         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
756         if (!NT_STATUS_IS_OK(status)) {
757                 printf("GetDomPwInfo failed - %s\n", nt_errstr(status));
758                 ret = False;
759         }
760
761         r.in.domain_name->string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
762         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
763
764         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
765         if (!NT_STATUS_IS_OK(status)) {
766                 printf("GetDomPwInfo failed - %s\n", nt_errstr(status));
767                 ret = False;
768         }
769
770         r.in.domain_name->string = "\\\\__NONAME__";
771         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
772
773         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
774         if (!NT_STATUS_IS_OK(status)) {
775                 printf("GetDomPwInfo failed - %s\n", nt_errstr(status));
776                 ret = False;
777         }
778
779         r.in.domain_name->string = "\\\\Builtin";
780         printf("Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
781
782         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &r);
783         if (!NT_STATUS_IS_OK(status)) {
784                 printf("GetDomPwInfo failed - %s\n", nt_errstr(status));
785                 ret = False;
786         }
787
788
789         return ret;
790 }
791
792 static BOOL test_GetUserPwInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
793                                struct policy_handle *handle)
794 {
795         NTSTATUS status;
796         struct samr_GetUserPwInfo r;
797         BOOL ret = True;
798
799         printf("Testing GetUserPwInfo\n");
800
801         r.in.user_handle = handle;
802
803         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &r);
804         if (!NT_STATUS_IS_OK(status)) {
805                 printf("GetUserPwInfo failed - %s\n", nt_errstr(status));
806                 ret = False;
807         }
808
809         return ret;
810 }
811
812 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
813                                 struct policy_handle *domain_handle, const char *name,
814                                 uint32_t *rid)
815 {
816         NTSTATUS status;
817         struct samr_LookupNames n;
818         struct lsa_String sname[2];
819
820         init_lsa_String(&sname[0], name);
821
822         n.in.domain_handle = domain_handle;
823         n.in.num_names = 1;
824         n.in.names = sname;
825         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
826         if (NT_STATUS_IS_OK(status)) {
827                 *rid = n.out.rids.ids[0];
828         } else {
829                 return status;
830         }
831
832         init_lsa_String(&sname[1], "xxNONAMExx");
833         n.in.num_names = 2;
834         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
835         if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
836                 printf("LookupNames[2] failed - %s\n", nt_errstr(status));              
837                 return status;
838         }
839
840         init_lsa_String(&sname[1], "xxNONAMExx");
841         n.in.num_names = 0;
842         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
843         if (!NT_STATUS_IS_OK(status)) {
844                 printf("LookupNames[0] failed - %s\n", nt_errstr(status));              
845         }
846
847         return status;
848 }
849
850 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
851                                      struct policy_handle *domain_handle,
852                                      const char *name, struct policy_handle *user_handle)
853 {
854         NTSTATUS status;
855         struct samr_OpenUser r;
856         uint32_t rid;
857
858         status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
859         if (!NT_STATUS_IS_OK(status)) {
860                 return status;
861         }
862
863         r.in.domain_handle = domain_handle;
864         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
865         r.in.rid = rid;
866         r.out.user_handle = user_handle;
867         status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
868         if (!NT_STATUS_IS_OK(status)) {
869                 printf("OpenUser_byname(%s) failed - %s\n", name, nt_errstr(status));
870         }
871
872         return status;
873 }
874
875 #if 0
876 static BOOL test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
877                                    struct policy_handle *handle)
878 {
879         NTSTATUS status;
880         struct samr_ChangePasswordUser r;
881         BOOL ret = True;
882         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
883         struct policy_handle user_handle;
884         char *oldpass = "test";
885         char *newpass = "test2";
886         uint8_t old_nt_hash[16], new_nt_hash[16];
887         uint8_t old_lm_hash[16], new_lm_hash[16];
888
889         status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
890         if (!NT_STATUS_IS_OK(status)) {
891                 return False;
892         }
893
894         printf("Testing ChangePasswordUser for user 'testuser'\n");
895
896         printf("old password: %s\n", oldpass);
897         printf("new password: %s\n", newpass);
898
899         E_md4hash(oldpass, old_nt_hash);
900         E_md4hash(newpass, new_nt_hash);
901         E_deshash(oldpass, old_lm_hash);
902         E_deshash(newpass, new_lm_hash);
903
904         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
905         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
906         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
907         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
908         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
909         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
910
911         r.in.handle = &user_handle;
912         r.in.lm_present = 1;
913         r.in.old_lm_crypted = &hash1;
914         r.in.new_lm_crypted = &hash2;
915         r.in.nt_present = 1;
916         r.in.old_nt_crypted = &hash3;
917         r.in.new_nt_crypted = &hash4;
918         r.in.cross1_present = 1;
919         r.in.nt_cross = &hash5;
920         r.in.cross2_present = 1;
921         r.in.lm_cross = &hash6;
922
923         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
924         if (!NT_STATUS_IS_OK(status)) {
925                 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
926                 ret = False;
927         }
928
929         if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
930                 ret = False;
931         }
932
933         return ret;
934 }
935 #endif
936
937 static BOOL test_ChangePasswordUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
938                                     struct policy_handle *handle, char **password)
939 {
940         NTSTATUS status;
941         struct samr_ChangePasswordUser r;
942         BOOL ret = True;
943         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
944         struct policy_handle user_handle;
945         char *oldpass = *password;
946         uint8_t old_nt_hash[16], new_nt_hash[16];
947         uint8_t old_lm_hash[16], new_lm_hash[16];
948
949         char *newpass;
950         struct samr_GetUserPwInfo pwp;
951         int policy_min_pw_len = 0;
952
953         status = test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle);
954         if (!NT_STATUS_IS_OK(status)) {
955                 return False;
956         }
957         pwp.in.user_handle = &user_handle;
958
959         status = dcerpc_samr_GetUserPwInfo(p, mem_ctx, &pwp);
960         if (NT_STATUS_IS_OK(status)) {
961                 policy_min_pw_len = pwp.out.info.min_password_length;
962         }
963         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
964
965         printf("Testing ChangePasswordUser\n");
966
967         E_md4hash(oldpass, old_nt_hash);
968         E_md4hash(newpass, new_nt_hash);
969         E_deshash(oldpass, old_lm_hash);
970         E_deshash(newpass, new_lm_hash);
971
972         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
973         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
974         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
975         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
976         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
977         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
978
979         r.in.user_handle = &user_handle;
980         r.in.lm_present = 1;
981         r.in.old_lm_crypted = &hash1;
982         r.in.new_lm_crypted = &hash2;
983         r.in.nt_present = 1;
984         r.in.old_nt_crypted = &hash3;
985         r.in.new_nt_crypted = &hash4;
986         r.in.cross1_present = 1;
987         r.in.nt_cross = &hash5;
988         r.in.cross2_present = 1;
989         r.in.lm_cross = &hash6;
990
991         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
992         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
993                 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
994         } else  if (!NT_STATUS_IS_OK(status)) {
995                 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
996                 ret = False;
997         } else {
998                 *password = newpass;
999         }
1000
1001         if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
1002                 ret = False;
1003         }
1004
1005         return ret;
1006 }
1007
1008
1009 static BOOL test_OemChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1010                                         struct policy_handle *handle, char **password)
1011 {
1012         NTSTATUS status;
1013         struct samr_OemChangePasswordUser2 r;
1014         BOOL ret = True;
1015         struct samr_Password lm_verifier;
1016         struct samr_CryptPassword lm_pass;
1017         struct lsa_AsciiString server, account, account_bad;
1018         char *oldpass = *password;
1019         char *newpass;
1020         uint8_t old_lm_hash[16], new_lm_hash[16];
1021
1022         struct samr_GetDomPwInfo dom_pw_info;
1023         int policy_min_pw_len = 0;
1024
1025         struct lsa_String domain_name;
1026         domain_name.string = "";
1027         dom_pw_info.in.domain_name = &domain_name;
1028
1029         printf("Testing OemChangePasswordUser2\n");
1030
1031         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &dom_pw_info);
1032         if (NT_STATUS_IS_OK(status)) {
1033                 policy_min_pw_len = dom_pw_info.out.info.min_password_length;
1034         }
1035
1036         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
1037
1038         server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1039         account.string = TEST_ACCOUNT_NAME;
1040
1041         E_deshash(oldpass, old_lm_hash);
1042         E_deshash(newpass, new_lm_hash);
1043
1044         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1045         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1046         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1047
1048         r.in.server = &server;
1049         r.in.account = &account;
1050         r.in.password = &lm_pass;
1051         r.in.hash = &lm_verifier;
1052
1053         /* Break the verification */
1054         lm_verifier.hash[0]++;
1055
1056         status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
1057
1058         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1059             && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1060                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1061                         nt_errstr(status));
1062                 ret = False;
1063         }
1064
1065         /* This shouldn't be a valid name */
1066         account_bad.string = TEST_ACCOUNT_NAME "XX";
1067         r.in.account = &account_bad;
1068
1069         status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
1070
1071         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1072                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1073                         nt_errstr(status));
1074                 ret = False;
1075         }
1076
1077         E_deshash(oldpass, old_lm_hash);
1078         E_deshash(newpass, new_lm_hash);
1079
1080         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1081         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1082         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1083
1084         r.in.server = &server;
1085         r.in.account = &account;
1086         r.in.password = &lm_pass;
1087         r.in.hash = &lm_verifier;
1088
1089         status = dcerpc_samr_OemChangePasswordUser2(p, mem_ctx, &r);
1090         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1091                 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1092         } else if (!NT_STATUS_IS_OK(status)) {
1093                 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
1094                 ret = False;
1095         } else {
1096                 *password = newpass;
1097         }
1098
1099         return ret;
1100 }
1101
1102
1103 static BOOL test_ChangePasswordUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1104                                      struct policy_handle *handle, char **password)
1105 {
1106         NTSTATUS status;
1107         struct samr_ChangePasswordUser2 r;
1108         BOOL ret = True;
1109         struct lsa_String server, account;
1110         struct samr_CryptPassword nt_pass, lm_pass;
1111         struct samr_Password nt_verifier, lm_verifier;
1112         char *oldpass = *password;
1113         char *newpass;
1114         uint8_t old_nt_hash[16], new_nt_hash[16];
1115         uint8_t old_lm_hash[16], new_lm_hash[16];
1116
1117         struct samr_GetDomPwInfo dom_pw_info;
1118         int policy_min_pw_len = 0;
1119
1120         struct lsa_String domain_name;
1121         domain_name.string = "";
1122         dom_pw_info.in.domain_name = &domain_name;
1123
1124         printf("Testing ChangePasswordUser2\n");
1125
1126         status = dcerpc_samr_GetDomPwInfo(p, mem_ctx, &dom_pw_info);
1127         if (NT_STATUS_IS_OK(status)) {
1128                 policy_min_pw_len = dom_pw_info.out.info.min_password_length;
1129         }
1130
1131         newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);
1132
1133         server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1134         init_lsa_String(&account, TEST_ACCOUNT_NAME);
1135
1136         E_md4hash(oldpass, old_nt_hash);
1137         E_md4hash(newpass, new_nt_hash);
1138
1139         E_deshash(oldpass, old_lm_hash);
1140         E_deshash(newpass, new_lm_hash);
1141
1142         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
1143         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1144         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1145
1146         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1147         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1148         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1149
1150         r.in.server = &server;
1151         r.in.account = &account;
1152         r.in.nt_password = &nt_pass;
1153         r.in.nt_verifier = &nt_verifier;
1154         r.in.lm_change = 1;
1155         r.in.lm_password = &lm_pass;
1156         r.in.lm_verifier = &lm_verifier;
1157
1158         status = dcerpc_samr_ChangePasswordUser2(p, mem_ctx, &r);
1159         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1160                 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1161         } else if (!NT_STATUS_IS_OK(status)) {
1162                 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
1163                 ret = False;
1164         } else {
1165                 *password = newpass;
1166         }
1167
1168         return ret;
1169 }
1170
1171
1172 BOOL test_ChangePasswordUser3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1173                               const char *account_string,
1174                               int policy_min_pw_len,
1175                               char **password)
1176 {
1177         NTSTATUS status;
1178         struct samr_ChangePasswordUser3 r;
1179         BOOL ret = True;
1180         struct lsa_String server, account, account_bad;
1181         struct samr_CryptPassword nt_pass, lm_pass;
1182         struct samr_Password nt_verifier, lm_verifier;
1183         char *oldpass = *password;
1184         char *newpass = samr_rand_pass(mem_ctx, policy_min_pw_len);     
1185         uint8_t old_nt_hash[16], new_nt_hash[16];
1186         uint8_t old_lm_hash[16], new_lm_hash[16];
1187
1188         printf("Testing ChangePasswordUser3\n");
1189
1190         server.string = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(p));
1191         init_lsa_String(&account, account_string);
1192
1193         E_md4hash(oldpass, old_nt_hash);
1194         E_md4hash(newpass, new_nt_hash);
1195
1196         E_deshash(oldpass, old_lm_hash);
1197         E_deshash(newpass, new_lm_hash);
1198
1199         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
1200         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
1201         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1202
1203         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1204         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1205         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1206         
1207         /* Break the verification */
1208         nt_verifier.hash[0]++;
1209
1210         r.in.server = &server;
1211         r.in.account = &account;
1212         r.in.nt_password = &nt_pass;
1213         r.in.nt_verifier = &nt_verifier;
1214         r.in.lm_change = 1;
1215         r.in.lm_password = &lm_pass;
1216         r.in.lm_verifier = &lm_verifier;
1217         r.in.password3 = NULL;
1218
1219         status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
1220         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
1221             (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
1222                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1223                         nt_errstr(status));
1224                 ret = False;
1225         }
1226         
1227         /* This shouldn't be a valid name */
1228         init_lsa_String(&account_bad, talloc_asprintf(mem_ctx, "%sXX", account_string));
1229
1230         r.in.account = &account_bad;
1231         status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
1232         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1233                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
1234                         nt_errstr(status));
1235                 ret = False;
1236         }
1237
1238         E_md4hash(oldpass, old_nt_hash);
1239         E_md4hash(newpass, new_nt_hash);
1240
1241         E_deshash(oldpass, old_lm_hash);
1242         E_deshash(newpass, new_lm_hash);
1243
1244         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
1245         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
1246         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1247
1248         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1249         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1250         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1251
1252         r.in.server = &server;
1253         r.in.account = &account;
1254         r.in.nt_password = &nt_pass;
1255         r.in.nt_verifier = &nt_verifier;
1256         r.in.lm_change = 1;
1257         r.in.lm_password = &lm_pass;
1258         r.in.lm_verifier = &lm_verifier;
1259         r.in.password3 = NULL;
1260
1261         status = dcerpc_samr_ChangePasswordUser3(p, mem_ctx, &r);
1262         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) 
1263             && !policy_min_pw_len) {
1264                 if (r.out.dominfo) {
1265                         policy_min_pw_len = r.out.dominfo->min_password_length;
1266                 }
1267                 if (policy_min_pw_len) /* try again with the right min password length */ {
1268                         ret = test_ChangePasswordUser3(p, mem_ctx, account_string, policy_min_pw_len, password);
1269                 } else {
1270                         printf("ChangePasswordUser3 failed (no min length known) - %s\n", nt_errstr(status));
1271                         ret = False;
1272                 }
1273         } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1274                 printf("ChangePasswordUser3 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1275         } else if (!NT_STATUS_IS_OK(status)) {
1276                 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
1277                 ret = False;
1278         } else {
1279                 *password = newpass;
1280         }
1281
1282         return ret;
1283 }
1284
1285
1286 static BOOL test_GetMembersInAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1287                                   struct policy_handle *alias_handle)
1288 {
1289         struct samr_GetMembersInAlias r;
1290         struct lsa_SidArray sids;
1291         NTSTATUS status;
1292         BOOL     ret = True;
1293
1294         printf("Testing GetMembersInAlias\n");
1295
1296         r.in.alias_handle = alias_handle;
1297         r.out.sids = &sids;
1298
1299         status = dcerpc_samr_GetMembersInAlias(p, mem_ctx, &r);
1300         if (!NT_STATUS_IS_OK(status)) {
1301                 printf("GetMembersInAlias failed - %s\n",
1302                        nt_errstr(status));
1303                 ret = False;
1304         }
1305
1306         return ret;
1307 }
1308
1309 static BOOL test_AddMemberToAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1310                                   struct policy_handle *alias_handle,
1311                                   const struct dom_sid *domain_sid)
1312 {
1313         struct samr_AddAliasMember r;
1314         struct samr_DeleteAliasMember d;
1315         NTSTATUS status;
1316         BOOL ret = True;
1317         struct dom_sid *sid;
1318
1319         sid = dom_sid_add_rid(mem_ctx, domain_sid, 512);
1320
1321         printf("testing AddAliasMember\n");
1322         r.in.alias_handle = alias_handle;
1323         r.in.sid = sid;
1324
1325         status = dcerpc_samr_AddAliasMember(p, mem_ctx, &r);
1326         if (!NT_STATUS_IS_OK(status)) {
1327                 printf("AddAliasMember failed - %s\n", nt_errstr(status));
1328                 ret = False;
1329         }
1330
1331         d.in.alias_handle = alias_handle;
1332         d.in.sid = sid;
1333
1334         status = dcerpc_samr_DeleteAliasMember(p, mem_ctx, &d);
1335         if (!NT_STATUS_IS_OK(status)) {
1336                 printf("DelAliasMember failed - %s\n", nt_errstr(status));
1337                 ret = False;
1338         }
1339
1340         return ret;
1341 }
1342
1343 static BOOL test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1344                                            struct policy_handle *alias_handle)
1345 {
1346         struct samr_AddMultipleMembersToAlias a;
1347         struct samr_RemoveMultipleMembersFromAlias r;
1348         NTSTATUS status;
1349         BOOL ret = True;
1350         struct lsa_SidArray sids;
1351
1352         printf("testing AddMultipleMembersToAlias\n");
1353         a.in.alias_handle = alias_handle;
1354         a.in.sids = &sids;
1355
1356         sids.num_sids = 3;
1357         sids.sids = talloc_array(mem_ctx, struct lsa_SidPtr, 3);
1358
1359         sids.sids[0].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-1");
1360         sids.sids[1].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-2");
1361         sids.sids[2].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-3");
1362
1363         status = dcerpc_samr_AddMultipleMembersToAlias(p, mem_ctx, &a);
1364         if (!NT_STATUS_IS_OK(status)) {
1365                 printf("AddMultipleMembersToAlias failed - %s\n", nt_errstr(status));
1366                 ret = False;
1367         }
1368
1369
1370         printf("testing RemoveMultipleMembersFromAlias\n");
1371         r.in.alias_handle = alias_handle;
1372         r.in.sids = &sids;
1373
1374         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
1375         if (!NT_STATUS_IS_OK(status)) {
1376                 printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
1377                 ret = False;
1378         }
1379
1380         /* strange! removing twice doesn't give any error */
1381         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
1382         if (!NT_STATUS_IS_OK(status)) {
1383                 printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
1384                 ret = False;
1385         }
1386
1387         /* but removing an alias that isn't there does */
1388         sids.sids[2].sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1-2-3-4");
1389
1390         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, mem_ctx, &r);
1391         if (!NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND, status)) {
1392                 printf("RemoveMultipleMembersFromAlias failed - %s\n", nt_errstr(status));
1393                 ret = False;
1394         }
1395
1396         return ret;
1397 }
1398
1399 static BOOL test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1400                                             struct policy_handle *user_handle)
1401 {
1402         struct samr_TestPrivateFunctionsUser r;
1403         NTSTATUS status;
1404         BOOL ret = True;
1405
1406         printf("Testing TestPrivateFunctionsUser\n");
1407
1408         r.in.user_handle = user_handle;
1409
1410         status = dcerpc_samr_TestPrivateFunctionsUser(p, mem_ctx, &r);
1411         if (!NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
1412                 printf("TestPrivateFunctionsUser failed - %s\n", nt_errstr(status));
1413                 ret = False;
1414         }
1415
1416         return ret;
1417 }
1418
1419
1420 static BOOL test_user_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1421                           struct policy_handle *handle, uint32_t base_acct_flags, 
1422                           const char *base_acct_name)
1423 {
1424         BOOL ret = True;
1425
1426         if (!test_QuerySecurity(p, mem_ctx, handle)) {
1427                 ret = False;
1428         }
1429
1430         if (!test_QueryUserInfo(p, mem_ctx, handle)) {
1431                 ret = False;
1432         }
1433
1434         if (!test_QueryUserInfo2(p, mem_ctx, handle)) {
1435                 ret = False;
1436         }
1437
1438         if (!test_SetUserInfo(p, mem_ctx, handle, base_acct_flags,
1439                               base_acct_name)) {
1440                 ret = False;
1441         }       
1442
1443         if (!test_GetUserPwInfo(p, mem_ctx, handle)) {
1444                 ret = False;
1445         }
1446
1447         if (!test_TestPrivateFunctionsUser(p, mem_ctx, handle)) {
1448                 ret = False;
1449         }
1450
1451         return ret;
1452 }
1453
1454 static BOOL test_alias_ops(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1455                            struct policy_handle *alias_handle,
1456                            const struct dom_sid *domain_sid)
1457 {
1458         BOOL ret = True;
1459
1460         if (!test_QuerySecurity(p, mem_ctx, alias_handle)) {
1461                 ret = False;
1462         }
1463
1464         if (!test_QueryAliasInfo(p, mem_ctx, alias_handle)) {
1465                 ret = False;
1466         }
1467
1468         if (!test_SetAliasInfo(p, mem_ctx, alias_handle)) {
1469                 ret = False;
1470         }
1471
1472         if (!test_AddMemberToAlias(p, mem_ctx, alias_handle, domain_sid)) {
1473                 ret = False;
1474         }
1475
1476         if (lp_parm_bool(-1, "target", "samba4", False)) {
1477                 printf("skipping MultipleMembers Alias tests against Samba4\n");
1478                 return ret;
1479         }
1480
1481         if (!test_AddMultipleMembersToAlias(p, mem_ctx, alias_handle)) {
1482                 ret = False;
1483         }
1484
1485         return ret;
1486 }
1487
1488
1489 BOOL test_DeleteUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1490                             struct policy_handle *handle, const char *name)
1491 {
1492         NTSTATUS status;
1493         struct samr_DeleteUser d;
1494         struct policy_handle user_handle;
1495         uint32_t rid;
1496
1497         status = test_LookupName(p, mem_ctx, handle, name, &rid);
1498         if (!NT_STATUS_IS_OK(status)) {
1499                 goto failed;
1500         }
1501
1502         status = test_OpenUser_byname(p, mem_ctx, handle, name, &user_handle);
1503         if (!NT_STATUS_IS_OK(status)) {
1504                 goto failed;
1505         }
1506
1507         d.in.user_handle = &user_handle;
1508         d.out.user_handle = &user_handle;
1509         status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
1510         if (!NT_STATUS_IS_OK(status)) {
1511                 goto failed;
1512         }
1513
1514         return True;
1515
1516 failed:
1517         printf("DeleteUser_byname(%s) failed - %s\n", name, nt_errstr(status));
1518         return False;
1519 }
1520
1521
1522 static BOOL test_DeleteGroup_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1523                                     struct policy_handle *handle, const char *name)
1524 {
1525         NTSTATUS status;
1526         struct samr_OpenGroup r;
1527         struct samr_DeleteDomainGroup d;
1528         struct policy_handle group_handle;
1529         uint32_t rid;
1530
1531         status = test_LookupName(p, mem_ctx, handle, name, &rid);
1532         if (!NT_STATUS_IS_OK(status)) {
1533                 goto failed;
1534         }
1535
1536         r.in.domain_handle = handle;
1537         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1538         r.in.rid = rid;
1539         r.out.group_handle = &group_handle;
1540         status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
1541         if (!NT_STATUS_IS_OK(status)) {
1542                 goto failed;
1543         }
1544
1545         d.in.group_handle = &group_handle;
1546         d.out.group_handle = &group_handle;
1547         status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
1548         if (!NT_STATUS_IS_OK(status)) {
1549                 goto failed;
1550         }
1551
1552         return True;
1553
1554 failed:
1555         printf("DeleteGroup_byname(%s) failed - %s\n", name, nt_errstr(status));
1556         return False;
1557 }
1558
1559
1560 static BOOL test_DeleteAlias_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1561                                    struct policy_handle *domain_handle, const char *name)
1562 {
1563         NTSTATUS status;
1564         struct samr_OpenAlias r;
1565         struct samr_DeleteDomAlias d;
1566         struct policy_handle alias_handle;
1567         uint32_t rid;
1568
1569         printf("testing DeleteAlias_byname\n");
1570
1571         status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
1572         if (!NT_STATUS_IS_OK(status)) {
1573                 goto failed;
1574         }
1575
1576         r.in.domain_handle = domain_handle;
1577         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1578         r.in.rid = rid;
1579         r.out.alias_handle = &alias_handle;
1580         status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
1581         if (!NT_STATUS_IS_OK(status)) {
1582                 goto failed;
1583         }
1584
1585         d.in.alias_handle = &alias_handle;
1586         d.out.alias_handle = &alias_handle;
1587         status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
1588         if (!NT_STATUS_IS_OK(status)) {
1589                 goto failed;
1590         }
1591
1592         return True;
1593
1594 failed:
1595         printf("DeleteAlias_byname(%s) failed - %s\n", name, nt_errstr(status));
1596         return False;
1597 }
1598
1599 static BOOL test_DeleteAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1600                                      struct policy_handle *alias_handle)
1601 {
1602         struct samr_DeleteDomAlias d;
1603         NTSTATUS status;
1604         BOOL ret = True;
1605         printf("Testing DeleteAlias\n");
1606
1607         d.in.alias_handle = alias_handle;
1608         d.out.alias_handle = alias_handle;
1609
1610         status = dcerpc_samr_DeleteDomAlias(p, mem_ctx, &d);
1611         if (!NT_STATUS_IS_OK(status)) {
1612                 printf("DeleteAlias failed - %s\n", nt_errstr(status));
1613                 ret = False;
1614         }
1615
1616         return ret;
1617 }
1618
1619 static BOOL test_CreateAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1620                             struct policy_handle *domain_handle, 
1621                              struct policy_handle *alias_handle, 
1622                              const struct dom_sid *domain_sid)
1623 {
1624         NTSTATUS status;
1625         struct samr_CreateDomAlias r;
1626         struct lsa_String name;
1627         uint32_t rid;
1628         BOOL ret = True;
1629
1630         init_lsa_String(&name, TEST_ALIASNAME);
1631         r.in.domain_handle = domain_handle;
1632         r.in.alias_name = &name;
1633         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1634         r.out.alias_handle = alias_handle;
1635         r.out.rid = &rid;
1636
1637         printf("Testing CreateAlias (%s)\n", r.in.alias_name->string);
1638
1639         status = dcerpc_samr_CreateDomAlias(p, mem_ctx, &r);
1640
1641         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1642                 printf("Server refused create of '%s'\n", r.in.alias_name->string);
1643                 return True;
1644         }
1645
1646         if (NT_STATUS_EQUAL(status, NT_STATUS_ALIAS_EXISTS)) {
1647                 if (!test_DeleteAlias_byname(p, mem_ctx, domain_handle, r.in.alias_name->string)) {
1648                         return False;
1649                 }
1650                 status = dcerpc_samr_CreateDomAlias(p, mem_ctx, &r);
1651         }
1652
1653         if (!NT_STATUS_IS_OK(status)) {
1654                 printf("CreateAlias failed - %s\n", nt_errstr(status));
1655                 return False;
1656         }
1657
1658         if (!test_alias_ops(p, mem_ctx, alias_handle, domain_sid)) {
1659                 ret = False;
1660         }
1661
1662         return ret;
1663 }
1664
1665 static BOOL test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1666                                 struct policy_handle *domain_handle, char **password)
1667 {
1668         BOOL ret = True;
1669
1670         if (!*password) {
1671                 return False;
1672         }
1673
1674         if (!test_ChangePasswordUser(p, mem_ctx, domain_handle, password)) {
1675                 ret = False;
1676         }
1677
1678         if (!test_ChangePasswordUser2(p, mem_ctx, domain_handle, password)) {
1679                 ret = False;
1680         }
1681
1682         if (!test_OemChangePasswordUser2(p, mem_ctx, domain_handle, password)) {
1683                 ret = False;
1684         }
1685
1686         /* we change passwords twice - this has the effect of verifying
1687            they were changed correctly for the final call */
1688         if (!test_ChangePasswordUser3(p, mem_ctx, TEST_ACCOUNT_NAME, 0, password)) {
1689                 ret = False;
1690         }
1691
1692         if (!test_ChangePasswordUser3(p, mem_ctx, TEST_ACCOUNT_NAME, 0, password)) {
1693                 ret = False;
1694         }
1695
1696         return ret;
1697 }
1698
1699 static BOOL test_CreateUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1700                             struct policy_handle *domain_handle, struct policy_handle *user_handle)
1701 {
1702         NTSTATUS status;
1703         struct samr_CreateUser r;
1704         struct samr_QueryUserInfo q;
1705         uint32_t rid;
1706         char *password = NULL;
1707
1708         int i;
1709         const uint32_t password_fields[] = {
1710                 SAMR_FIELD_PASSWORD,
1711                 SAMR_FIELD_PASSWORD2,
1712                 SAMR_FIELD_PASSWORD | SAMR_FIELD_PASSWORD2,
1713                 0
1714         };
1715         
1716         TALLOC_CTX *user_ctx;
1717
1718         /* This call creates a 'normal' account - check that it really does */
1719         const uint32_t acct_flags = ACB_NORMAL;
1720         struct lsa_String name;
1721         BOOL ret = True;
1722
1723         user_ctx = talloc_named(mem_ctx, 0, "test_CreateUser2 per-user context");
1724         init_lsa_String(&name, TEST_ACCOUNT_NAME);
1725
1726         r.in.domain_handle = domain_handle;
1727         r.in.account_name = &name;
1728         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1729         r.out.user_handle = user_handle;
1730         r.out.rid = &rid;
1731
1732         printf("Testing CreateUser(%s)\n", r.in.account_name->string);
1733
1734         status = dcerpc_samr_CreateUser(p, user_ctx, &r);
1735
1736         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1737                 printf("Server refused create of '%s'\n", r.in.account_name->string);
1738                 ZERO_STRUCTP(user_handle);
1739                 talloc_free(user_ctx);
1740                 return True;
1741         }
1742
1743         if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
1744                 if (!test_DeleteUser_byname(p, user_ctx, domain_handle, r.in.account_name->string)) {
1745                         talloc_free(user_ctx);
1746                         return False;
1747                 }
1748                 status = dcerpc_samr_CreateUser(p, user_ctx, &r);
1749         }
1750         if (!NT_STATUS_IS_OK(status)) {
1751                 talloc_free(user_ctx);
1752                 printf("CreateUser failed - %s\n", nt_errstr(status));
1753                 return False;
1754         }
1755
1756         q.in.user_handle = user_handle;
1757         q.in.level = 16;
1758
1759         status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
1760         if (!NT_STATUS_IS_OK(status)) {
1761                 printf("QueryUserInfo level %u failed - %s\n", 
1762                        q.in.level, nt_errstr(status));
1763                 ret = False;
1764         } else {
1765                 if ((q.out.info->info16.acct_flags & acct_flags) != acct_flags) {
1766                         printf("QuerUserInfo level 16 failed, it returned 0x%08x (%u) when we expected flags of 0x%08x (%u)\n",
1767                                q.out.info->info16.acct_flags, q.out.info->info16.acct_flags, 
1768                                acct_flags, acct_flags);
1769                         ret = False;
1770                 }
1771         }
1772
1773         if (!test_user_ops(p, user_ctx, user_handle, acct_flags, name.string)) {
1774                 ret = False;
1775         }
1776
1777         if (!test_SetUserPass(p, user_ctx, user_handle, &password)) {
1778                 ret = False;
1779         }       
1780
1781         for (i = 0; password_fields[i]; i++) {
1782                 if (!test_SetUserPass_23(p, user_ctx, user_handle, password_fields[i], &password)) {
1783                         ret = False;
1784                 }       
1785                 
1786                 /* check it was set right */
1787                 if (!test_ChangePasswordUser3(p, user_ctx, TEST_ACCOUNT_NAME, 0, &password)) {
1788                         ret = False;
1789                 }
1790         }               
1791
1792         for (i = 0; password_fields[i]; i++) {
1793                 if (!test_SetUserPass_25(p, user_ctx, user_handle, password_fields[i], &password)) {
1794                         ret = False;
1795                 }       
1796                 
1797                 /* check it was set right */
1798                 if (!test_ChangePasswordUser3(p, user_ctx, TEST_ACCOUNT_NAME, 0, &password)) {
1799                         ret = False;
1800                 }
1801         }               
1802
1803         if (!test_SetUserPassEx(p, user_ctx, user_handle, &password)) {
1804                 ret = False;
1805         }       
1806
1807         if (!test_ChangePassword(p, user_ctx, domain_handle, &password)) {
1808                 ret = False;
1809         }       
1810
1811         talloc_free(user_ctx);
1812         
1813         return ret;
1814 }
1815
1816
1817 static BOOL test_DeleteUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
1818                             struct policy_handle *user_handle)
1819 {
1820         struct samr_DeleteUser d;
1821         NTSTATUS status;
1822         BOOL ret = True;
1823
1824         printf("Testing DeleteUser\n");
1825
1826         d.in.user_handle = user_handle;
1827         d.out.user_handle = user_handle;
1828
1829         status = dcerpc_samr_DeleteUser(p, mem_ctx, &d);
1830         if (!NT_STATUS_IS_OK(status)) {
1831                 printf("DeleteUser failed - %s\n", nt_errstr(status));
1832                 ret = False;
1833         }
1834
1835         return ret;
1836 }
1837
1838 static BOOL test_CreateUser2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1839                              struct policy_handle *handle)
1840 {
1841         NTSTATUS status;
1842         struct samr_CreateUser2 r;
1843         struct samr_QueryUserInfo q;
1844         struct samr_DeleteUser d;
1845         struct policy_handle user_handle;
1846         uint32_t rid;
1847         struct lsa_String name;
1848         BOOL ret = True;
1849         int i;
1850
1851         struct {
1852                 uint32_t acct_flags;
1853                 const char *account_name;
1854                 NTSTATUS nt_status;
1855         } account_types[] = {
1856                 { ACB_NORMAL, TEST_ACCOUNT_NAME, NT_STATUS_OK },
1857                 { ACB_NORMAL | ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
1858                 { ACB_NORMAL | ACB_PWNOEXP, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
1859                 { ACB_WSTRUST, TEST_MACHINENAME, NT_STATUS_OK },
1860                 { ACB_WSTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
1861                 { ACB_WSTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
1862                 { ACB_SVRTRUST, TEST_MACHINENAME, NT_STATUS_OK },
1863                 { ACB_SVRTRUST | ACB_DISABLED, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
1864                 { ACB_SVRTRUST | ACB_PWNOEXP, TEST_MACHINENAME, NT_STATUS_INVALID_PARAMETER },
1865                 { ACB_DOMTRUST, TEST_DOMAINNAME, NT_STATUS_OK },
1866                 { ACB_DOMTRUST | ACB_DISABLED, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
1867                 { ACB_DOMTRUST | ACB_PWNOEXP, TEST_DOMAINNAME, NT_STATUS_INVALID_PARAMETER },
1868                 { 0, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
1869                 { ACB_DISABLED, TEST_ACCOUNT_NAME, NT_STATUS_INVALID_PARAMETER },
1870                 { 0, NULL, NT_STATUS_INVALID_PARAMETER }
1871         };
1872
1873         for (i = 0; account_types[i].account_name; i++) {
1874                 TALLOC_CTX *user_ctx;
1875                 uint32_t acct_flags = account_types[i].acct_flags;
1876                 uint32_t access_granted;
1877                 user_ctx = talloc_named(mem_ctx, 0, "test_CreateUser2 per-user context");
1878                 init_lsa_String(&name, account_types[i].account_name);
1879
1880                 r.in.domain_handle = handle;
1881                 r.in.account_name = &name;
1882                 r.in.acct_flags = acct_flags;
1883                 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1884                 r.out.user_handle = &user_handle;
1885                 r.out.access_granted = &access_granted;
1886                 r.out.rid = &rid;
1887                 
1888                 printf("Testing CreateUser2(%s, 0x%x)\n", r.in.account_name->string, acct_flags);
1889                 
1890                 status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
1891                 
1892                 if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
1893                         talloc_free(user_ctx);
1894                         printf("Server refused create of '%s'\n", r.in.account_name->string);
1895                         continue;
1896
1897                 } else if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
1898                         if (!test_DeleteUser_byname(p, user_ctx, handle, r.in.account_name->string)) {
1899                                 talloc_free(user_ctx);
1900                                 ret = False;
1901                                 continue;
1902                         }
1903                         status = dcerpc_samr_CreateUser2(p, user_ctx, &r);
1904
1905                 }
1906                 if (!NT_STATUS_EQUAL(status, account_types[i].nt_status)) {
1907                         printf("CreateUser2 failed gave incorrect error return - %s (should be %s)\n", 
1908                                nt_errstr(status), nt_errstr(account_types[i].nt_status));
1909                         ret = False;
1910                 }
1911                 
1912                 if (NT_STATUS_IS_OK(status)) {
1913                         q.in.user_handle = &user_handle;
1914                         q.in.level = 16;
1915                         
1916                         status = dcerpc_samr_QueryUserInfo(p, user_ctx, &q);
1917                         if (!NT_STATUS_IS_OK(status)) {
1918                                 printf("QueryUserInfo level %u failed - %s\n", 
1919                                        q.in.level, nt_errstr(status));
1920                                 ret = False;
1921                         } else {
1922                                 if ((q.out.info->info16.acct_flags & acct_flags) != acct_flags) {
1923                                         printf("QuerUserInfo level 16 failed, it returned 0x%08x when we expected flags of 0x%08x\n",
1924                                                q.out.info->info16.acct_flags, 
1925                                                acct_flags);
1926                                         ret = False;
1927                                 }
1928                         }
1929                 
1930                         if (!test_user_ops(p, user_ctx, &user_handle, acct_flags, name.string)) {
1931                                 ret = False;
1932                         }
1933
1934                         printf("Testing DeleteUser (createuser2 test)\n");
1935                 
1936                         d.in.user_handle = &user_handle;
1937                         d.out.user_handle = &user_handle;
1938                         
1939                         status = dcerpc_samr_DeleteUser(p, user_ctx, &d);
1940                         if (!NT_STATUS_IS_OK(status)) {
1941                                 printf("DeleteUser failed - %s\n", nt_errstr(status));
1942                                 ret = False;
1943                         }
1944                 }
1945                 talloc_free(user_ctx);
1946         }
1947
1948         return ret;
1949 }
1950
1951 static BOOL test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1952                                 struct policy_handle *handle)
1953 {
1954         NTSTATUS status;
1955         struct samr_QueryAliasInfo r;
1956         uint16_t levels[] = {1, 2, 3};
1957         int i;
1958         BOOL ret = True;
1959
1960         for (i=0;i<ARRAY_SIZE(levels);i++) {
1961                 printf("Testing QueryAliasInfo level %u\n", levels[i]);
1962
1963                 r.in.alias_handle = handle;
1964                 r.in.level = levels[i];
1965
1966                 status = dcerpc_samr_QueryAliasInfo(p, mem_ctx, &r);
1967                 if (!NT_STATUS_IS_OK(status)) {
1968                         printf("QueryAliasInfo level %u failed - %s\n", 
1969                                levels[i], nt_errstr(status));
1970                         ret = False;
1971                 }
1972         }
1973
1974         return ret;
1975 }
1976
1977 static BOOL test_QueryGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1978                                 struct policy_handle *handle)
1979 {
1980         NTSTATUS status;
1981         struct samr_QueryGroupInfo r;
1982         uint16_t levels[] = {1, 2, 3, 4, 5};
1983         int i;
1984         BOOL ret = True;
1985
1986         for (i=0;i<ARRAY_SIZE(levels);i++) {
1987                 printf("Testing QueryGroupInfo level %u\n", levels[i]);
1988
1989                 r.in.group_handle = handle;
1990                 r.in.level = levels[i];
1991
1992                 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
1993                 if (!NT_STATUS_IS_OK(status)) {
1994                         printf("QueryGroupInfo level %u failed - %s\n", 
1995                                levels[i], nt_errstr(status));
1996                         ret = False;
1997                 }
1998         }
1999
2000         return ret;
2001 }
2002
2003 static BOOL test_QueryGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2004                                   struct policy_handle *handle)
2005 {
2006         NTSTATUS status;
2007         struct samr_QueryGroupMember r;
2008         BOOL ret = True;
2009
2010         printf("Testing QueryGroupMember\n");
2011
2012         r.in.group_handle = handle;
2013
2014         status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &r);
2015         if (!NT_STATUS_IS_OK(status)) {
2016                 printf("QueryGroupInfo failed - %s\n", nt_errstr(status));
2017                 ret = False;
2018         }
2019
2020         return ret;
2021 }
2022
2023
2024 static BOOL test_SetGroupInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2025                               struct policy_handle *handle)
2026 {
2027         NTSTATUS status;
2028         struct samr_QueryGroupInfo r;
2029         struct samr_SetGroupInfo s;
2030         uint16_t levels[] = {1, 2, 3, 4};
2031         uint16_t set_ok[] = {0, 1, 1, 1};
2032         int i;
2033         BOOL ret = True;
2034
2035         for (i=0;i<ARRAY_SIZE(levels);i++) {
2036                 printf("Testing QueryGroupInfo level %u\n", levels[i]);
2037
2038                 r.in.group_handle = handle;
2039                 r.in.level = levels[i];
2040
2041                 status = dcerpc_samr_QueryGroupInfo(p, mem_ctx, &r);
2042                 if (!NT_STATUS_IS_OK(status)) {
2043                         printf("QueryGroupInfo level %u failed - %s\n", 
2044                                levels[i], nt_errstr(status));
2045                         ret = False;
2046                 }
2047
2048                 printf("Testing SetGroupInfo level %u\n", levels[i]);
2049
2050                 s.in.group_handle = handle;
2051                 s.in.level = levels[i];
2052                 s.in.info = r.out.info;
2053
2054 #if 0
2055                 /* disabled this, as it changes the name only from the point of view of samr, 
2056                    but leaves the name from the point of view of w2k3 internals (and ldap). This means
2057                    the name is still reserved, so creating the old name fails, but deleting by the old name
2058                    also fails */
2059                 if (s.in.level == 2) {
2060                         init_lsa_String(&s.in.info->string, "NewName");
2061                 }
2062 #endif
2063
2064                 if (s.in.level == 4) {
2065                         init_lsa_String(&s.in.info->description, "test description");
2066                 }
2067
2068                 status = dcerpc_samr_SetGroupInfo(p, mem_ctx, &s);
2069                 if (set_ok[i]) {
2070                         if (!NT_STATUS_IS_OK(status)) {
2071                                 printf("SetGroupInfo level %u failed - %s\n", 
2072                                        r.in.level, nt_errstr(status));
2073                                 ret = False;
2074                                 continue;
2075                         }
2076                 } else {
2077                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
2078                                 printf("SetGroupInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n", 
2079                                        r.in.level, nt_errstr(status));
2080                                 ret = False;
2081                                 continue;
2082                         }
2083                 }
2084         }
2085
2086         return ret;
2087 }
2088
2089 static BOOL test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2090                                struct policy_handle *handle)
2091 {
2092         NTSTATUS status;
2093         struct samr_QueryUserInfo r;
2094         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2095                            11, 12, 13, 14, 16, 17, 20, 21};
2096         int i;
2097         BOOL ret = True;
2098
2099         for (i=0;i<ARRAY_SIZE(levels);i++) {
2100                 printf("Testing QueryUserInfo level %u\n", levels[i]);
2101
2102                 r.in.user_handle = handle;
2103                 r.in.level = levels[i];
2104
2105                 status = dcerpc_samr_QueryUserInfo(p, mem_ctx, &r);
2106                 if (!NT_STATUS_IS_OK(status)) {
2107                         printf("QueryUserInfo level %u failed - %s\n", 
2108                                levels[i], nt_errstr(status));
2109                         ret = False;
2110                 }
2111         }
2112
2113         return ret;
2114 }
2115
2116 static BOOL test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2117                                 struct policy_handle *handle)
2118 {
2119         NTSTATUS status;
2120         struct samr_QueryUserInfo2 r;
2121         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2122                            11, 12, 13, 14, 16, 17, 20, 21};
2123         int i;
2124         BOOL ret = True;
2125
2126         for (i=0;i<ARRAY_SIZE(levels);i++) {
2127                 printf("Testing QueryUserInfo2 level %u\n", levels[i]);
2128
2129                 r.in.user_handle = handle;
2130                 r.in.level = levels[i];
2131
2132                 status = dcerpc_samr_QueryUserInfo2(p, mem_ctx, &r);
2133                 if (!NT_STATUS_IS_OK(status)) {
2134                         printf("QueryUserInfo2 level %u failed - %s\n", 
2135                                levels[i], nt_errstr(status));
2136                         ret = False;
2137                 }
2138         }
2139
2140         return ret;
2141 }
2142
2143 static BOOL test_OpenUser(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2144                           struct policy_handle *handle, uint32_t rid)
2145 {
2146         NTSTATUS status;
2147         struct samr_OpenUser r;
2148         struct policy_handle user_handle;
2149         BOOL ret = True;
2150
2151         printf("Testing OpenUser(%u)\n", rid);
2152
2153         r.in.domain_handle = handle;
2154         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2155         r.in.rid = rid;
2156         r.out.user_handle = &user_handle;
2157
2158         status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
2159         if (!NT_STATUS_IS_OK(status)) {
2160                 printf("OpenUser(%u) failed - %s\n", rid, nt_errstr(status));
2161                 return False;
2162         }
2163
2164         if (!test_QuerySecurity(p, mem_ctx, &user_handle)) {
2165                 ret = False;
2166         }
2167
2168         if (!test_QueryUserInfo(p, mem_ctx, &user_handle)) {
2169                 ret = False;
2170         }
2171
2172         if (!test_QueryUserInfo2(p, mem_ctx, &user_handle)) {
2173                 ret = False;
2174         }
2175
2176         if (!test_GetUserPwInfo(p, mem_ctx, &user_handle)) {
2177                 ret = False;
2178         }
2179
2180         if (!test_GetGroupsForUser(p,mem_ctx, &user_handle)) {
2181                 ret = False;
2182         }
2183
2184         if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
2185                 ret = False;
2186         }
2187
2188         return ret;
2189 }
2190
2191 static BOOL test_OpenGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2192                            struct policy_handle *handle, uint32_t rid)
2193 {
2194         NTSTATUS status;
2195         struct samr_OpenGroup r;
2196         struct policy_handle group_handle;
2197         BOOL ret = True;
2198
2199         printf("Testing OpenGroup(%u)\n", rid);
2200
2201         r.in.domain_handle = handle;
2202         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2203         r.in.rid = rid;
2204         r.out.group_handle = &group_handle;
2205
2206         status = dcerpc_samr_OpenGroup(p, mem_ctx, &r);
2207         if (!NT_STATUS_IS_OK(status)) {
2208                 printf("OpenGroup(%u) failed - %s\n", rid, nt_errstr(status));
2209                 return False;
2210         }
2211
2212         if (!test_QuerySecurity(p, mem_ctx, &group_handle)) {
2213                 ret = False;
2214         }
2215
2216         if (!test_QueryGroupInfo(p, mem_ctx, &group_handle)) {
2217                 ret = False;
2218         }
2219
2220         if (!test_QueryGroupMember(p, mem_ctx, &group_handle)) {
2221                 ret = False;
2222         }
2223
2224         if (!test_samr_handle_Close(p, mem_ctx, &group_handle)) {
2225                 ret = False;
2226         }
2227
2228         return ret;
2229 }
2230
2231 static BOOL test_OpenAlias(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2232                            struct policy_handle *handle, uint32_t rid)
2233 {
2234         NTSTATUS status;
2235         struct samr_OpenAlias r;
2236         struct policy_handle alias_handle;
2237         BOOL ret = True;
2238
2239         printf("Testing OpenAlias(%u)\n", rid);
2240
2241         r.in.domain_handle = handle;
2242         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2243         r.in.rid = rid;
2244         r.out.alias_handle = &alias_handle;
2245
2246         status = dcerpc_samr_OpenAlias(p, mem_ctx, &r);
2247         if (!NT_STATUS_IS_OK(status)) {
2248                 printf("OpenAlias(%u) failed - %s\n", rid, nt_errstr(status));
2249                 return False;
2250         }
2251
2252         if (!test_QuerySecurity(p, mem_ctx, &alias_handle)) {
2253                 ret = False;
2254         }
2255
2256         if (!test_QueryAliasInfo(p, mem_ctx, &alias_handle)) {
2257                 ret = False;
2258         }
2259
2260         if (!test_GetMembersInAlias(p, mem_ctx, &alias_handle)) {
2261                 ret = False;
2262         }
2263
2264         if (!test_samr_handle_Close(p, mem_ctx, &alias_handle)) {
2265                 ret = False;
2266         }
2267
2268         return ret;
2269 }
2270
2271 static BOOL test_EnumDomainUsers(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2272                                  struct policy_handle *handle)
2273 {
2274         NTSTATUS status;
2275         struct samr_EnumDomainUsers r;
2276         uint32_t resume_handle=0;
2277         int i;
2278         BOOL ret = True;
2279         struct samr_LookupNames n;
2280         struct samr_LookupRids  lr ;
2281
2282         printf("Testing EnumDomainUsers\n");
2283
2284         r.in.domain_handle = handle;
2285         r.in.resume_handle = &resume_handle;
2286         r.in.acct_flags = 0;
2287         r.in.max_size = (uint32_t)-1;
2288         r.out.resume_handle = &resume_handle;
2289
2290         status = dcerpc_samr_EnumDomainUsers(p, mem_ctx, &r);
2291         if (!NT_STATUS_IS_OK(status)) {
2292                 printf("EnumDomainUsers failed - %s\n", nt_errstr(status));
2293                 return False;
2294         }
2295         
2296         if (!r.out.sam) {
2297                 return False;
2298         }
2299
2300         if (r.out.sam->count == 0) {
2301                 return True;
2302         }
2303
2304         for (i=0;i<r.out.sam->count;i++) {
2305                 if (!test_OpenUser(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
2306                         ret = False;
2307                 }
2308         }
2309
2310         printf("Testing LookupNames\n");
2311         n.in.domain_handle = handle;
2312         n.in.num_names = r.out.sam->count;
2313         n.in.names = talloc_array(mem_ctx, struct lsa_String, r.out.sam->count);
2314         for (i=0;i<r.out.sam->count;i++) {
2315                 n.in.names[i].string = r.out.sam->entries[i].name.string;
2316         }
2317         status = dcerpc_samr_LookupNames(p, mem_ctx, &n);
2318         if (!NT_STATUS_IS_OK(status)) {
2319                 printf("LookupNames failed - %s\n", nt_errstr(status));
2320                 ret = False;
2321         }
2322
2323
2324         printf("Testing LookupRids\n");
2325         lr.in.domain_handle = handle;
2326         lr.in.num_rids = r.out.sam->count;
2327         lr.in.rids = talloc_array(mem_ctx, uint32_t, r.out.sam->count);
2328         for (i=0;i<r.out.sam->count;i++) {
2329                 lr.in.rids[i] = r.out.sam->entries[i].idx;
2330         }
2331         status = dcerpc_samr_LookupRids(p, mem_ctx, &lr);
2332         if (!NT_STATUS_IS_OK(status)) {
2333                 printf("LookupRids failed - %s\n", nt_errstr(status));
2334                 ret = False;
2335         }
2336
2337         return ret;     
2338 }
2339
2340 /*
2341   try blasting the server with a bunch of sync requests
2342 */
2343 static BOOL test_EnumDomainUsers_async(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2344                                        struct policy_handle *handle)
2345 {
2346         NTSTATUS status;
2347         struct samr_EnumDomainUsers r;
2348         uint32_t resume_handle=0;
2349         int i;
2350 #define ASYNC_COUNT 100
2351         struct rpc_request *req[ASYNC_COUNT];
2352
2353         if (!lp_parm_bool(-1, "torture", "dangerous", False)) {
2354                 printf("samr async test disabled - enable dangerous tests to use\n");
2355                 return True;
2356         }
2357
2358         printf("Testing EnumDomainUsers_async\n");
2359
2360         r.in.domain_handle = handle;
2361         r.in.resume_handle = &resume_handle;
2362         r.in.acct_flags = 0;
2363         r.in.max_size = (uint32_t)-1;
2364         r.out.resume_handle = &resume_handle;
2365
2366         for (i=0;i<ASYNC_COUNT;i++) {
2367                 req[i] = dcerpc_samr_EnumDomainUsers_send(p, mem_ctx, &r);
2368         }
2369
2370         for (i=0;i<ASYNC_COUNT;i++) {
2371                 status = dcerpc_ndr_request_recv(req[i]);
2372                 if (!NT_STATUS_IS_OK(status)) {
2373                         printf("EnumDomainUsers[%d] failed - %s\n", 
2374                                i, nt_errstr(status));
2375                         return False;
2376                 }
2377         }
2378         
2379         printf("%d async requests OK\n", i);
2380
2381         return True;
2382 }
2383
2384 static BOOL test_EnumDomainGroups(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2385                                   struct policy_handle *handle)
2386 {
2387         NTSTATUS status;
2388         struct samr_EnumDomainGroups r;
2389         uint32_t resume_handle=0;
2390         int i;
2391         BOOL ret = True;
2392
2393         printf("Testing EnumDomainGroups\n");
2394
2395         r.in.domain_handle = handle;
2396         r.in.resume_handle = &resume_handle;
2397         r.in.max_size = (uint32_t)-1;
2398         r.out.resume_handle = &resume_handle;
2399
2400         status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &r);
2401         if (!NT_STATUS_IS_OK(status)) {
2402                 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
2403                 return False;
2404         }
2405         
2406         if (!r.out.sam) {
2407                 return False;
2408         }
2409
2410         for (i=0;i<r.out.sam->count;i++) {
2411                 if (!test_OpenGroup(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
2412                         ret = False;
2413                 }
2414         }
2415
2416         return ret;
2417 }
2418
2419 static BOOL test_EnumDomainAliases(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2420                                    struct policy_handle *handle)
2421 {
2422         NTSTATUS status;
2423         struct samr_EnumDomainAliases r;
2424         uint32_t resume_handle=0;
2425         int i;
2426         BOOL ret = True;
2427
2428         printf("Testing EnumDomainAliases\n");
2429
2430         r.in.domain_handle = handle;
2431         r.in.resume_handle = &resume_handle;
2432         r.in.acct_flags = (uint32_t)-1;
2433         r.out.resume_handle = &resume_handle;
2434
2435         status = dcerpc_samr_EnumDomainAliases(p, mem_ctx, &r);
2436         if (!NT_STATUS_IS_OK(status)) {
2437                 printf("EnumDomainAliases failed - %s\n", nt_errstr(status));
2438                 return False;
2439         }
2440         
2441         if (!r.out.sam) {
2442                 return False;
2443         }
2444
2445         for (i=0;i<r.out.sam->count;i++) {
2446                 if (!test_OpenAlias(p, mem_ctx, handle, r.out.sam->entries[i].idx)) {
2447                         ret = False;
2448                 }
2449         }
2450
2451         return ret;     
2452 }
2453
2454 static BOOL test_GetDisplayEnumerationIndex(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2455                                             struct policy_handle *handle)
2456 {
2457         NTSTATUS status;
2458         struct samr_GetDisplayEnumerationIndex r;
2459         BOOL ret = True;
2460         uint16_t levels[] = {1, 2, 3, 4, 5};
2461         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
2462         int i;
2463
2464         for (i=0;i<ARRAY_SIZE(levels);i++) {
2465                 printf("Testing GetDisplayEnumerationIndex level %u\n", levels[i]);
2466
2467                 r.in.domain_handle = handle;
2468                 r.in.level = levels[i];
2469                 init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME);
2470
2471                 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
2472
2473                 if (ok_lvl[i] && 
2474                     !NT_STATUS_IS_OK(status) &&
2475                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
2476                         printf("GetDisplayEnumerationIndex level %u failed - %s\n", 
2477                                levels[i], nt_errstr(status));
2478                         ret = False;
2479                 }
2480
2481                 init_lsa_String(&r.in.name, "zzzzzzzz");
2482
2483                 status = dcerpc_samr_GetDisplayEnumerationIndex(p, mem_ctx, &r);
2484                 
2485                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
2486                         printf("GetDisplayEnumerationIndex level %u failed - %s\n", 
2487                                levels[i], nt_errstr(status));
2488                         ret = False;
2489                 }
2490         }
2491         
2492         return ret;     
2493 }
2494
2495 static BOOL test_GetDisplayEnumerationIndex2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2496                                              struct policy_handle *handle)
2497 {
2498         NTSTATUS status;
2499         struct samr_GetDisplayEnumerationIndex2 r;
2500         BOOL ret = True;
2501         uint16_t levels[] = {1, 2, 3, 4, 5};
2502         uint16_t ok_lvl[] = {1, 1, 1, 0, 0};
2503         int i;
2504
2505         for (i=0;i<ARRAY_SIZE(levels);i++) {
2506                 printf("Testing GetDisplayEnumerationIndex2 level %u\n", levels[i]);
2507
2508                 r.in.domain_handle = handle;
2509                 r.in.level = levels[i];
2510                 init_lsa_String(&r.in.name, TEST_ACCOUNT_NAME);
2511
2512                 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
2513                 if (ok_lvl[i] && 
2514                     !NT_STATUS_IS_OK(status) && 
2515                     !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
2516                         printf("GetDisplayEnumerationIndex2 level %u failed - %s\n", 
2517                                levels[i], nt_errstr(status));
2518                         ret = False;
2519                 }
2520
2521                 init_lsa_String(&r.in.name, "zzzzzzzz");
2522
2523                 status = dcerpc_samr_GetDisplayEnumerationIndex2(p, mem_ctx, &r);
2524                 if (ok_lvl[i] && !NT_STATUS_EQUAL(NT_STATUS_NO_MORE_ENTRIES, status)) {
2525                         printf("GetDisplayEnumerationIndex2 level %u failed - %s\n", 
2526                                levels[i], nt_errstr(status));
2527                         ret = False;
2528                 }
2529         }
2530         
2531         return ret;     
2532 }
2533
2534 static BOOL test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2535                                   struct policy_handle *handle)
2536 {
2537         NTSTATUS status;
2538         struct samr_QueryDisplayInfo r;
2539         BOOL ret = True;
2540         uint16_t levels[] = {1, 2, 3, 4, 5};
2541         int i;
2542
2543         for (i=0;i<ARRAY_SIZE(levels);i++) {
2544                 printf("Testing QueryDisplayInfo level %u\n", levels[i]);
2545
2546                 r.in.domain_handle = handle;
2547                 r.in.level = levels[i];
2548                 r.in.start_idx = 0;
2549                 r.in.max_entries = 1000;
2550                 r.in.buf_size = (uint32_t)-1;
2551
2552                 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
2553                 if (!NT_STATUS_IS_OK(status)) {
2554                         printf("QueryDisplayInfo level %u failed - %s\n", 
2555                                levels[i], nt_errstr(status));
2556                         ret = False;
2557                 }
2558         }
2559         
2560         return ret;     
2561 }
2562
2563 static BOOL test_QueryDisplayInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2564                                   struct policy_handle *handle)
2565 {
2566         NTSTATUS status;
2567         struct samr_QueryDisplayInfo2 r;
2568         BOOL ret = True;
2569         uint16_t levels[] = {1, 2, 3, 4, 5};
2570         int i;
2571
2572         for (i=0;i<ARRAY_SIZE(levels);i++) {
2573                 printf("Testing QueryDisplayInfo2 level %u\n", levels[i]);
2574
2575                 r.in.domain_handle = handle;
2576                 r.in.level = levels[i];
2577                 r.in.start_idx = 0;
2578                 r.in.max_entries = 1000;
2579                 r.in.buf_size = (uint32_t)-1;
2580
2581                 status = dcerpc_samr_QueryDisplayInfo2(p, mem_ctx, &r);
2582                 if (!NT_STATUS_IS_OK(status)) {
2583                         printf("QueryDisplayInfo2 level %u failed - %s\n", 
2584                                levels[i], nt_errstr(status));
2585                         ret = False;
2586                 }
2587         }
2588         
2589         return ret;     
2590 }
2591
2592 static BOOL test_QueryDisplayInfo3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2593                                   struct policy_handle *handle)
2594 {
2595         NTSTATUS status;
2596         struct samr_QueryDisplayInfo3 r;
2597         BOOL ret = True;
2598         uint16_t levels[] = {1, 2, 3, 4, 5};
2599         int i;
2600
2601         for (i=0;i<ARRAY_SIZE(levels);i++) {
2602                 printf("Testing QueryDisplayInfo3 level %u\n", levels[i]);
2603
2604                 r.in.domain_handle = handle;
2605                 r.in.level = levels[i];
2606                 r.in.start_idx = 0;
2607                 r.in.max_entries = 1000;
2608                 r.in.buf_size = (uint32_t)-1;
2609
2610                 status = dcerpc_samr_QueryDisplayInfo3(p, mem_ctx, &r);
2611                 if (!NT_STATUS_IS_OK(status)) {
2612                         printf("QueryDisplayInfo3 level %u failed - %s\n", 
2613                                levels[i], nt_errstr(status));
2614                         ret = False;
2615                 }
2616         }
2617         
2618         return ret;     
2619 }
2620
2621
2622 static BOOL test_QueryDisplayInfo_continue(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2623                                            struct policy_handle *handle)
2624 {
2625         NTSTATUS status;
2626         struct samr_QueryDisplayInfo r;
2627         BOOL ret = True;
2628
2629         printf("Testing QueryDisplayInfo continuation\n");
2630
2631         r.in.domain_handle = handle;
2632         r.in.level = 1;
2633         r.in.start_idx = 0;
2634         r.in.max_entries = 1;
2635         r.in.buf_size = (uint32_t)-1;
2636
2637         do {
2638                 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &r);
2639                 if (NT_STATUS_IS_OK(status) && r.out.returned_size != 0) {
2640                         if (r.out.info.info1.entries[0].idx != r.in.start_idx + 1) {
2641                                 printf("expected idx %d but got %d\n",
2642                                        r.in.start_idx + 1,
2643                                        r.out.info.info1.entries[0].idx);
2644                                 break;
2645                         }
2646                 }
2647                 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) &&
2648                     !NT_STATUS_IS_OK(status)) {
2649                         printf("QueryDisplayInfo level %u failed - %s\n", 
2650                                r.in.level, nt_errstr(status));
2651                         ret = False;
2652                         break;
2653                 }
2654                 r.in.start_idx++;
2655         } while ((NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) ||
2656                   NT_STATUS_IS_OK(status)) &&
2657                  r.out.returned_size != 0);
2658         
2659         return ret;     
2660 }
2661
2662 static BOOL test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2663                                  struct policy_handle *handle)
2664 {
2665         NTSTATUS status;
2666         struct samr_QueryDomainInfo r;
2667         struct samr_SetDomainInfo s;
2668         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
2669         uint16_t set_ok[] = {1, 0, 1, 1, 0, 1, 1, 0, 1,  0,  1,  0};
2670         int i;
2671         BOOL ret = True;
2672         const char *domain_comment = talloc_asprintf(mem_ctx, 
2673                                   "Tortured by Samba4 RPC-SAMR: %s", 
2674                                   timestring(mem_ctx, time(NULL)));
2675
2676         s.in.domain_handle = handle;
2677         s.in.level = 4;
2678         s.in.info = talloc(mem_ctx, union samr_DomainInfo);
2679         
2680         s.in.info->info4.comment.string = domain_comment;
2681         status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
2682         if (!NT_STATUS_IS_OK(status)) {
2683                 printf("SetDomainInfo level %u (set comment) failed - %s\n", 
2684                        r.in.level, nt_errstr(status));
2685                 return False;
2686         }
2687
2688         for (i=0;i<ARRAY_SIZE(levels);i++) {
2689                 printf("Testing QueryDomainInfo level %u\n", levels[i]);
2690
2691                 r.in.domain_handle = handle;
2692                 r.in.level = levels[i];
2693
2694                 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
2695                 if (!NT_STATUS_IS_OK(status)) {
2696                         printf("QueryDomainInfo level %u failed - %s\n", 
2697                                r.in.level, nt_errstr(status));
2698                         ret = False;
2699                         continue;
2700                 }
2701
2702                 switch (levels[i]) {
2703                 case 2:
2704                         if (strcmp(r.out.info->info2.comment.string, domain_comment) != 0) {
2705                                 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
2706                                        levels[i], r.out.info->info2.comment.string, domain_comment);
2707                                 ret = False;
2708                         }
2709                         break;
2710                 case 4:
2711                         if (strcmp(r.out.info->info4.comment.string, domain_comment) != 0) {
2712                                 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
2713                                        levels[i], r.out.info->info4.comment.string, domain_comment);
2714                                 ret = False;
2715                         }
2716                         break;
2717                 case 11:
2718                         if (strcmp(r.out.info->info11.info2.comment.string, domain_comment) != 0) {
2719                                 printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
2720                                        levels[i], r.out.info->info11.info2.comment.string, domain_comment);
2721                                 ret = False;
2722                         }
2723                         break;
2724                 }
2725
2726                 printf("Testing SetDomainInfo level %u\n", levels[i]);
2727
2728                 s.in.domain_handle = handle;
2729                 s.in.level = levels[i];
2730                 s.in.info = r.out.info;
2731
2732                 status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
2733                 if (set_ok[i]) {
2734                         if (!NT_STATUS_IS_OK(status)) {
2735                                 printf("SetDomainInfo level %u failed - %s\n", 
2736                                        r.in.level, nt_errstr(status));
2737                                 ret = False;
2738                                 continue;
2739                         }
2740                 } else {
2741                         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_INFO_CLASS, status)) {
2742                                 printf("SetDomainInfo level %u gave %s - should have been NT_STATUS_INVALID_INFO_CLASS\n", 
2743                                        r.in.level, nt_errstr(status));
2744                                 ret = False;
2745                                 continue;
2746                         }
2747                 }
2748
2749                 status = dcerpc_samr_QueryDomainInfo(p, mem_ctx, &r);
2750                 if (!NT_STATUS_IS_OK(status)) {
2751                         printf("QueryDomainInfo level %u failed - %s\n", 
2752                                r.in.level, nt_errstr(status));
2753                         ret = False;
2754                         continue;
2755                 }
2756         }
2757
2758         return True;    
2759 }
2760
2761
2762 static BOOL test_QueryDomainInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2763                                   struct policy_handle *handle)
2764 {
2765         NTSTATUS status;
2766         struct samr_QueryDomainInfo2 r;
2767         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13};
2768         int i;
2769         BOOL ret = True;
2770
2771         for (i=0;i<ARRAY_SIZE(levels);i++) {
2772                 printf("Testing QueryDomainInfo2 level %u\n", levels[i]);
2773
2774                 r.in.domain_handle = handle;
2775                 r.in.level = levels[i];
2776
2777                 status = dcerpc_samr_QueryDomainInfo2(p, mem_ctx, &r);
2778                 if (!NT_STATUS_IS_OK(status)) {
2779                         printf("QueryDomainInfo2 level %u failed - %s\n", 
2780                                r.in.level, nt_errstr(status));
2781                         ret = False;
2782                         continue;
2783                 }
2784         }
2785
2786         return True;    
2787 }
2788
2789 /* Test whether querydispinfo level 5 and enumdomgroups return the same
2790    set of group names. */
2791 static BOOL test_GroupList(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2792                            struct policy_handle *handle)
2793 {
2794         struct samr_EnumDomainGroups q1;
2795         struct samr_QueryDisplayInfo q2;
2796         NTSTATUS status;
2797         uint32_t resume_handle=0;
2798         int i;
2799         BOOL ret = True;
2800
2801         int num_names = 0;
2802         const char **names = NULL;
2803
2804         printf("Testing coherency of querydispinfo vs enumdomgroups\n");
2805
2806         q1.in.domain_handle = handle;
2807         q1.in.resume_handle = &resume_handle;
2808         q1.in.max_size = 5;
2809         q1.out.resume_handle = &resume_handle;
2810
2811         status = STATUS_MORE_ENTRIES;
2812         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2813                 status = dcerpc_samr_EnumDomainGroups(p, mem_ctx, &q1);
2814
2815                 if (!NT_STATUS_IS_OK(status) &&
2816                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2817                         break;
2818
2819                 for (i=0; i<q1.out.num_entries; i++) {
2820                         add_string_to_array(mem_ctx,
2821                                             q1.out.sam->entries[i].name.string,
2822                                             &names, &num_names);
2823                 }
2824         }
2825
2826         if (!NT_STATUS_IS_OK(status)) {
2827                 printf("EnumDomainGroups failed - %s\n", nt_errstr(status));
2828                 return False;
2829         }
2830         
2831         if (!q1.out.sam) {
2832                 return False;
2833         }
2834
2835         q2.in.domain_handle = handle;
2836         q2.in.level = 5;
2837         q2.in.start_idx = 0;
2838         q2.in.max_entries = 5;
2839         q2.in.buf_size = (uint32_t)-1;
2840
2841         status = STATUS_MORE_ENTRIES;
2842         while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2843                 status = dcerpc_samr_QueryDisplayInfo(p, mem_ctx, &q2);
2844
2845                 if (!NT_STATUS_IS_OK(status) &&
2846                     !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2847                         break;
2848
2849                 for (i=0; i<q2.out.info.info5.count; i++) {
2850                         int j;
2851                         const char *name = q2.out.info.info5.entries[i].account_name.string;
2852                         BOOL found = False;
2853                         for (j=0; j<num_names; j++) {
2854                                 if (names[j] == NULL)
2855                                         continue;
2856                                 /* Hmm. No strequal in samba4 */
2857                                 if (strequal(names[j], name)) {
2858                                         names[j] = NULL;
2859                                         found = True;
2860                                         break;
2861                                 }
2862                         }
2863
2864                         if (!found) {
2865                                 printf("QueryDisplayInfo gave name [%s] that EnumDomainGroups did not\n",
2866                                        name);
2867                                 ret = False;
2868                         }
2869                 }
2870                 q2.in.start_idx += q2.out.info.info5.count;
2871         }
2872
2873         if (!NT_STATUS_IS_OK(status)) {
2874                 printf("QueryDisplayInfo level 5 failed - %s\n",
2875                        nt_errstr(status));
2876                 ret = False;
2877         }
2878
2879         for (i=0; i<num_names; i++) {
2880                 if (names[i] != NULL) {
2881                         printf("EnumDomainGroups gave name [%s] that QueryDisplayInfo did not\n",
2882                                names[i]);
2883                         ret = False;
2884                 }
2885         }
2886
2887         return ret;
2888 }
2889
2890 static BOOL test_DeleteDomainGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2891                                    struct policy_handle *group_handle)
2892 {
2893         struct samr_DeleteDomainGroup d;
2894         NTSTATUS status;
2895         BOOL ret = True;
2896
2897         printf("Testing DeleteDomainGroup\n");
2898
2899         d.in.group_handle = group_handle;
2900         d.out.group_handle = group_handle;
2901
2902         status = dcerpc_samr_DeleteDomainGroup(p, mem_ctx, &d);
2903         if (!NT_STATUS_IS_OK(status)) {
2904                 printf("DeleteDomainGroup failed - %s\n", nt_errstr(status));
2905                 ret = False;
2906         }
2907
2908         return ret;
2909 }
2910
2911 static BOOL test_TestPrivateFunctionsDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2912                                             struct policy_handle *domain_handle)
2913 {
2914         struct samr_TestPrivateFunctionsDomain r;
2915         NTSTATUS status;
2916         BOOL ret = True;
2917
2918         printf("Testing TestPrivateFunctionsDomain\n");
2919
2920         r.in.domain_handle = domain_handle;
2921
2922         status = dcerpc_samr_TestPrivateFunctionsDomain(p, mem_ctx, &r);
2923         if (!NT_STATUS_EQUAL(NT_STATUS_NOT_IMPLEMENTED, status)) {
2924                 printf("TestPrivateFunctionsDomain failed - %s\n", nt_errstr(status));
2925                 ret = False;
2926         }
2927
2928         return ret;
2929 }
2930
2931 static BOOL test_RidToSid(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2932                           struct dom_sid *domain_sid,
2933                           struct policy_handle *domain_handle)
2934 {
2935         struct samr_RidToSid r;
2936         NTSTATUS status;
2937         BOOL ret = True;
2938         struct dom_sid *calc_sid;
2939         int rids[] = { 0, 42, 512, 10200 };
2940         int i;
2941
2942         for (i=0;i<ARRAY_SIZE(rids);i++) {
2943         
2944                 printf("Testing RidToSid\n");
2945                 
2946                 calc_sid = dom_sid_dup(mem_ctx, domain_sid);
2947                 r.in.domain_handle = domain_handle;
2948                 r.in.rid = rids[i];
2949                 
2950                 status = dcerpc_samr_RidToSid(p, mem_ctx, &r);
2951                 if (!NT_STATUS_IS_OK(status)) {
2952                         printf("RidToSid for %d failed - %s\n", rids[i], nt_errstr(status));
2953                         ret = False;
2954                 } else {
2955                         calc_sid = dom_sid_add_rid(calc_sid, calc_sid, rids[i]);
2956
2957                         if (!dom_sid_equal(calc_sid, r.out.sid)) {
2958                                 printf("RidToSid for %d failed - got %s, expected %s\n", rids[i], 
2959                                        dom_sid_string(mem_ctx, r.out.sid), 
2960                                        dom_sid_string(mem_ctx, calc_sid));
2961                                 ret = False;
2962                         }
2963                 }
2964         }
2965
2966         return ret;
2967 }
2968
2969 static BOOL test_GetBootKeyInformation(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
2970                                        struct policy_handle *domain_handle)
2971 {
2972         struct samr_GetBootKeyInformation r;
2973         NTSTATUS status;
2974         BOOL ret = True;
2975
2976         printf("Testing GetBootKeyInformation\n");
2977
2978         r.in.domain_handle = domain_handle;
2979
2980         status = dcerpc_samr_GetBootKeyInformation(p, mem_ctx, &r);
2981         if (!NT_STATUS_IS_OK(status)) {
2982                 /* w2k3 seems to fail this sometimes and pass it sometimes */
2983                 printf("GetBootKeyInformation (ignored) - %s\n", nt_errstr(status));
2984         }
2985
2986         return ret;
2987 }
2988
2989 static BOOL test_AddGroupMember(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
2990                                 struct policy_handle *domain_handle,
2991                                 struct policy_handle *group_handle)
2992 {
2993         NTSTATUS status;
2994         struct samr_AddGroupMember r;
2995         struct samr_DeleteGroupMember d;
2996         struct samr_QueryGroupMember q;
2997         struct samr_SetMemberAttributesOfGroup s;
2998         BOOL ret = True;
2999         uint32_t rid;
3000
3001         status = test_LookupName(p, mem_ctx, domain_handle, TEST_ACCOUNT_NAME, &rid);
3002         if (!NT_STATUS_IS_OK(status)) {
3003                 return False;
3004         }
3005
3006         r.in.group_handle = group_handle;
3007         r.in.rid = rid;
3008         r.in.flags = 0; /* ??? */
3009
3010         printf("Testing AddGroupMember and DeleteGroupMember\n");
3011
3012         d.in.group_handle = group_handle;
3013         d.in.rid = rid;
3014
3015         status = dcerpc_samr_DeleteGroupMember(p, mem_ctx, &d);
3016         if (!NT_STATUS_EQUAL(NT_STATUS_MEMBER_NOT_IN_GROUP, status)) {
3017                 printf("DeleteGroupMember gave %s - should be NT_STATUS_MEMBER_NOT_IN_GROUP\n", 
3018                        nt_errstr(status));
3019                 return False;
3020         }
3021
3022         status = dcerpc_samr_AddGroupMember(p, mem_ctx, &r);
3023         if (!NT_STATUS_IS_OK(status)) {
3024                 printf("AddGroupMember failed - %s\n", nt_errstr(status));
3025                 return False;
3026         }
3027
3028         status = dcerpc_samr_AddGroupMember(p, mem_ctx, &r);
3029         if (!NT_STATUS_EQUAL(NT_STATUS_MEMBER_IN_GROUP, status)) {
3030                 printf("AddGroupMember gave %s - should be NT_STATUS_MEMBER_IN_GROUP\n", 
3031                        nt_errstr(status));
3032                 return False;
3033         }
3034
3035         if (lp_parm_bool(-1, "target", "samba4", False)) {
3036                 printf("skipping SetMemberAttributesOfGroup test against Samba4\n");
3037         } else {
3038                 /* this one is quite strange. I am using random inputs in the
3039                    hope of triggering an error that might give us a clue */
3040
3041                 s.in.group_handle = group_handle;
3042                 s.in.unknown1 = random();
3043                 s.in.unknown2 = random();
3044
3045                 status = dcerpc_samr_SetMemberAttributesOfGroup(p, mem_ctx, &s);
3046                 if (!NT_STATUS_IS_OK(status)) {
3047                         printf("SetMemberAttributesOfGroup failed - %s\n", nt_errstr(status));
3048                         return False;
3049                 }
3050         }
3051
3052         q.in.group_handle = group_handle;
3053
3054         status = dcerpc_samr_QueryGroupMember(p, mem_ctx, &q);
3055         if (!NT_STATUS_IS_OK(status)) {
3056                 printf("QueryGroupMember failed - %s\n", nt_errstr(status));
3057                 return False;
3058         }
3059
3060         status = dcerpc_samr_DeleteGroupMember(p, mem_ctx, &d);
3061         if (!NT_STATUS_IS_OK(status)) {
3062                 printf("DeleteGroupMember failed - %s\n", nt_errstr(status));
3063                 return False;
3064         }
3065
3066         status = dcerpc_samr_AddGroupMember(p, mem_ctx, &r);
3067         if (!NT_STATUS_IS_OK(status)) {
3068                 printf("AddGroupMember failed - %s\n", nt_errstr(status));
3069                 return False;
3070         }
3071
3072         return ret;
3073 }
3074
3075
3076 static BOOL test_CreateDomainGroup(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3077                                    struct policy_handle *domain_handle, struct policy_handle *group_handle)
3078 {
3079         NTSTATUS status;
3080         struct samr_CreateDomainGroup r;
3081         uint32_t rid;
3082         struct lsa_String name;
3083         BOOL ret = True;
3084
3085         init_lsa_String(&name, TEST_GROUPNAME);
3086
3087         r.in.domain_handle = domain_handle;
3088         r.in.name = &name;
3089         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3090         r.out.group_handle = group_handle;
3091         r.out.rid = &rid;
3092
3093         printf("Testing CreateDomainGroup(%s)\n", r.in.name->string);
3094
3095         status = dcerpc_samr_CreateDomainGroup(p, mem_ctx, &r);
3096
3097         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
3098                 printf("Server refused create of '%s'\n", r.in.name->string);
3099                 ZERO_STRUCTP(group_handle);
3100                 return True;
3101         }
3102
3103         if (NT_STATUS_EQUAL(status, NT_STATUS_GROUP_EXISTS) ||
3104             NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
3105                 if (!test_DeleteGroup_byname(p, mem_ctx, domain_handle, r.in.name->string)) {
3106                         return False;
3107                 }
3108                 status = dcerpc_samr_CreateDomainGroup(p, mem_ctx, &r);
3109         }
3110         if (!NT_STATUS_IS_OK(status)) {
3111                 printf("CreateDomainGroup failed - %s\n", nt_errstr(status));
3112                 return False;
3113         }
3114
3115         if (!test_AddGroupMember(p, mem_ctx, domain_handle, group_handle)) {
3116                 ret = False;
3117         }
3118
3119         if (!test_SetGroupInfo(p, mem_ctx, group_handle)) {
3120                 ret = False;
3121         }
3122
3123         return ret;
3124 }
3125
3126
3127 /*
3128   its not totally clear what this does. It seems to accept any sid you like.
3129 */
3130 static BOOL test_RemoveMemberFromForeignDomain(struct dcerpc_pipe *p, 
3131                                                TALLOC_CTX *mem_ctx, 
3132                                                struct policy_handle *domain_handle)
3133 {
3134         NTSTATUS status;
3135         struct samr_RemoveMemberFromForeignDomain r;
3136
3137         r.in.domain_handle = domain_handle;
3138         r.in.sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-12-34-56-78");
3139
3140         status = dcerpc_samr_RemoveMemberFromForeignDomain(p, mem_ctx, &r);
3141         if (!NT_STATUS_IS_OK(status)) {
3142                 printf("RemoveMemberFromForeignDomain failed - %s\n", nt_errstr(status));
3143                 return False;
3144         }
3145
3146         return True;
3147 }
3148
3149
3150
3151 static BOOL test_Connect(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3152                          struct policy_handle *handle);
3153
3154 static BOOL test_OpenDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3155                             struct policy_handle *handle, struct dom_sid *sid)
3156 {
3157         NTSTATUS status;
3158         struct samr_OpenDomain r;
3159         struct policy_handle domain_handle;
3160         struct policy_handle user_handle;
3161         struct policy_handle alias_handle;
3162         struct policy_handle group_handle;
3163         BOOL ret = True;
3164
3165         ZERO_STRUCT(user_handle);
3166         ZERO_STRUCT(alias_handle);
3167         ZERO_STRUCT(group_handle);
3168         ZERO_STRUCT(domain_handle);
3169
3170         printf("Testing OpenDomain\n");
3171
3172         r.in.connect_handle = handle;
3173         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3174         r.in.sid = sid;
3175         r.out.domain_handle = &domain_handle;
3176
3177         status = dcerpc_samr_OpenDomain(p, mem_ctx, &r);
3178         if (!NT_STATUS_IS_OK(status)) {
3179                 printf("OpenDomain failed - %s\n", nt_errstr(status));
3180                 return False;
3181         }
3182
3183         /* run the domain tests with the main handle closed - this tests
3184            the servers reference counting */
3185         ret &= test_samr_handle_Close(p, mem_ctx, handle);
3186
3187         ret &= test_QuerySecurity(p, mem_ctx, &domain_handle);
3188         ret &= test_RemoveMemberFromForeignDomain(p, mem_ctx, &domain_handle);
3189         ret &= test_CreateUser2(p, mem_ctx, &domain_handle);
3190         ret &= test_CreateUser(p, mem_ctx, &domain_handle, &user_handle);
3191         ret &= test_CreateAlias(p, mem_ctx, &domain_handle, &alias_handle, sid);
3192         ret &= test_CreateDomainGroup(p, mem_ctx, &domain_handle, &group_handle);
3193         ret &= test_QueryDomainInfo(p, mem_ctx, &domain_handle);
3194         ret &= test_QueryDomainInfo2(p, mem_ctx, &domain_handle);
3195         ret &= test_EnumDomainUsers(p, mem_ctx, &domain_handle);
3196         ret &= test_EnumDomainUsers_async(p, mem_ctx, &domain_handle);
3197         ret &= test_EnumDomainGroups(p, mem_ctx, &domain_handle);
3198         ret &= test_EnumDomainAliases(p, mem_ctx, &domain_handle);
3199         ret &= test_QueryDisplayInfo(p, mem_ctx, &domain_handle);
3200         ret &= test_QueryDisplayInfo2(p, mem_ctx, &domain_handle);
3201         ret &= test_QueryDisplayInfo3(p, mem_ctx, &domain_handle);
3202         ret &= test_QueryDisplayInfo_continue(p, mem_ctx, &domain_handle);
3203         
3204         if (lp_parm_bool(-1, "target", "samba4", False)) {
3205                 printf("skipping GetDisplayEnumerationIndex test against Samba4\n");
3206         } else {
3207                 ret &= test_GetDisplayEnumerationIndex(p, mem_ctx, &domain_handle);
3208                 ret &= test_GetDisplayEnumerationIndex2(p, mem_ctx, &domain_handle);
3209         }
3210         ret &= test_GroupList(p, mem_ctx, &domain_handle);
3211         ret &= test_TestPrivateFunctionsDomain(p, mem_ctx, &domain_handle);
3212         ret &= test_RidToSid(p, mem_ctx, sid, &domain_handle);
3213         ret &= test_GetBootKeyInformation(p, mem_ctx, &domain_handle);
3214
3215         if (!policy_handle_empty(&user_handle) &&
3216             !test_DeleteUser(p, mem_ctx, &user_handle)) {
3217                 ret = False;
3218         }
3219
3220         if (!policy_handle_empty(&alias_handle) &&
3221             !test_DeleteAlias(p, mem_ctx, &alias_handle)) {
3222                 ret = False;
3223         }
3224
3225         if (!policy_handle_empty(&group_handle) &&
3226             !test_DeleteDomainGroup(p, mem_ctx, &group_handle)) {
3227                 ret = False;
3228         }
3229
3230         ret &= test_samr_handle_Close(p, mem_ctx, &domain_handle);
3231
3232         /* reconnect the main handle */
3233         ret &= test_Connect(p, mem_ctx, handle);
3234
3235         return ret;
3236 }
3237
3238 static BOOL test_LookupDomain(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3239                               struct policy_handle *handle, struct lsa_String *domain)
3240 {
3241         NTSTATUS status;
3242         struct samr_LookupDomain r;
3243         struct lsa_String n2;
3244         BOOL ret = True;
3245
3246         printf("Testing LookupDomain(%s)\n", domain->string);
3247
3248         /* check for correct error codes */
3249         r.in.connect_handle = handle;
3250         r.in.domain_name = &n2;
3251         n2.string = NULL;
3252
3253         status = dcerpc_samr_LookupDomain(p, mem_ctx, &r);
3254         if (!NT_STATUS_EQUAL(NT_STATUS_INVALID_PARAMETER, status)) {
3255                 printf("failed: LookupDomain expected NT_STATUS_INVALID_PARAMETER - %s\n", nt_errstr(status));
3256                 ret = False;
3257         }
3258
3259         n2.string = "xxNODOMAINxx";
3260
3261         status = dcerpc_samr_LookupDomain(p, mem_ctx, &r);
3262         if (!NT_STATUS_EQUAL(NT_STATUS_NO_SUCH_DOMAIN, status)) {
3263                 printf("failed: LookupDomain expected NT_STATUS_NO_SUCH_DOMAIN - %s\n", nt_errstr(status));
3264                 ret = False;
3265         }
3266
3267         r.in.connect_handle = handle;
3268         r.in.domain_name = domain;
3269
3270         status = dcerpc_samr_LookupDomain(p, mem_ctx, &r);
3271         if (!NT_STATUS_IS_OK(status)) {
3272                 printf("LookupDomain failed - %s\n", nt_errstr(status));
3273                 ret = False;
3274         }
3275
3276         if (!test_GetDomPwInfo(p, mem_ctx, domain)) {
3277                 ret = False;
3278         }
3279
3280         if (!test_OpenDomain(p, mem_ctx, handle, r.out.sid)) {
3281                 ret = False;
3282         }
3283
3284         return ret;
3285 }
3286
3287
3288 static BOOL test_EnumDomains(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3289                              struct policy_handle *handle)
3290 {
3291         NTSTATUS status;
3292         struct samr_EnumDomains r;
3293         uint32_t resume_handle = 0;
3294         int i;
3295         BOOL ret = True;
3296
3297         r.in.connect_handle = handle;
3298         r.in.resume_handle = &resume_handle;
3299         r.in.buf_size = (uint32_t)-1;
3300         r.out.resume_handle = &resume_handle;
3301
3302         status = dcerpc_samr_EnumDomains(p, mem_ctx, &r);
3303         if (!NT_STATUS_IS_OK(status)) {
3304                 printf("EnumDomains failed - %s\n", nt_errstr(status));
3305                 return False;
3306         }
3307
3308         if (!r.out.sam) {
3309                 return False;
3310         }
3311
3312         for (i=0;i<r.out.sam->count;i++) {
3313                 if (!test_LookupDomain(p, mem_ctx, handle, 
3314                                        &r.out.sam->entries[i].name)) {
3315                         ret = False;
3316                 }
3317         }
3318
3319         status = dcerpc_samr_EnumDomains(p, mem_ctx, &r);
3320         if (!NT_STATUS_IS_OK(status)) {
3321                 printf("EnumDomains failed - %s\n", nt_errstr(status));
3322                 return False;
3323         }
3324
3325         return ret;
3326 }
3327
3328
3329 static BOOL test_Connect(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
3330                          struct policy_handle *handle)
3331 {
3332         NTSTATUS status;
3333         struct samr_Connect r;
3334         struct samr_Connect2 r2;
3335         struct samr_Connect3 r3;
3336         struct samr_Connect4 r4;
3337         struct samr_Connect5 r5;
3338         union samr_ConnectInfo info;
3339         struct policy_handle h;
3340         BOOL ret = True, got_handle = False;
3341
3342         printf("testing samr_Connect\n");
3343
3344         r.in.system_name = 0;
3345         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3346         r.out.connect_handle = &h;
3347
3348         status = dcerpc_samr_Connect(p, mem_ctx, &r);
3349         if (!NT_STATUS_IS_OK(status)) {
3350                 printf("Connect failed - %s\n", nt_errstr(status));
3351                 ret = False;
3352         } else {
3353                 got_handle = True;
3354                 *handle = h;
3355         }
3356
3357         printf("testing samr_Connect2\n");
3358
3359         r2.in.system_name = NULL;
3360         r2.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3361         r2.out.connect_handle = &h;
3362
3363         status = dcerpc_samr_Connect2(p, mem_ctx, &r2);
3364         if (!NT_STATUS_IS_OK(status)) {
3365                 printf("Connect2 failed - %s\n", nt_errstr(status));
3366                 ret = False;
3367         } else {
3368                 if (got_handle) {
3369                         test_samr_handle_Close(p, mem_ctx, handle);
3370                 }
3371                 got_handle = True;
3372                 *handle = h;
3373         }
3374
3375         printf("testing samr_Connect3\n");
3376
3377         r3.in.system_name = NULL;
3378         r3.in.unknown = 0;
3379         r3.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3380         r3.out.connect_handle = &h;
3381
3382         status = dcerpc_samr_Connect3(p, mem_ctx, &r3);
3383         if (!NT_STATUS_IS_OK(status)) {
3384                 printf("Connect3 failed - %s\n", nt_errstr(status));
3385                 ret = False;
3386         } else {
3387                 if (got_handle) {
3388                         test_samr_handle_Close(p, mem_ctx, handle);
3389                 }
3390                 got_handle = True;
3391                 *handle = h;
3392         }
3393
3394         printf("testing samr_Connect4\n");
3395
3396         r4.in.system_name = "";
3397         r4.in.unknown = 0;
3398         r4.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3399         r4.out.connect_handle = &h;
3400
3401         status = dcerpc_samr_Connect4(p, mem_ctx, &r4);
3402         if (!NT_STATUS_IS_OK(status)) {
3403                 printf("Connect4 failed - %s\n", nt_errstr(status));
3404                 ret = False;
3405         } else {
3406                 if (got_handle) {
3407                         test_samr_handle_Close(p, mem_ctx, handle);
3408                 }
3409                 got_handle = True;
3410                 *handle = h;
3411         }
3412
3413         printf("testing samr_Connect5\n");
3414
3415         info.info1.unknown1 = 0;
3416         info.info1.unknown2 = 0;
3417
3418         r5.in.system_name = "";
3419         r5.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3420         r5.in.level = 1;
3421         r5.in.info = &info;
3422         r5.out.info = &info;
3423         r5.out.connect_handle = &h;
3424
3425         status = dcerpc_samr_Connect5(p, mem_ctx, &r5);
3426         if (!NT_STATUS_IS_OK(status)) {
3427                 printf("Connect5 failed - %s\n", nt_errstr(status));
3428                 ret = False;
3429         } else {
3430                 if (got_handle) {
3431                         test_samr_handle_Close(p, mem_ctx, handle);
3432                 }
3433                 got_handle = True;
3434                 *handle = h;
3435         }
3436
3437         return ret;
3438 }
3439
3440
3441 BOOL torture_rpc_samr(struct torture_context *torture)
3442 {
3443     NTSTATUS status;
3444     struct dcerpc_pipe *p;
3445         BOOL ret = True;
3446         struct policy_handle handle;
3447
3448         status = torture_rpc_connection(torture, &p, &dcerpc_table_samr);
3449         if (!NT_STATUS_IS_OK(status)) {
3450                 return False;
3451         }
3452
3453         ret &= test_Connect(p, torture, &handle);
3454
3455         ret &= test_QuerySecurity(p, torture, &handle);
3456
3457         ret &= test_EnumDomains(p, torture, &handle);
3458
3459         ret &= test_SetDsrmPassword(p, torture, &handle);
3460
3461         ret &= test_Shutdown(p, torture, &handle);
3462
3463         ret &= test_samr_handle_Close(p, torture, &handle);
3464
3465         return ret;
3466 }
3467