b9fa778fa70d458a3a28d7278c8a88a31d0d29b0
[kai/samba.git] / source4 / torture / rpc / samr.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for samr rpc operations
4
5    Copyright (C) Andrew Tridgell 2003
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "system/time.h"
25 #include "librpc/gen_ndr/lsa.h"
26 #include "librpc/gen_ndr/ndr_samr_c.h"
27 #include "../lib/crypto/crypto.h"
28 #include "libcli/auth/libcli_auth.h"
29 #include "libcli/security/security.h"
30 #include "torture/rpc/rpc.h"
31
32 #include <unistd.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 enum torture_samr_choice {
41         TORTURE_SAMR_PASSWORDS,
42         TORTURE_SAMR_PASSWORDS_PWDLASTSET,
43         TORTURE_SAMR_USER_ATTRIBUTES,
44         TORTURE_SAMR_OTHER
45 };
46
47 static bool test_QueryUserInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
48                                struct policy_handle *handle);
49
50 static bool test_QueryUserInfo2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
51                                 struct policy_handle *handle);
52
53 static bool test_QueryAliasInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
54                                struct policy_handle *handle);
55
56 static bool test_ChangePassword(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
57                                 const char *acct_name, 
58                                 struct policy_handle *domain_handle, char **password);
59
60 static void init_lsa_String(struct lsa_String *string, const char *s)
61 {
62         string->string = s;
63 }
64
65 static void init_lsa_BinaryString(struct lsa_BinaryString *string, const char *s, uint32_t length)
66 {
67         string->length = length;
68         string->size = length;
69         string->array = (uint16_t *)discard_const(s);
70 }
71
72 bool test_samr_handle_Close(struct dcerpc_pipe *p, struct torture_context *tctx,
73                                    struct policy_handle *handle)
74 {
75         NTSTATUS status;
76         struct samr_Close r;
77
78         r.in.handle = handle;
79         r.out.handle = handle;
80
81         status = dcerpc_samr_Close(p, tctx, &r);
82         torture_assert_ntstatus_ok(tctx, status, "Close");
83
84         return true;
85 }
86
87 static bool test_Shutdown(struct dcerpc_pipe *p, struct torture_context *tctx,
88                        struct policy_handle *handle)
89 {
90         NTSTATUS status;
91         struct samr_Shutdown r;
92
93         if (!torture_setting_bool(tctx, "dangerous", false)) {
94                 torture_skip(tctx, "samr_Shutdown disabled - enable dangerous tests to use\n");
95                 return true;
96         }
97
98         r.in.connect_handle = handle;
99
100         torture_comment(tctx, "testing samr_Shutdown\n");
101
102         status = dcerpc_samr_Shutdown(p, tctx, &r);
103         torture_assert_ntstatus_ok(tctx, status, "samr_Shutdown");
104
105         return true;
106 }
107
108 static bool test_SetDsrmPassword(struct dcerpc_pipe *p, struct torture_context *tctx,
109                                  struct policy_handle *handle)
110 {
111         NTSTATUS status;
112         struct samr_SetDsrmPassword r;
113         struct lsa_String string;
114         struct samr_Password hash;
115
116         if (!torture_setting_bool(tctx, "dangerous", false)) {
117                 torture_skip(tctx, "samr_SetDsrmPassword disabled - enable dangerous tests to use");
118         }
119
120         E_md4hash("TeSTDSRM123", hash.hash);
121
122         init_lsa_String(&string, "Administrator");
123
124         r.in.name = &string;
125         r.in.unknown = 0;
126         r.in.hash = &hash;
127
128         torture_comment(tctx, "testing samr_SetDsrmPassword\n");
129
130         status = dcerpc_samr_SetDsrmPassword(p, tctx, &r);
131         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED, "samr_SetDsrmPassword");
132
133         return true;
134 }
135
136
137 static bool test_QuerySecurity(struct dcerpc_pipe *p, 
138                                struct torture_context *tctx, 
139                                struct policy_handle *handle)
140 {
141         NTSTATUS status;
142         struct samr_QuerySecurity r;
143         struct samr_SetSecurity s;
144         struct sec_desc_buf *sdbuf = NULL;
145
146         r.in.handle = handle;
147         r.in.sec_info = 7;
148         r.out.sdbuf = &sdbuf;
149
150         status = dcerpc_samr_QuerySecurity(p, tctx, &r);
151         torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
152
153         torture_assert(tctx, sdbuf != NULL, "sdbuf is NULL");
154
155         s.in.handle = handle;
156         s.in.sec_info = 7;
157         s.in.sdbuf = sdbuf;
158
159         if (torture_setting_bool(tctx, "samba4", false)) {
160                 torture_skip(tctx, "skipping SetSecurity test against Samba4\n");
161         }
162
163         status = dcerpc_samr_SetSecurity(p, tctx, &s);
164         torture_assert_ntstatus_ok(tctx, status, "SetSecurity");
165
166         status = dcerpc_samr_QuerySecurity(p, tctx, &r);
167         torture_assert_ntstatus_ok(tctx, status, "QuerySecurity");
168
169         return true;
170 }
171
172
173 static bool test_SetUserInfo(struct dcerpc_pipe *p, struct torture_context *tctx, 
174                              struct policy_handle *handle, uint32_t base_acct_flags,
175                              const char *base_account_name)
176 {
177         NTSTATUS status;
178         struct samr_SetUserInfo s;
179         struct samr_SetUserInfo2 s2;
180         struct samr_QueryUserInfo q;
181         struct samr_QueryUserInfo q0;
182         union samr_UserInfo u;
183         union samr_UserInfo *info;
184         bool ret = true;
185         const char *test_account_name;
186
187         uint32_t user_extra_flags = 0;
188         if (base_acct_flags == ACB_NORMAL) {
189                 /* When created, accounts are expired by default */
190                 user_extra_flags = ACB_PW_EXPIRED;
191         }
192
193         s.in.user_handle = handle;
194         s.in.info = &u;
195
196         s2.in.user_handle = handle;
197         s2.in.info = &u;
198
199         q.in.user_handle = handle;
200         q.out.info = &info;
201         q0 = q;
202
203 #define TESTCALL(call, r) \
204                 status = dcerpc_samr_ ##call(p, tctx, &r); \
205                 if (!NT_STATUS_IS_OK(status)) { \
206                         torture_comment(tctx, #call " level %u failed - %s (%s)\n", \
207                                r.in.level, nt_errstr(status), __location__); \
208                         ret = false; \
209                         break; \
210                 }
211
212 #define STRING_EQUAL(s1, s2, field) \
213                 if ((s1 && !s2) || (s2 && !s1) || strcmp(s1, s2)) { \
214                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
215                                #field, s2, __location__); \
216                         ret = false; \
217                         break; \
218                 }
219
220 #define MEM_EQUAL(s1, s2, length, field) \
221                 if ((s1 && !s2) || (s2 && !s1) || memcmp(s1, s2, length)) { \
222                         torture_comment(tctx, "Failed to set %s to '%s' (%s)\n", \
223                                #field, (const char *)s2, __location__); \
224                         ret = false; \
225                         break; \
226                 }
227
228 #define INT_EQUAL(i1, i2, field) \
229                 if (i1 != i2) { \
230                         torture_comment(tctx, "Failed to set %s to 0x%llx - got 0x%llx (%s)\n", \
231                                #field, (unsigned long long)i2, (unsigned long long)i1, __location__); \
232                         ret = false; \
233                         break; \
234                 }
235
236 #define TEST_USERINFO_STRING(lvl1, field1, lvl2, field2, value, fpval) do { \
237                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
238                 q.in.level = lvl1; \
239                 TESTCALL(QueryUserInfo, q) \
240                 s.in.level = lvl1; \
241                 s2.in.level = lvl1; \
242                 u = *info; \
243                 if (lvl1 == 21) { \
244                         ZERO_STRUCT(u.info21); \
245                         u.info21.fields_present = fpval; \
246                 } \
247                 init_lsa_String(&u.info ## lvl1.field1, value); \
248                 TESTCALL(SetUserInfo, s) \
249                 TESTCALL(SetUserInfo2, s2) \
250                 init_lsa_String(&u.info ## lvl1.field1, ""); \
251                 TESTCALL(QueryUserInfo, q); \
252                 u = *info; \
253                 STRING_EQUAL(u.info ## lvl1.field1.string, value, field1); \
254                 q.in.level = lvl2; \
255                 TESTCALL(QueryUserInfo, q) \
256                 u = *info; \
257                 STRING_EQUAL(u.info ## lvl2.field2.string, value, field2); \
258         } while (0)
259
260 #define TEST_USERINFO_BINARYSTRING(lvl1, field1, lvl2, field2, value, fpval) do { \
261                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
262                 q.in.level = lvl1; \
263                 TESTCALL(QueryUserInfo, q) \
264                 s.in.level = lvl1; \
265                 s2.in.level = lvl1; \
266                 u = *info; \
267                 if (lvl1 == 21) { \
268                         ZERO_STRUCT(u.info21); \
269                         u.info21.fields_present = fpval; \
270                 } \
271                 init_lsa_BinaryString(&u.info ## lvl1.field1, value, strlen(value)); \
272                 TESTCALL(SetUserInfo, s) \
273                 TESTCALL(SetUserInfo2, s2) \
274                 init_lsa_BinaryString(&u.info ## lvl1.field1, "", 1); \
275                 TESTCALL(QueryUserInfo, q); \
276                 u = *info; \
277                 MEM_EQUAL(u.info ## lvl1.field1.array, value, strlen(value), field1); \
278                 q.in.level = lvl2; \
279                 TESTCALL(QueryUserInfo, q) \
280                 u = *info; \
281                 MEM_EQUAL(u.info ## lvl2.field2.array, value, strlen(value), field2); \
282         } while (0)
283
284 #define TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, exp_value, fpval) do { \
285                 torture_comment(tctx, "field test %d/%s vs %d/%s\n", lvl1, #field1, lvl2, #field2); \
286                 q.in.level = lvl1; \
287                 TESTCALL(QueryUserInfo, q) \
288                 s.in.level = lvl1; \
289                 s2.in.level = lvl1; \
290                 u = *info; \
291                 if (lvl1 == 21) { \
292                         uint8_t *bits = u.info21.logon_hours.bits; \
293                         ZERO_STRUCT(u.info21); \
294                         if (fpval == SAMR_FIELD_LOGON_HOURS) { \
295                                 u.info21.logon_hours.units_per_week = 168; \
296                                 u.info21.logon_hours.bits = bits; \
297                         } \
298                         u.info21.fields_present = fpval; \
299                 } \
300                 u.info ## lvl1.field1 = value; \
301                 TESTCALL(SetUserInfo, s) \
302                 TESTCALL(SetUserInfo2, s2) \
303                 u.info ## lvl1.field1 = 0; \
304                 TESTCALL(QueryUserInfo, q); \
305                 u = *info; \
306                 INT_EQUAL(u.info ## lvl1.field1, exp_value, field1); \
307                 q.in.level = lvl2; \
308                 TESTCALL(QueryUserInfo, q) \
309                 u = *info; \
310                 INT_EQUAL(u.info ## lvl2.field2, exp_value, field1); \
311         } while (0)
312
313 #define TEST_USERINFO_INT(lvl1, field1, lvl2, field2, value, fpval) do { \
314         TEST_USERINFO_INT_EXP(lvl1, field1, lvl2, field2, value, value, fpval); \
315         } while (0)
316
317         q0.in.level = 12;
318         do { TESTCALL(QueryUserInfo, q0) } while (0);
319
320         TEST_USERINFO_STRING(2, comment,  1, comment, "xx2-1 comment", 0);
321         TEST_USERINFO_STRING(2, comment, 21, comment, "xx2-21 comment", 0);
322         TEST_USERINFO_STRING(21, comment, 21, comment, "xx21-21 comment", 
323                            SAMR_FIELD_COMMENT);
324
325         test_account_name = talloc_asprintf(tctx, "%sxx7-1", base_account_name);
326         TEST_USERINFO_STRING(7, account_name,  1, account_name, base_account_name, 0);
327         test_account_name = talloc_asprintf(tctx, "%sxx7-3", base_account_name);
328         TEST_USERINFO_STRING(7, account_name,  3, account_name, base_account_name, 0);
329         test_account_name = talloc_asprintf(tctx, "%sxx7-5", base_account_name);
330         TEST_USERINFO_STRING(7, account_name,  5, account_name, base_account_name, 0);
331         test_account_name = talloc_asprintf(tctx, "%sxx7-6", base_account_name);
332         TEST_USERINFO_STRING(7, account_name,  6, account_name, base_account_name, 0);
333         test_account_name = talloc_asprintf(tctx, "%sxx7-7", base_account_name);
334         TEST_USERINFO_STRING(7, account_name,  7, account_name, base_account_name, 0);
335         test_account_name = talloc_asprintf(tctx, "%sxx7-21", base_account_name);
336         TEST_USERINFO_STRING(7, account_name, 21, account_name, base_account_name, 0);
337         test_account_name = base_account_name;
338         TEST_USERINFO_STRING(21, account_name, 21, account_name, base_account_name, 
339                            SAMR_FIELD_ACCOUNT_NAME);
340
341         TEST_USERINFO_STRING(6, full_name,  1, full_name, "xx6-1 full_name", 0);
342         TEST_USERINFO_STRING(6, full_name,  3, full_name, "xx6-3 full_name", 0);
343         TEST_USERINFO_STRING(6, full_name,  5, full_name, "xx6-5 full_name", 0);
344         TEST_USERINFO_STRING(6, full_name,  6, full_name, "xx6-6 full_name", 0);
345         TEST_USERINFO_STRING(6, full_name,  8, full_name, "xx6-8 full_name", 0);
346         TEST_USERINFO_STRING(6, full_name, 21, full_name, "xx6-21 full_name", 0);
347         TEST_USERINFO_STRING(8, full_name, 21, full_name, "xx8-21 full_name", 0);
348         TEST_USERINFO_STRING(21, full_name, 21, full_name, "xx21-21 full_name", 
349                            SAMR_FIELD_FULL_NAME);
350
351         TEST_USERINFO_STRING(6, full_name,  1, full_name, "", 0);
352         TEST_USERINFO_STRING(6, full_name,  3, full_name, "", 0);
353         TEST_USERINFO_STRING(6, full_name,  5, full_name, "", 0);
354         TEST_USERINFO_STRING(6, full_name,  6, full_name, "", 0);
355         TEST_USERINFO_STRING(6, full_name,  8, full_name, "", 0);
356         TEST_USERINFO_STRING(6, full_name, 21, full_name, "", 0);
357         TEST_USERINFO_STRING(8, full_name, 21, full_name, "", 0);
358         TEST_USERINFO_STRING(21, full_name, 21, full_name, "", 
359                            SAMR_FIELD_FULL_NAME);
360
361         TEST_USERINFO_STRING(11, logon_script, 3, logon_script, "xx11-3 logon_script", 0);
362         TEST_USERINFO_STRING(11, logon_script, 5, logon_script, "xx11-5 logon_script", 0);
363         TEST_USERINFO_STRING(11, logon_script, 21, logon_script, "xx11-21 logon_script", 0);
364         TEST_USERINFO_STRING(21, logon_script, 21, logon_script, "xx21-21 logon_script", 
365                            SAMR_FIELD_LOGON_SCRIPT);
366
367         TEST_USERINFO_STRING(12, profile_path,  3, profile_path, "xx12-3 profile_path", 0);
368         TEST_USERINFO_STRING(12, profile_path,  5, profile_path, "xx12-5 profile_path", 0);
369         TEST_USERINFO_STRING(12, profile_path, 21, profile_path, "xx12-21 profile_path", 0);
370         TEST_USERINFO_STRING(21, profile_path, 21, profile_path, "xx21-21 profile_path", 
371                            SAMR_FIELD_PROFILE_PATH);
372
373         TEST_USERINFO_STRING(10, home_directory, 3, home_directory, "xx10-3 home_directory", 0);
374         TEST_USERINFO_STRING(10, home_directory, 5, home_directory, "xx10-5 home_directory", 0);
375         TEST_USERINFO_STRING(10, home_directory, 21, home_directory, "xx10-21 home_directory", 0);
376         TEST_USERINFO_STRING(21, home_directory, 21, home_directory, "xx21-21 home_directory",
377                              SAMR_FIELD_HOME_DIRECTORY);
378         TEST_USERINFO_STRING(21, home_directory, 10, home_directory, "xx21-10 home_directory",
379                              SAMR_FIELD_HOME_DIRECTORY);
380
381         TEST_USERINFO_STRING(10, home_drive, 3, home_drive, "xx10-3 home_drive", 0);
382         TEST_USERINFO_STRING(10, home_drive, 5, home_drive, "xx10-5 home_drive", 0);
383         TEST_USERINFO_STRING(10, home_drive, 21, home_drive, "xx10-21 home_drive", 0);
384         TEST_USERINFO_STRING(21, home_drive, 21, home_drive, "xx21-21 home_drive",
385                              SAMR_FIELD_HOME_DRIVE);
386         TEST_USERINFO_STRING(21, home_drive, 10, home_drive, "xx21-10 home_drive",
387                              SAMR_FIELD_HOME_DRIVE);
388         
389         TEST_USERINFO_STRING(13, description,  1, description, "xx13-1 description", 0);
390         TEST_USERINFO_STRING(13, description,  5, description, "xx13-5 description", 0);
391         TEST_USERINFO_STRING(13, description, 21, description, "xx13-21 description", 0);
392         TEST_USERINFO_STRING(21, description, 21, description, "xx21-21 description", 
393                            SAMR_FIELD_DESCRIPTION);
394
395         TEST_USERINFO_STRING(14, workstations,  3, workstations, "14workstation3", 0);
396         TEST_USERINFO_STRING(14, workstations,  5, workstations, "14workstation4", 0);
397         TEST_USERINFO_STRING(14, workstations, 21, workstations, "14workstation21", 0);
398         TEST_USERINFO_STRING(21, workstations, 21, workstations, "21workstation21", 
399                            SAMR_FIELD_WORKSTATIONS);
400         TEST_USERINFO_STRING(21, workstations, 3, workstations, "21workstation3", 
401                            SAMR_FIELD_WORKSTATIONS);
402         TEST_USERINFO_STRING(21, workstations, 5, workstations, "21workstation5", 
403                            SAMR_FIELD_WORKSTATIONS);
404         TEST_USERINFO_STRING(21, workstations, 14, workstations, "21workstation14", 
405                            SAMR_FIELD_WORKSTATIONS);
406
407         TEST_USERINFO_BINARYSTRING(20, parameters, 21, parameters, "xx20-21 parameters", 0);
408         TEST_USERINFO_BINARYSTRING(21, parameters, 21, parameters, "xx21-21 parameters",
409                            SAMR_FIELD_PARAMETERS);
410         TEST_USERINFO_BINARYSTRING(21, parameters, 20, parameters, "xx21-20 parameters",
411                            SAMR_FIELD_PARAMETERS);
412
413         TEST_USERINFO_INT(2, country_code, 2, country_code, __LINE__, 0);
414         TEST_USERINFO_INT(2, country_code, 21, country_code, __LINE__, 0);
415         TEST_USERINFO_INT(21, country_code, 21, country_code, __LINE__, 
416                           SAMR_FIELD_COUNTRY_CODE);
417         TEST_USERINFO_INT(21, country_code, 2, country_code, __LINE__, 
418                           SAMR_FIELD_COUNTRY_CODE);
419
420         TEST_USERINFO_INT(2, code_page, 21, code_page, __LINE__, 0);
421         TEST_USERINFO_INT(21, code_page, 21, code_page, __LINE__, 
422                           SAMR_FIELD_CODE_PAGE);
423         TEST_USERINFO_INT(21, code_page, 2, code_page, __LINE__, 
424                           SAMR_FIELD_CODE_PAGE);
425
426         TEST_USERINFO_INT(17, acct_expiry, 21, acct_expiry, __LINE__, 0);
427         TEST_USERINFO_INT(17, acct_expiry, 5, acct_expiry, __LINE__, 0);
428         TEST_USERINFO_INT(21, acct_expiry, 21, acct_expiry, __LINE__, 
429                           SAMR_FIELD_ACCT_EXPIRY);
430         TEST_USERINFO_INT(21, acct_expiry, 5, acct_expiry, __LINE__, 
431                           SAMR_FIELD_ACCT_EXPIRY);
432         TEST_USERINFO_INT(21, acct_expiry, 17, acct_expiry, __LINE__, 
433                           SAMR_FIELD_ACCT_EXPIRY);
434
435         TEST_USERINFO_INT(4, logon_hours.bits[3],  3, logon_hours.bits[3], 1, 0);
436         TEST_USERINFO_INT(4, logon_hours.bits[3],  5, logon_hours.bits[3], 2, 0);
437         TEST_USERINFO_INT(4, logon_hours.bits[3], 21, logon_hours.bits[3], 3, 0);
438         TEST_USERINFO_INT(21, logon_hours.bits[3], 21, logon_hours.bits[3], 4, 
439                           SAMR_FIELD_LOGON_HOURS);
440
441         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
442                               (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ), 
443                               (base_acct_flags  | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
444                               0);
445         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
446                               (base_acct_flags  | ACB_DISABLED), 
447                               (base_acct_flags  | ACB_DISABLED | user_extra_flags), 
448                               0);
449         
450         /* Setting PWNOEXP clears the magic ACB_PW_EXPIRED flag */
451         TEST_USERINFO_INT_EXP(16, acct_flags, 5, acct_flags, 
452                               (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP), 
453                               (base_acct_flags  | ACB_DISABLED | ACB_PWNOEXP), 
454                               0);
455         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
456                               (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ), 
457                               (base_acct_flags | ACB_DISABLED | ACB_HOMDIRREQ | user_extra_flags), 
458                               0);
459
460
461         /* The 'autolock' flag doesn't stick - check this */
462         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
463                               (base_acct_flags | ACB_DISABLED | ACB_AUTOLOCK), 
464                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
465                               0);
466 #if 0
467         /* Removing the 'disabled' flag doesn't stick - check this */
468         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
469                               (base_acct_flags), 
470                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
471                               0);
472 #endif
473         /* The 'store plaintext' flag does stick */
474         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
475                               (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED), 
476                               (base_acct_flags | ACB_DISABLED | ACB_ENC_TXT_PWD_ALLOWED | user_extra_flags), 
477                               0);
478         /* The 'use DES' flag does stick */
479         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
480                               (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY), 
481                               (base_acct_flags | ACB_DISABLED | ACB_USE_DES_KEY_ONLY | user_extra_flags), 
482                               0);
483         /* The 'don't require kerberos pre-authentication flag does stick */
484         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
485                               (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH), 
486                               (base_acct_flags | ACB_DISABLED | ACB_DONT_REQUIRE_PREAUTH | user_extra_flags), 
487                               0);
488         /* The 'no kerberos PAC required' flag sticks */
489         TEST_USERINFO_INT_EXP(16, acct_flags, 21, acct_flags, 
490                               (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD), 
491                               (base_acct_flags | ACB_DISABLED | ACB_NO_AUTH_DATA_REQD | user_extra_flags), 
492                               0);
493
494         TEST_USERINFO_INT_EXP(21, acct_flags, 21, acct_flags, 
495                               (base_acct_flags | ACB_DISABLED), 
496                               (base_acct_flags | ACB_DISABLED | user_extra_flags), 
497                               SAMR_FIELD_ACCT_FLAGS);
498
499 #if 0
500         /* these fail with win2003 - it appears you can't set the primary gid?
501            the set succeeds, but the gid isn't changed. Very weird! */
502         TEST_USERINFO_INT(9, primary_gid,  1, primary_gid, 513);
503         TEST_USERINFO_INT(9, primary_gid,  3, primary_gid, 513);
504         TEST_USERINFO_INT(9, primary_gid,  5, primary_gid, 513);
505         TEST_USERINFO_INT(9, primary_gid, 21, primary_gid, 513);
506 #endif
507
508         return ret;
509 }
510
511 /*
512   generate a random password for password change tests
513 */
514 static char *samr_rand_pass_silent(TALLOC_CTX *mem_ctx, int min_len)
515 {
516         size_t len = MAX(8, min_len) + (random() % 6);
517         char *s = generate_random_str(mem_ctx, len);
518         return s;
519 }
520
521 static char *samr_rand_pass(TALLOC_CTX *mem_ctx, int min_len)
522 {
523         char *s = samr_rand_pass_silent(mem_ctx, min_len);
524         printf("Generated password '%s'\n", s);
525         return s;
526
527 }
528
529 /*
530   generate a random password for password change tests
531 */
532 static DATA_BLOB samr_very_rand_pass(TALLOC_CTX *mem_ctx, int len)
533 {
534         int i;
535         DATA_BLOB password = data_blob_talloc(mem_ctx, NULL, len * 2 /* number of unicode chars */);
536         generate_random_buffer(password.data, password.length);
537
538         for (i=0; i < len; i++) {
539                 if (((uint16_t *)password.data)[i] == 0) {
540                         ((uint16_t *)password.data)[i] = 1;
541                 }
542         }
543
544         return password;
545 }
546
547 /*
548   generate a random password for password change tests (fixed length)
549 */
550 static char *samr_rand_pass_fixed_len(TALLOC_CTX *mem_ctx, int len)
551 {
552         char *s = generate_random_str(mem_ctx, len);
553         printf("Generated password '%s'\n", s);
554         return s;
555 }
556
557 static bool test_SetUserPass(struct dcerpc_pipe *p, struct torture_context *tctx,
558                              struct policy_handle *handle, char **password)
559 {
560         NTSTATUS status;
561         struct samr_SetUserInfo s;
562         union samr_UserInfo u;
563         bool ret = true;
564         DATA_BLOB session_key;
565         char *newpass;
566         struct samr_GetUserPwInfo pwp;
567         struct samr_PwInfo info;
568         int policy_min_pw_len = 0;
569         pwp.in.user_handle = handle;
570         pwp.out.info = &info;
571
572         status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
573         if (NT_STATUS_IS_OK(status)) {
574                 policy_min_pw_len = pwp.out.info->min_password_length;
575         }
576         newpass = samr_rand_pass(tctx, policy_min_pw_len);
577
578         s.in.user_handle = handle;
579         s.in.info = &u;
580         s.in.level = 24;
581
582         encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
583         u.info24.password_expired = 0;
584
585         status = dcerpc_fetch_session_key(p, &session_key);
586         if (!NT_STATUS_IS_OK(status)) {
587                 printf("SetUserInfo level %u - no session key - %s\n",
588                        s.in.level, nt_errstr(status));
589                 return false;
590         }
591
592         arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
593
594         torture_comment(tctx, "Testing SetUserInfo level 24 (set password)\n");
595
596         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
597         if (!NT_STATUS_IS_OK(status)) {
598                 printf("SetUserInfo level %u failed - %s\n",
599                        s.in.level, nt_errstr(status));
600                 ret = false;
601         } else {
602                 *password = newpass;
603         }
604
605         return ret;
606 }
607
608
609 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
610                                 struct policy_handle *handle, uint32_t fields_present,
611                                 char **password)
612 {
613         NTSTATUS status;
614         struct samr_SetUserInfo s;
615         union samr_UserInfo u;
616         bool ret = true;
617         DATA_BLOB session_key;
618         char *newpass;
619         struct samr_GetUserPwInfo pwp;
620         struct samr_PwInfo info;
621         int policy_min_pw_len = 0;
622         pwp.in.user_handle = handle;
623         pwp.out.info = &info;
624
625         status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
626         if (NT_STATUS_IS_OK(status)) {
627                 policy_min_pw_len = pwp.out.info->min_password_length;
628         }
629         newpass = samr_rand_pass(tctx, policy_min_pw_len);
630
631         s.in.user_handle = handle;
632         s.in.info = &u;
633         s.in.level = 23;
634
635         ZERO_STRUCT(u);
636
637         u.info23.info.fields_present = fields_present;
638
639         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
640
641         status = dcerpc_fetch_session_key(p, &session_key);
642         if (!NT_STATUS_IS_OK(status)) {
643                 printf("SetUserInfo level %u - no session key - %s\n",
644                        s.in.level, nt_errstr(status));
645                 return false;
646         }
647
648         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
649
650         torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
651
652         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
653         if (!NT_STATUS_IS_OK(status)) {
654                 printf("SetUserInfo level %u failed - %s\n",
655                        s.in.level, nt_errstr(status));
656                 ret = false;
657         } else {
658                 *password = newpass;
659         }
660
661         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
662
663         status = dcerpc_fetch_session_key(p, &session_key);
664         if (!NT_STATUS_IS_OK(status)) {
665                 printf("SetUserInfo level %u - no session key - %s\n",
666                        s.in.level, nt_errstr(status));
667                 return false;
668         }
669
670         /* This should break the key nicely */
671         session_key.length--;
672         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
673
674         torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
675
676         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
677         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
678                 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
679                        s.in.level, nt_errstr(status));
680                 ret = false;
681         }
682
683         return ret;
684 }
685
686
687 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
688                                struct policy_handle *handle, bool makeshort, 
689                                char **password)
690 {
691         NTSTATUS status;
692         struct samr_SetUserInfo s;
693         union samr_UserInfo u;
694         bool ret = true;
695         DATA_BLOB session_key;
696         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
697         uint8_t confounder[16];
698         char *newpass;
699         struct MD5Context ctx;
700         struct samr_GetUserPwInfo pwp;
701         struct samr_PwInfo info;
702         int policy_min_pw_len = 0;
703         pwp.in.user_handle = handle;
704         pwp.out.info = &info;
705
706         status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
707         if (NT_STATUS_IS_OK(status)) {
708                 policy_min_pw_len = pwp.out.info->min_password_length;
709         }
710         if (makeshort && policy_min_pw_len) {
711                 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
712         } else {
713                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
714         }
715
716         s.in.user_handle = handle;
717         s.in.info = &u;
718         s.in.level = 26;
719
720         encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
721         u.info26.password_expired = 0;
722
723         status = dcerpc_fetch_session_key(p, &session_key);
724         if (!NT_STATUS_IS_OK(status)) {
725                 printf("SetUserInfo level %u - no session key - %s\n",
726                        s.in.level, nt_errstr(status));
727                 return false;
728         }
729
730         generate_random_buffer((uint8_t *)confounder, 16);
731
732         MD5Init(&ctx);
733         MD5Update(&ctx, confounder, 16);
734         MD5Update(&ctx, session_key.data, session_key.length);
735         MD5Final(confounded_session_key.data, &ctx);
736
737         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
738         memcpy(&u.info26.password.data[516], confounder, 16);
739
740         torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
741
742         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
743         if (!NT_STATUS_IS_OK(status)) {
744                 printf("SetUserInfo level %u failed - %s\n",
745                        s.in.level, nt_errstr(status));
746                 ret = false;
747         } else {
748                 *password = newpass;
749         }
750
751         /* This should break the key nicely */
752         confounded_session_key.data[0]++;
753
754         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
755         memcpy(&u.info26.password.data[516], confounder, 16);
756
757         torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
758
759         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
760         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
761                 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
762                        s.in.level, nt_errstr(status));
763                 ret = false;
764         } else {
765                 *password = newpass;
766         }
767
768         return ret;
769 }
770
771 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
772                                 struct policy_handle *handle, uint32_t fields_present,
773                                 char **password)
774 {
775         NTSTATUS status;
776         struct samr_SetUserInfo s;
777         union samr_UserInfo u;
778         bool ret = true;
779         DATA_BLOB session_key;
780         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
781         struct MD5Context ctx;
782         uint8_t confounder[16];
783         char *newpass;
784         struct samr_GetUserPwInfo pwp;
785         struct samr_PwInfo info;
786         int policy_min_pw_len = 0;
787         pwp.in.user_handle = handle;
788         pwp.out.info = &info;
789
790         status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
791         if (NT_STATUS_IS_OK(status)) {
792                 policy_min_pw_len = pwp.out.info->min_password_length;
793         }
794         newpass = samr_rand_pass(tctx, policy_min_pw_len);
795
796         s.in.user_handle = handle;
797         s.in.info = &u;
798         s.in.level = 25;
799
800         ZERO_STRUCT(u);
801
802         u.info25.info.fields_present = fields_present;
803
804         encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
805
806         status = dcerpc_fetch_session_key(p, &session_key);
807         if (!NT_STATUS_IS_OK(status)) {
808                 printf("SetUserInfo level %u - no session key - %s\n",
809                        s.in.level, nt_errstr(status));
810                 return false;
811         }
812
813         generate_random_buffer((uint8_t *)confounder, 16);
814
815         MD5Init(&ctx);
816         MD5Update(&ctx, confounder, 16);
817         MD5Update(&ctx, session_key.data, session_key.length);
818         MD5Final(confounded_session_key.data, &ctx);
819
820         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
821         memcpy(&u.info25.password.data[516], confounder, 16);
822
823         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
824
825         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
826         if (!NT_STATUS_IS_OK(status)) {
827                 printf("SetUserInfo level %u failed - %s\n",
828                        s.in.level, nt_errstr(status));
829                 ret = false;
830         } else {
831                 *password = newpass;
832         }
833
834         /* This should break the key nicely */
835         confounded_session_key.data[0]++;
836
837         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
838         memcpy(&u.info25.password.data[516], confounder, 16);
839
840         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
841
842         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
843         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
844                 printf("SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
845                        s.in.level, nt_errstr(status));
846                 ret = false;
847         }
848
849         return ret;
850 }
851
852 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
853                                 struct policy_handle *handle, char **password)
854 {
855         NTSTATUS status;
856         struct samr_SetUserInfo s;
857         union samr_UserInfo u;
858         bool ret = true;
859         DATA_BLOB session_key;
860         char *newpass;
861         struct samr_GetUserPwInfo pwp;
862         struct samr_PwInfo info;
863         int policy_min_pw_len = 0;
864         uint8_t lm_hash[16], nt_hash[16];
865
866         pwp.in.user_handle = handle;
867         pwp.out.info = &info;
868
869         status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
870         if (NT_STATUS_IS_OK(status)) {
871                 policy_min_pw_len = pwp.out.info->min_password_length;
872         }
873         newpass = samr_rand_pass(tctx, policy_min_pw_len);
874
875         s.in.user_handle = handle;
876         s.in.info = &u;
877         s.in.level = 18;
878
879         ZERO_STRUCT(u);
880
881         u.info18.nt_pwd_active = true;
882         u.info18.lm_pwd_active = true;
883
884         E_md4hash(newpass, nt_hash);
885         E_deshash(newpass, lm_hash);
886
887         status = dcerpc_fetch_session_key(p, &session_key);
888         if (!NT_STATUS_IS_OK(status)) {
889                 printf("SetUserInfo level %u - no session key - %s\n",
890                        s.in.level, nt_errstr(status));
891                 return false;
892         }
893
894         {
895                 DATA_BLOB in,out;
896                 in = data_blob_const(nt_hash, 16);
897                 out = data_blob_talloc_zero(tctx, 16);
898                 sess_crypt_blob(&out, &in, &session_key, true);
899                 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
900         }
901         {
902                 DATA_BLOB in,out;
903                 in = data_blob_const(lm_hash, 16);
904                 out = data_blob_talloc_zero(tctx, 16);
905                 sess_crypt_blob(&out, &in, &session_key, true);
906                 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
907         }
908
909         torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
910
911         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
912         if (!NT_STATUS_IS_OK(status)) {
913                 printf("SetUserInfo level %u failed - %s\n",
914                        s.in.level, nt_errstr(status));
915                 ret = false;
916         } else {
917                 *password = newpass;
918         }
919
920         return ret;
921 }
922
923 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
924                                 struct policy_handle *handle, uint32_t fields_present,
925                                 char **password)
926 {
927         NTSTATUS status;
928         struct samr_SetUserInfo s;
929         union samr_UserInfo u;
930         bool ret = true;
931         DATA_BLOB session_key;
932         char *newpass;
933         struct samr_GetUserPwInfo pwp;
934         struct samr_PwInfo info;
935         int policy_min_pw_len = 0;
936         uint8_t lm_hash[16], nt_hash[16];
937
938         pwp.in.user_handle = handle;
939         pwp.out.info = &info;
940
941         status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
942         if (NT_STATUS_IS_OK(status)) {
943                 policy_min_pw_len = pwp.out.info->min_password_length;
944         }
945         newpass = samr_rand_pass(tctx, policy_min_pw_len);
946
947         s.in.user_handle = handle;
948         s.in.info = &u;
949         s.in.level = 21;
950
951         E_md4hash(newpass, nt_hash);
952         E_deshash(newpass, lm_hash);
953
954         ZERO_STRUCT(u);
955
956         u.info21.fields_present = fields_present;
957
958         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
959                 u.info21.lm_owf_password.length = 16;
960                 u.info21.lm_owf_password.size = 16;
961                 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
962                 u.info21.lm_password_set = true;
963         }
964
965         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
966                 u.info21.nt_owf_password.length = 16;
967                 u.info21.nt_owf_password.size = 16;
968                 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
969                 u.info21.nt_password_set = true;
970         }
971
972         status = dcerpc_fetch_session_key(p, &session_key);
973         if (!NT_STATUS_IS_OK(status)) {
974                 printf("SetUserInfo level %u - no session key - %s\n",
975                        s.in.level, nt_errstr(status));
976                 return false;
977         }
978
979         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
980                 DATA_BLOB in,out;
981                 in = data_blob_const(u.info21.lm_owf_password.array,
982                                      u.info21.lm_owf_password.length);
983                 out = data_blob_talloc_zero(tctx, 16);
984                 sess_crypt_blob(&out, &in, &session_key, true);
985                 u.info21.lm_owf_password.array = (uint16_t *)out.data;
986         }
987
988         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
989                 DATA_BLOB in,out;
990                 in = data_blob_const(u.info21.nt_owf_password.array,
991                                      u.info21.nt_owf_password.length);
992                 out = data_blob_talloc_zero(tctx, 16);
993                 sess_crypt_blob(&out, &in, &session_key, true);
994                 u.info21.nt_owf_password.array = (uint16_t *)out.data;
995         }
996
997         torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
998
999         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1000         if (!NT_STATUS_IS_OK(status)) {
1001                 printf("SetUserInfo level %u failed - %s\n",
1002                        s.in.level, nt_errstr(status));
1003                 ret = false;
1004         } else {
1005                 *password = newpass;
1006         }
1007
1008         /* try invalid length */
1009         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1010
1011                 u.info21.nt_owf_password.length++;
1012
1013                 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1014
1015                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1016                         printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1017                                s.in.level, nt_errstr(status));
1018                         ret = false;
1019                 }
1020         }
1021
1022         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1023
1024                 u.info21.lm_owf_password.length++;
1025
1026                 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1027
1028                 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1029                         printf("SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1030                                s.in.level, nt_errstr(status));
1031                         ret = false;
1032                 }
1033         }
1034
1035         return ret;
1036 }
1037
1038 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1039                                       struct torture_context *tctx,
1040                                       struct policy_handle *handle,
1041                                       uint16_t level,
1042                                       uint32_t fields_present,
1043                                       char **password, uint8_t password_expired,
1044                                       bool use_setinfo2,
1045                                       bool *matched_expected_error)
1046 {
1047         NTSTATUS status;
1048         NTSTATUS expected_error = NT_STATUS_OK;
1049         struct samr_SetUserInfo s;
1050         struct samr_SetUserInfo2 s2;
1051         union samr_UserInfo u;
1052         bool ret = true;
1053         DATA_BLOB session_key;
1054         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1055         struct MD5Context ctx;
1056         uint8_t confounder[16];
1057         char *newpass;
1058         struct samr_GetUserPwInfo pwp;
1059         struct samr_PwInfo info;
1060         int policy_min_pw_len = 0;
1061         const char *comment = NULL;
1062
1063         pwp.in.user_handle = handle;
1064         pwp.out.info = &info;
1065
1066         status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1067         if (NT_STATUS_IS_OK(status)) {
1068                 policy_min_pw_len = pwp.out.info->min_password_length;
1069         }
1070         newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1071
1072         if (use_setinfo2) {
1073                 s2.in.user_handle = handle;
1074                 s2.in.info = &u;
1075                 s2.in.level = level;
1076         } else {
1077                 s.in.user_handle = handle;
1078                 s.in.info = &u;
1079                 s.in.level = level;
1080         }
1081
1082         if (fields_present & SAMR_FIELD_COMMENT) {
1083                 comment = talloc_asprintf(tctx, "comment: %d\n", time(NULL));
1084         }
1085
1086         ZERO_STRUCT(u);
1087
1088         switch (level) {
1089         case 21:
1090                 u.info21.fields_present = fields_present;
1091                 u.info21.password_expired = password_expired;
1092                 u.info21.comment.string = comment;
1093
1094                 break;
1095         case 23:
1096                 u.info23.info.fields_present = fields_present;
1097                 u.info23.info.password_expired = password_expired;
1098                 u.info23.info.comment.string = comment;
1099
1100                 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1101
1102                 break;
1103         case 24:
1104                 u.info24.password_expired = password_expired;
1105
1106                 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1107
1108                 break;
1109         case 25:
1110                 u.info25.info.fields_present = fields_present;
1111                 u.info25.info.password_expired = password_expired;
1112                 u.info25.info.comment.string = comment;
1113
1114                 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1115
1116                 break;
1117         case 26:
1118                 u.info26.password_expired = password_expired;
1119
1120                 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1121
1122                 break;
1123         }
1124
1125         status = dcerpc_fetch_session_key(p, &session_key);
1126         if (!NT_STATUS_IS_OK(status)) {
1127                 printf("SetUserInfo level %u - no session key - %s\n",
1128                        s.in.level, nt_errstr(status));
1129                 return false;
1130         }
1131
1132         generate_random_buffer((uint8_t *)confounder, 16);
1133
1134         MD5Init(&ctx);
1135         MD5Update(&ctx, confounder, 16);
1136         MD5Update(&ctx, session_key.data, session_key.length);
1137         MD5Final(confounded_session_key.data, &ctx);
1138
1139         switch (level) {
1140         case 23:
1141                 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1142                 break;
1143         case 24:
1144                 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1145                 break;
1146         case 25:
1147                 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1148                 memcpy(&u.info25.password.data[516], confounder, 16);
1149                 break;
1150         case 26:
1151                 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1152                 memcpy(&u.info26.password.data[516], confounder, 16);
1153                 break;
1154         }
1155
1156         if (use_setinfo2) {
1157                 status = dcerpc_samr_SetUserInfo2(p, tctx, &s2);
1158         } else {
1159                 status = dcerpc_samr_SetUserInfo(p, tctx, &s);
1160         }
1161
1162         if (!NT_STATUS_IS_OK(status)) {
1163                 if (fields_present == 0) {
1164                         expected_error = NT_STATUS_INVALID_PARAMETER;
1165                 }
1166                 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1167                         expected_error = NT_STATUS_ACCESS_DENIED;
1168                 }
1169         }
1170
1171         if (!NT_STATUS_IS_OK(expected_error)) {
1172                 if (use_setinfo2) {
1173                         torture_assert_ntstatus_equal(tctx,
1174                                 s2.out.result,
1175                                 expected_error, "SetUserInfo2 failed");
1176                 } else {
1177                         torture_assert_ntstatus_equal(tctx,
1178                                 s.out.result,
1179                                 expected_error, "SetUserInfo failed");
1180                 }
1181                 *matched_expected_error = true;
1182                 return true;
1183         }
1184
1185         if (!NT_STATUS_IS_OK(status)) {
1186                 printf("SetUserInfo%s level %u failed - %s\n",
1187                        use_setinfo2 ? "2":"", level, nt_errstr(status));
1188                 ret = false;
1189         } else {
1190                 if (level != 21) {
1191                         *password = newpass;
1192                 }
1193         }
1194
1195         return ret;
1196 }
1197
1198 static bool test_SetAliasInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1199                                struct policy_handle *handle)
1200 {
1201         NTSTATUS status;
1202         struct samr_SetAliasInfo r;
1203         struct samr_QueryAliasInfo q;
1204         union samr_AliasInfo *info;
1205         uint16_t levels[] = {2, 3};
1206         int i;
1207         bool ret = true;
1208
1209         /* Ignoring switch level 1, as that includes the number of members for the alias
1210          * and setting this to a wrong value might have negative consequences
1211          */
1212
1213         for (i=0;i<ARRAY_SIZE(levels);i++) {
1214                 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1215
1216                 r.in.alias_handle = handle;
1217                 r.in.level = levels[i];
1218                 r.in.info  = talloc(tctx, union samr_AliasInfo);
1219                 switch (r.in.level) {
1220                     case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1221                     case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1222                                 "Test Description, should test I18N as well"); break;
1223                     case ALIASINFOALL: printf("ALIASINFOALL ignored\n"); break;
1224                 }
1225
1226                 status = dcerpc_samr_SetAliasInfo(p, tctx, &r);
1227                 if (!NT_STATUS_IS_OK(status)) {
1228                         printf("SetAliasInfo level %u failed - %s\n",
1229                                levels[i], nt_errstr(status));
1230                         ret = false;
1231                 }
1232
1233                 q.in.alias_handle = handle;
1234                 q.in.level = levels[i];
1235                 q.out.info = &info;
1236
1237                 status = dcerpc_samr_QueryAliasInfo(p, tctx, &q);
1238                 if (!NT_STATUS_IS_OK(status)) {
1239                         printf("QueryAliasInfo level %u failed - %s\n",
1240                                levels[i], nt_errstr(status));
1241                         ret = false;
1242                 }
1243         }
1244
1245         return ret;
1246 }
1247
1248 static bool test_GetGroupsForUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1249                                   struct policy_handle *user_handle)
1250 {
1251         struct samr_GetGroupsForUser r;
1252         struct samr_RidWithAttributeArray *rids = NULL;
1253         NTSTATUS status;
1254
1255         torture_comment(tctx, "testing GetGroupsForUser\n");
1256
1257         r.in.user_handle = user_handle;
1258         r.out.rids = &rids;
1259
1260         status = dcerpc_samr_GetGroupsForUser(p, tctx, &r);
1261         torture_assert_ntstatus_ok(tctx, status, "GetGroupsForUser");
1262
1263         return true;
1264
1265 }
1266
1267 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1268                               struct lsa_String *domain_name)
1269 {
1270         NTSTATUS status;
1271         struct samr_GetDomPwInfo r;
1272         struct samr_PwInfo info;
1273
1274         r.in.domain_name = domain_name;
1275         r.out.info = &info;
1276
1277         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1278
1279         status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1280         torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1281
1282         r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1283         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1284
1285         status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1286         torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1287
1288         r.in.domain_name->string = "\\\\__NONAME__";
1289         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1290
1291         status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1292         torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1293
1294         r.in.domain_name->string = "\\\\Builtin";
1295         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1296
1297         status = dcerpc_samr_GetDomPwInfo(p, tctx, &r);
1298         torture_assert_ntstatus_ok(tctx, status, "GetDomPwInfo");
1299
1300         return true;
1301 }
1302
1303 static bool test_GetUserPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1304                                struct policy_handle *handle)
1305 {
1306         NTSTATUS status;
1307         struct samr_GetUserPwInfo r;
1308         struct samr_PwInfo info;
1309
1310         torture_comment(tctx, "Testing GetUserPwInfo\n");
1311
1312         r.in.user_handle = handle;
1313         r.out.info = &info;
1314
1315         status = dcerpc_samr_GetUserPwInfo(p, tctx, &r);
1316         torture_assert_ntstatus_ok(tctx, status, "GetUserPwInfo");
1317
1318         return true;
1319 }
1320
1321 static NTSTATUS test_LookupName(struct dcerpc_pipe *p, struct torture_context *tctx,
1322                                 struct policy_handle *domain_handle, const char *name,
1323                                 uint32_t *rid)
1324 {
1325         NTSTATUS status;
1326         struct samr_LookupNames n;
1327         struct lsa_String sname[2];
1328         struct samr_Ids rids, types;
1329
1330         init_lsa_String(&sname[0], name);
1331
1332         n.in.domain_handle = domain_handle;
1333         n.in.num_names = 1;
1334         n.in.names = sname;
1335         n.out.rids = &rids;
1336         n.out.types = &types;
1337         status = dcerpc_samr_LookupNames(p, tctx, &n);
1338         if (NT_STATUS_IS_OK(status)) {
1339                 *rid = n.out.rids->ids[0];
1340         } else {
1341                 return status;
1342         }
1343
1344         init_lsa_String(&sname[1], "xxNONAMExx");
1345         n.in.num_names = 2;
1346         status = dcerpc_samr_LookupNames(p, tctx, &n);
1347         if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1348                 printf("LookupNames[2] failed - %s\n", nt_errstr(status));              
1349                 if (NT_STATUS_IS_OK(status)) {
1350                         return NT_STATUS_UNSUCCESSFUL;
1351                 }
1352                 return status;
1353         }
1354
1355         n.in.num_names = 0;
1356         status = dcerpc_samr_LookupNames(p, tctx, &n);
1357         if (!NT_STATUS_IS_OK(status)) {
1358                 printf("LookupNames[0] failed - %s\n", nt_errstr(status));              
1359                 return status;
1360         }
1361
1362         init_lsa_String(&sname[0], "xxNONAMExx");
1363         n.in.num_names = 1;
1364         status = dcerpc_samr_LookupNames(p, tctx, &n);
1365         if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1366                 printf("LookupNames[1 bad name] failed - %s\n", nt_errstr(status));             
1367                 if (NT_STATUS_IS_OK(status)) {
1368                         return NT_STATUS_UNSUCCESSFUL;
1369                 }
1370                 return status;
1371         }
1372
1373         init_lsa_String(&sname[0], "xxNONAMExx");
1374         init_lsa_String(&sname[1], "xxNONAME2xx");
1375         n.in.num_names = 2;
1376         status = dcerpc_samr_LookupNames(p, tctx, &n);
1377         if (!NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
1378                 printf("LookupNames[2 bad names] failed - %s\n", nt_errstr(status));            
1379                 if (NT_STATUS_IS_OK(status)) {
1380                         return NT_STATUS_UNSUCCESSFUL;
1381                 }
1382                 return status;
1383         }
1384
1385         return NT_STATUS_OK;
1386 }
1387
1388 static NTSTATUS test_OpenUser_byname(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1389                                      struct policy_handle *domain_handle,
1390                                      const char *name, struct policy_handle *user_handle)
1391 {
1392         NTSTATUS status;
1393         struct samr_OpenUser r;
1394         uint32_t rid;
1395
1396         status = test_LookupName(p, mem_ctx, domain_handle, name, &rid);
1397         if (!NT_STATUS_IS_OK(status)) {
1398                 return status;
1399         }
1400
1401         r.in.domain_handle = domain_handle;
1402         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1403         r.in.rid = rid;
1404         r.out.user_handle = user_handle;
1405         status = dcerpc_samr_OpenUser(p, mem_ctx, &r);
1406         if (!NT_STATUS_IS_OK(status)) {
1407                 printf("OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(status));
1408         }
1409
1410         return status;
1411 }
1412
1413 #if 0
1414 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, 
1415                                    struct policy_handle *handle)
1416 {
1417         NTSTATUS status;
1418         struct samr_ChangePasswordUser r;
1419         bool ret = true;
1420         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1421         struct policy_handle user_handle;
1422         char *oldpass = "test";
1423         char *newpass = "test2";
1424         uint8_t old_nt_hash[16], new_nt_hash[16];
1425         uint8_t old_lm_hash[16], new_lm_hash[16];
1426
1427         status = test_OpenUser_byname(p, mem_ctx, handle, "testuser", &user_handle);
1428         if (!NT_STATUS_IS_OK(status)) {
1429                 return false;
1430         }
1431
1432         printf("Testing ChangePasswordUser for user 'testuser'\n");
1433
1434         printf("old password: %s\n", oldpass);
1435         printf("new password: %s\n", newpass);
1436
1437         E_md4hash(oldpass, old_nt_hash);
1438         E_md4hash(newpass, new_nt_hash);
1439         E_deshash(oldpass, old_lm_hash);
1440         E_deshash(newpass, new_lm_hash);
1441
1442         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1443         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1444         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1445         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1446         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1447         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1448
1449         r.in.handle = &user_handle;
1450         r.in.lm_present = 1;
1451         r.in.old_lm_crypted = &hash1;
1452         r.in.new_lm_crypted = &hash2;
1453         r.in.nt_present = 1;
1454         r.in.old_nt_crypted = &hash3;
1455         r.in.new_nt_crypted = &hash4;
1456         r.in.cross1_present = 1;
1457         r.in.nt_cross = &hash5;
1458         r.in.cross2_present = 1;
1459         r.in.lm_cross = &hash6;
1460
1461         status = dcerpc_samr_ChangePasswordUser(p, mem_ctx, &r);
1462         if (!NT_STATUS_IS_OK(status)) {
1463                 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1464                 ret = false;
1465         }
1466
1467         if (!test_samr_handle_Close(p, mem_ctx, &user_handle)) {
1468                 ret = false;
1469         }
1470
1471         return ret;
1472 }
1473 #endif
1474
1475 static bool test_ChangePasswordUser(struct dcerpc_pipe *p, struct torture_context *tctx,
1476                                     const char *acct_name, 
1477                                     struct policy_handle *handle, char **password)
1478 {
1479         NTSTATUS status;
1480         struct samr_ChangePasswordUser r;
1481         bool ret = true;
1482         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1483         struct policy_handle user_handle;
1484         char *oldpass;
1485         uint8_t old_nt_hash[16], new_nt_hash[16];
1486         uint8_t old_lm_hash[16], new_lm_hash[16];
1487         bool changed = true;
1488
1489         char *newpass;
1490         struct samr_GetUserPwInfo pwp;
1491         struct samr_PwInfo info;
1492         int policy_min_pw_len = 0;
1493
1494         status = test_OpenUser_byname(p, tctx, handle, acct_name, &user_handle);
1495         if (!NT_STATUS_IS_OK(status)) {
1496                 return false;
1497         }
1498         pwp.in.user_handle = &user_handle;
1499         pwp.out.info = &info;
1500
1501         status = dcerpc_samr_GetUserPwInfo(p, tctx, &pwp);
1502         if (NT_STATUS_IS_OK(status)) {
1503                 policy_min_pw_len = pwp.out.info->min_password_length;
1504         }
1505         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1506
1507         torture_comment(tctx, "Testing ChangePasswordUser\n");
1508
1509         torture_assert(tctx, *password != NULL, 
1510                                    "Failing ChangePasswordUser as old password was NULL.  Previous test failed?");
1511
1512         oldpass = *password;
1513
1514         E_md4hash(oldpass, old_nt_hash);
1515         E_md4hash(newpass, new_nt_hash);
1516         E_deshash(oldpass, old_lm_hash);
1517         E_deshash(newpass, new_lm_hash);
1518
1519         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1520         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1521         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1522         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1523         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1524         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1525
1526         r.in.user_handle = &user_handle;
1527         r.in.lm_present = 1;
1528         /* Break the LM hash */
1529         hash1.hash[0]++;
1530         r.in.old_lm_crypted = &hash1;
1531         r.in.new_lm_crypted = &hash2;
1532         r.in.nt_present = 1;
1533         r.in.old_nt_crypted = &hash3;
1534         r.in.new_nt_crypted = &hash4;
1535         r.in.cross1_present = 1;
1536         r.in.nt_cross = &hash5;
1537         r.in.cross2_present = 1;
1538         r.in.lm_cross = &hash6;
1539
1540         status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1541         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD,
1542                 "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1543
1544         /* Unbreak the LM hash */
1545         hash1.hash[0]--;
1546
1547         r.in.user_handle = &user_handle;
1548         r.in.lm_present = 1;
1549         r.in.old_lm_crypted = &hash1;
1550         r.in.new_lm_crypted = &hash2;
1551         /* Break the NT hash */
1552         hash3.hash[0]--;
1553         r.in.nt_present = 1;
1554         r.in.old_nt_crypted = &hash3;
1555         r.in.new_nt_crypted = &hash4;
1556         r.in.cross1_present = 1;
1557         r.in.nt_cross = &hash5;
1558         r.in.cross2_present = 1;
1559         r.in.lm_cross = &hash6;
1560
1561         status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1562         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_WRONG_PASSWORD, 
1563                 "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1564
1565         /* Unbreak the NT hash */
1566         hash3.hash[0]--;
1567
1568         r.in.user_handle = &user_handle;
1569         r.in.lm_present = 1;
1570         r.in.old_lm_crypted = &hash1;
1571         r.in.new_lm_crypted = &hash2;
1572         r.in.nt_present = 1;
1573         r.in.old_nt_crypted = &hash3;
1574         r.in.new_nt_crypted = &hash4;
1575         r.in.cross1_present = 1;
1576         r.in.nt_cross = &hash5;
1577         r.in.cross2_present = 1;
1578         /* Break the LM cross */
1579         hash6.hash[0]++;
1580         r.in.lm_cross = &hash6;
1581
1582         status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1583         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1584                 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM cross-hash, got %s\n", nt_errstr(status));
1585                 ret = false;
1586         }
1587
1588         /* Unbreak the LM cross */
1589         hash6.hash[0]--;
1590
1591         r.in.user_handle = &user_handle;
1592         r.in.lm_present = 1;
1593         r.in.old_lm_crypted = &hash1;
1594         r.in.new_lm_crypted = &hash2;
1595         r.in.nt_present = 1;
1596         r.in.old_nt_crypted = &hash3;
1597         r.in.new_nt_crypted = &hash4;
1598         r.in.cross1_present = 1;
1599         /* Break the NT cross */
1600         hash5.hash[0]++;
1601         r.in.nt_cross = &hash5;
1602         r.in.cross2_present = 1;
1603         r.in.lm_cross = &hash6;
1604
1605         status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1606         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1607                 printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the NT cross-hash, got %s\n", nt_errstr(status));
1608                 ret = false;
1609         }
1610
1611         /* Unbreak the NT cross */
1612         hash5.hash[0]--;
1613
1614
1615         /* Reset the hashes to not broken values */
1616         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1617         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1618         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1619         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1620         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1621         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1622
1623         r.in.user_handle = &user_handle;
1624         r.in.lm_present = 1;
1625         r.in.old_lm_crypted = &hash1;
1626         r.in.new_lm_crypted = &hash2;
1627         r.in.nt_present = 1;
1628         r.in.old_nt_crypted = &hash3;
1629         r.in.new_nt_crypted = &hash4;
1630         r.in.cross1_present = 1;
1631         r.in.nt_cross = &hash5;
1632         r.in.cross2_present = 0;
1633         r.in.lm_cross = NULL;
1634
1635         status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1636         if (NT_STATUS_IS_OK(status)) {
1637                 changed = true;
1638                 *password = newpass;
1639         } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1640                 printf("ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(status));
1641                 ret = false;
1642         }
1643
1644         oldpass = newpass;
1645         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1646
1647         E_md4hash(oldpass, old_nt_hash);
1648         E_md4hash(newpass, new_nt_hash);
1649         E_deshash(oldpass, old_lm_hash);
1650         E_deshash(newpass, new_lm_hash);
1651
1652
1653         /* Reset the hashes to not broken values */
1654         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1655         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1656         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1657         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1658         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1659         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1660
1661         r.in.user_handle = &user_handle;
1662         r.in.lm_present = 1;
1663         r.in.old_lm_crypted = &hash1;
1664         r.in.new_lm_crypted = &hash2;
1665         r.in.nt_present = 1;
1666         r.in.old_nt_crypted = &hash3;
1667         r.in.new_nt_crypted = &hash4;
1668         r.in.cross1_present = 0;
1669         r.in.nt_cross = NULL;
1670         r.in.cross2_present = 1;
1671         r.in.lm_cross = &hash6;
1672
1673         status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1674         if (NT_STATUS_IS_OK(status)) {
1675                 changed = true;
1676                 *password = newpass;
1677         } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, status)) {
1678                 printf("ChangePasswordUser failed: expected NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED, got %s\n", nt_errstr(status));
1679                 ret = false;
1680         }
1681
1682         oldpass = newpass;
1683         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1684
1685         E_md4hash(oldpass, old_nt_hash);
1686         E_md4hash(newpass, new_nt_hash);
1687         E_deshash(oldpass, old_lm_hash);
1688         E_deshash(newpass, new_lm_hash);
1689
1690
1691         /* Reset the hashes to not broken values */
1692         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1693         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1694         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1695         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1696         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1697         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1698
1699         r.in.user_handle = &user_handle;
1700         r.in.lm_present = 1;
1701         r.in.old_lm_crypted = &hash1;
1702         r.in.new_lm_crypted = &hash2;
1703         r.in.nt_present = 1;
1704         r.in.old_nt_crypted = &hash3;
1705         r.in.new_nt_crypted = &hash4;
1706         r.in.cross1_present = 1;
1707         r.in.nt_cross = &hash5;
1708         r.in.cross2_present = 1;
1709         r.in.lm_cross = &hash6;
1710
1711         status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1712         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1713                 printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1714         } else  if (!NT_STATUS_IS_OK(status)) {
1715                 printf("ChangePasswordUser failed - %s\n", nt_errstr(status));
1716                 ret = false;
1717         } else {
1718                 changed = true;
1719                 *password = newpass;
1720         }
1721
1722         r.in.user_handle = &user_handle;
1723         r.in.lm_present = 1;
1724         r.in.old_lm_crypted = &hash1;
1725         r.in.new_lm_crypted = &hash2;
1726         r.in.nt_present = 1;
1727         r.in.old_nt_crypted = &hash3;
1728         r.in.new_nt_crypted = &hash4;
1729         r.in.cross1_present = 1;
1730         r.in.nt_cross = &hash5;
1731         r.in.cross2_present = 1;
1732         r.in.lm_cross = &hash6;
1733
1734         if (changed) {
1735                 status = dcerpc_samr_ChangePasswordUser(p, tctx, &r);
1736                 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1737                         printf("ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1738                 } else if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1739                         printf("ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(status));
1740                         ret = false;
1741                 }
1742         }
1743
1744         
1745         if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1746                 ret = false;
1747         }
1748
1749         return ret;
1750 }
1751
1752
1753 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1754                                         const char *acct_name,
1755                                         struct policy_handle *handle, char **password)
1756 {
1757         NTSTATUS status;
1758         struct samr_OemChangePasswordUser2 r;
1759         bool ret = true;
1760         struct samr_Password lm_verifier;
1761         struct samr_CryptPassword lm_pass;
1762         struct lsa_AsciiString server, account, account_bad;
1763         char *oldpass;
1764         char *newpass;
1765         uint8_t old_lm_hash[16], new_lm_hash[16];
1766
1767         struct samr_GetDomPwInfo dom_pw_info;
1768         struct samr_PwInfo info;
1769         int policy_min_pw_len = 0;
1770
1771         struct lsa_String domain_name;
1772
1773         domain_name.string = "";
1774         dom_pw_info.in.domain_name = &domain_name;
1775         dom_pw_info.out.info = &info;
1776
1777         torture_comment(tctx, "Testing OemChangePasswordUser2\n");
1778
1779         torture_assert(tctx, *password != NULL, 
1780                                    "Failing OemChangePasswordUser2 as old password was NULL.  Previous test failed?");
1781
1782         oldpass = *password;
1783
1784         status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1785         if (NT_STATUS_IS_OK(status)) {
1786                 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1787         }
1788
1789         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1790
1791         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1792         account.string = acct_name;
1793
1794         E_deshash(oldpass, old_lm_hash);
1795         E_deshash(newpass, new_lm_hash);
1796
1797         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1798         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1799         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1800
1801         r.in.server = &server;
1802         r.in.account = &account;
1803         r.in.password = &lm_pass;
1804         r.in.hash = &lm_verifier;
1805
1806         /* Break the verification */
1807         lm_verifier.hash[0]++;
1808
1809         status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1810
1811         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1812             && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1813                 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
1814                         nt_errstr(status));
1815                 ret = false;
1816         }
1817
1818         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1819         /* Break the old password */
1820         old_lm_hash[0]++;
1821         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1822         /* unbreak it for the next operation */
1823         old_lm_hash[0]--;
1824         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1825
1826         r.in.server = &server;
1827         r.in.account = &account;
1828         r.in.password = &lm_pass;
1829         r.in.hash = &lm_verifier;
1830
1831         status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1832
1833         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1834             && !NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1835                 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
1836                         nt_errstr(status));
1837                 ret = false;
1838         }
1839
1840         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1841         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1842
1843         r.in.server = &server;
1844         r.in.account = &account;
1845         r.in.password = &lm_pass;
1846         r.in.hash = NULL;
1847
1848         status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1849
1850         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
1851             && !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1852                 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
1853                         nt_errstr(status));
1854                 ret = false;
1855         }
1856
1857         /* This shouldn't be a valid name */
1858         account_bad.string = TEST_ACCOUNT_NAME "XX";
1859         r.in.account = &account_bad;
1860
1861         status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1862
1863         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1864                 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
1865                         nt_errstr(status));
1866                 ret = false;
1867         }
1868
1869         /* This shouldn't be a valid name */
1870         account_bad.string = TEST_ACCOUNT_NAME "XX";
1871         r.in.account = &account_bad;
1872         r.in.password = &lm_pass;
1873         r.in.hash = &lm_verifier;
1874
1875         status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1876
1877         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
1878                 printf("OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
1879                         nt_errstr(status));
1880                 ret = false;
1881         }
1882
1883         /* This shouldn't be a valid name */
1884         account_bad.string = TEST_ACCOUNT_NAME "XX";
1885         r.in.account = &account_bad;
1886         r.in.password = NULL;
1887         r.in.hash = &lm_verifier;
1888
1889         status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1890
1891         if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1892                 printf("OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
1893                         nt_errstr(status));
1894                 ret = false;
1895         }
1896
1897         E_deshash(oldpass, old_lm_hash);
1898         E_deshash(newpass, new_lm_hash);
1899
1900         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
1901         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1902         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
1903
1904         r.in.server = &server;
1905         r.in.account = &account;
1906         r.in.password = &lm_pass;
1907         r.in.hash = &lm_verifier;
1908
1909         status = dcerpc_samr_OemChangePasswordUser2(p, tctx, &r);
1910         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1911                 printf("OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1912         } else if (!NT_STATUS_IS_OK(status)) {
1913                 printf("OemChangePasswordUser2 failed - %s\n", nt_errstr(status));
1914                 ret = false;
1915         } else {
1916                 *password = newpass;
1917         }
1918
1919         return ret;
1920 }
1921
1922
1923 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
1924                                      const char *acct_name,
1925                                      char **password,
1926                                      char *newpass, bool allow_password_restriction)
1927 {
1928         NTSTATUS status;
1929         struct samr_ChangePasswordUser2 r;
1930         bool ret = true;
1931         struct lsa_String server, account;
1932         struct samr_CryptPassword nt_pass, lm_pass;
1933         struct samr_Password nt_verifier, lm_verifier;
1934         char *oldpass;
1935         uint8_t old_nt_hash[16], new_nt_hash[16];
1936         uint8_t old_lm_hash[16], new_lm_hash[16];
1937
1938         struct samr_GetDomPwInfo dom_pw_info;
1939         struct samr_PwInfo info;
1940
1941         struct lsa_String domain_name;
1942
1943         domain_name.string = "";
1944         dom_pw_info.in.domain_name = &domain_name;
1945         dom_pw_info.out.info = &info;
1946
1947         torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
1948
1949         torture_assert(tctx, *password != NULL, 
1950                                    "Failing ChangePasswordUser2 as old password was NULL.  Previous test failed?");
1951         oldpass = *password;
1952
1953         if (!newpass) {
1954                 int policy_min_pw_len = 0;
1955                 status = dcerpc_samr_GetDomPwInfo(p, tctx, &dom_pw_info);
1956                 if (NT_STATUS_IS_OK(status)) {
1957                         policy_min_pw_len = dom_pw_info.out.info->min_password_length;
1958                 }
1959
1960                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
1961         } 
1962
1963         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1964         init_lsa_String(&account, acct_name);
1965
1966         E_md4hash(oldpass, old_nt_hash);
1967         E_md4hash(newpass, new_nt_hash);
1968
1969         E_deshash(oldpass, old_lm_hash);
1970         E_deshash(newpass, new_lm_hash);
1971
1972         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII|STR_TERMINATE);
1973         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
1974         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
1975
1976         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
1977         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
1978         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
1979
1980         r.in.server = &server;
1981         r.in.account = &account;
1982         r.in.nt_password = &nt_pass;
1983         r.in.nt_verifier = &nt_verifier;
1984         r.in.lm_change = 1;
1985         r.in.lm_password = &lm_pass;
1986         r.in.lm_verifier = &lm_verifier;
1987
1988         status = dcerpc_samr_ChangePasswordUser2(p, tctx, &r);
1989         if (allow_password_restriction && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
1990                 printf("ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(status));
1991         } else if (!NT_STATUS_IS_OK(status)) {
1992                 printf("ChangePasswordUser2 failed - %s\n", nt_errstr(status));
1993                 ret = false;
1994         } else {
1995                 *password = newpass;
1996         }
1997
1998         return ret;
1999 }
2000
2001
2002 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx, 
2003                               const char *account_string,
2004                               int policy_min_pw_len,
2005                               char **password,
2006                               const char *newpass,
2007                               NTTIME last_password_change,
2008                               bool handle_reject_reason)
2009 {
2010         NTSTATUS status;
2011         struct samr_ChangePasswordUser3 r;
2012         bool ret = true;
2013         struct lsa_String server, account, account_bad;
2014         struct samr_CryptPassword nt_pass, lm_pass;
2015         struct samr_Password nt_verifier, lm_verifier;
2016         char *oldpass;
2017         uint8_t old_nt_hash[16], new_nt_hash[16];
2018         uint8_t old_lm_hash[16], new_lm_hash[16];
2019         NTTIME t;
2020         struct samr_DomInfo1 *dominfo = NULL;
2021         struct samr_ChangeReject *reject = NULL;
2022
2023         torture_comment(tctx, "Testing ChangePasswordUser3\n");
2024
2025         if (newpass == NULL) {
2026                 do {
2027                         if (policy_min_pw_len == 0) {
2028                                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2029                         } else {
2030                                 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2031                         }
2032                 } while (check_password_quality(newpass) == false);
2033         } else {
2034                 torture_comment(tctx, "Using password '%s'\n", newpass);
2035         }
2036
2037         torture_assert(tctx, *password != NULL, 
2038                                    "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
2039
2040         oldpass = *password;
2041         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2042         init_lsa_String(&account, account_string);
2043
2044         E_md4hash(oldpass, old_nt_hash);
2045         E_md4hash(newpass, new_nt_hash);
2046
2047         E_deshash(oldpass, old_lm_hash);
2048         E_deshash(newpass, new_lm_hash);
2049
2050         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2051         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2052         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2053
2054         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2055         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2056         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2057         
2058         /* Break the verification */
2059         nt_verifier.hash[0]++;
2060
2061         r.in.server = &server;
2062         r.in.account = &account;
2063         r.in.nt_password = &nt_pass;
2064         r.in.nt_verifier = &nt_verifier;
2065         r.in.lm_change = 1;
2066         r.in.lm_password = &lm_pass;
2067         r.in.lm_verifier = &lm_verifier;
2068         r.in.password3 = NULL;
2069         r.out.dominfo = &dominfo;
2070         r.out.reject = &reject;
2071
2072         status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2073         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2074             (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2075                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2076                         nt_errstr(status));
2077                 ret = false;
2078         }
2079         
2080         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2081         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2082         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2083
2084         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2085         /* Break the NT hash */
2086         old_nt_hash[0]++;
2087         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2088         /* Unbreak it again */
2089         old_nt_hash[0]--;
2090         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2091         
2092         r.in.server = &server;
2093         r.in.account = &account;
2094         r.in.nt_password = &nt_pass;
2095         r.in.nt_verifier = &nt_verifier;
2096         r.in.lm_change = 1;
2097         r.in.lm_password = &lm_pass;
2098         r.in.lm_verifier = &lm_verifier;
2099         r.in.password3 = NULL;
2100         r.out.dominfo = &dominfo;
2101         r.out.reject = &reject;
2102
2103         status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2104         if (!NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION) &&
2105             (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD))) {
2106                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2107                         nt_errstr(status));
2108                 ret = false;
2109         }
2110         
2111         /* This shouldn't be a valid name */
2112         init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2113
2114         r.in.account = &account_bad;
2115         status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2116         if (!NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
2117                 printf("ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2118                         nt_errstr(status));
2119                 ret = false;
2120         }
2121
2122         E_md4hash(oldpass, old_nt_hash);
2123         E_md4hash(newpass, new_nt_hash);
2124
2125         E_deshash(oldpass, old_lm_hash);
2126         E_deshash(newpass, new_lm_hash);
2127
2128         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2129         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2130         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2131
2132         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2133         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2134         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2135
2136         r.in.server = &server;
2137         r.in.account = &account;
2138         r.in.nt_password = &nt_pass;
2139         r.in.nt_verifier = &nt_verifier;
2140         r.in.lm_change = 1;
2141         r.in.lm_password = &lm_pass;
2142         r.in.lm_verifier = &lm_verifier;
2143         r.in.password3 = NULL;
2144         r.out.dominfo = &dominfo;
2145         r.out.reject = &reject;
2146
2147         unix_to_nt_time(&t, time(NULL));
2148
2149         status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2150
2151         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)
2152             && dominfo
2153             && reject
2154             && handle_reject_reason
2155             && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2156                 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2157
2158                         if (reject && (reject->reason != SAMR_REJECT_OTHER)) {
2159                                 printf("expected SAMR_REJECT_OTHER (%d), got %d\n", 
2160                                         SAMR_REJECT_OTHER, reject->reason);
2161                                 return false;
2162                         }
2163                 }
2164
2165                 /* We tested the order of precendence which is as follows:
2166                 
2167                 * pwd min_age 
2168                 * pwd length
2169                 * pwd complexity
2170                 * pwd history
2171
2172                 Guenther */
2173
2174                 if ((dominfo->min_password_age > 0) && !null_nttime(last_password_change) &&
2175                            (last_password_change + dominfo->min_password_age > t)) {
2176
2177                         if (reject->reason != SAMR_REJECT_OTHER) {
2178                                 printf("expected SAMR_REJECT_OTHER (%d), got %d\n", 
2179                                         SAMR_REJECT_OTHER, reject->reason);
2180                                 return false;
2181                         }
2182
2183                 } else if ((dominfo->min_password_length > 0) &&
2184                            (strlen(newpass) < dominfo->min_password_length)) {
2185
2186                         if (reject->reason != SAMR_REJECT_TOO_SHORT) {
2187                                 printf("expected SAMR_REJECT_TOO_SHORT (%d), got %d\n", 
2188                                         SAMR_REJECT_TOO_SHORT, reject->reason);
2189                                 return false;
2190                         }
2191
2192                 } else if ((dominfo->password_history_length > 0) &&
2193                             strequal(oldpass, newpass)) {
2194
2195                         if (reject->reason != SAMR_REJECT_IN_HISTORY) {
2196                                 printf("expected SAMR_REJECT_IN_HISTORY (%d), got %d\n", 
2197                                         SAMR_REJECT_IN_HISTORY, reject->reason);
2198                                 return false;
2199                         }
2200                 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2201
2202                         if (reject->reason != SAMR_REJECT_COMPLEXITY) {
2203                                 printf("expected SAMR_REJECT_COMPLEXITY (%d), got %d\n", 
2204                                         SAMR_REJECT_COMPLEXITY, reject->reason);
2205                                 return false;
2206                         }
2207
2208                 }
2209
2210                 if (reject->reason == SAMR_REJECT_TOO_SHORT) {
2211                         /* retry with adjusted size */
2212                         return test_ChangePasswordUser3(p, tctx, account_string, 
2213                                                         dominfo->min_password_length,
2214                                                         password, NULL, 0, false); 
2215
2216                 }
2217
2218         } else if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2219                 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2220                         printf("expected SAMR_REJECT_OTHER (%d), got %d\n", 
2221                                SAMR_REJECT_OTHER, reject->reason);
2222                         return false;
2223                 }
2224                 /* Perhaps the server has a 'min password age' set? */
2225
2226         } else { 
2227                 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3");
2228                 *password = talloc_strdup(tctx, newpass);
2229         }
2230
2231         return ret;
2232 }
2233
2234 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2235                                     const char *account_string,
2236                                     struct policy_handle *handle, 
2237                                     char **password)
2238 {
2239         NTSTATUS status;
2240         struct samr_ChangePasswordUser3 r;
2241         struct samr_SetUserInfo s;
2242         union samr_UserInfo u;
2243         DATA_BLOB session_key;
2244         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2245         uint8_t confounder[16];
2246         struct MD5Context ctx;
2247
2248         bool ret = true;
2249         struct lsa_String server, account;
2250         struct samr_CryptPassword nt_pass;
2251         struct samr_Password nt_verifier;
2252         DATA_BLOB new_random_pass;
2253         char *newpass;
2254         char *oldpass;
2255         uint8_t old_nt_hash[16], new_nt_hash[16];
2256         NTTIME t;
2257         struct samr_DomInfo1 *dominfo = NULL;
2258         struct samr_ChangeReject *reject = NULL;
2259
2260         new_random_pass = samr_very_rand_pass(tctx, 128);
2261
2262         torture_assert(tctx, *password != NULL, 
2263                                    "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
2264
2265         oldpass = *password;
2266         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2267         init_lsa_String(&account, account_string);
2268
2269         s.in.user_handle = handle;
2270         s.in.info = &u;
2271         s.in.level = 25;
2272
2273         ZERO_STRUCT(u);
2274
2275         u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2276
2277         set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2278
2279         status = dcerpc_fetch_session_key(p, &session_key);
2280         if (!NT_STATUS_IS_OK(status)) {
2281                 printf("SetUserInfo level %u - no session key - %s\n",
2282                        s.in.level, nt_errstr(status));
2283                 return false;
2284         }
2285
2286         generate_random_buffer((uint8_t *)confounder, 16);
2287
2288         MD5Init(&ctx);
2289         MD5Update(&ctx, confounder, 16);
2290         MD5Update(&ctx, session_key.data, session_key.length);
2291         MD5Final(confounded_session_key.data, &ctx);
2292
2293         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2294         memcpy(&u.info25.password.data[516], confounder, 16);
2295
2296         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2297
2298         status = dcerpc_samr_SetUserInfo(p, tctx, &s);
2299         if (!NT_STATUS_IS_OK(status)) {
2300                 printf("SetUserInfo level %u failed - %s\n",
2301                        s.in.level, nt_errstr(status));
2302                 ret = false;
2303         }
2304
2305         torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2306
2307         mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2308
2309         new_random_pass = samr_very_rand_pass(tctx, 128);
2310
2311         mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2312
2313         set_pw_in_buffer(nt_pass.data, &new_random_pass);
2314         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2315         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2316
2317         r.in.server = &server;
2318         r.in.account = &account;
2319         r.in.nt_password = &nt_pass;
2320         r.in.nt_verifier = &nt_verifier;
2321         r.in.lm_change = 0;
2322         r.in.lm_password = NULL;
2323         r.in.lm_verifier = NULL;
2324         r.in.password3 = NULL;
2325         r.out.dominfo = &dominfo;
2326         r.out.reject = &reject;
2327
2328         unix_to_nt_time(&t, time(NULL));
2329
2330         status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2331
2332         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2333                 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2334                         printf("expected SAMR_REJECT_OTHER (%d), got %d\n", 
2335                                SAMR_REJECT_OTHER, reject->reason);
2336                         return false;
2337                 }
2338                 /* Perhaps the server has a 'min password age' set? */
2339
2340         } else if (!NT_STATUS_IS_OK(status)) {
2341                 printf("ChangePasswordUser3 failed - %s\n", nt_errstr(status));
2342                 ret = false;
2343         }
2344         
2345         newpass = samr_rand_pass(tctx, 128);
2346
2347         mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2348
2349         E_md4hash(newpass, new_nt_hash);
2350
2351         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2352         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2353         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2354
2355         r.in.server = &server;
2356         r.in.account = &account;
2357         r.in.nt_password = &nt_pass;
2358         r.in.nt_verifier = &nt_verifier;
2359         r.in.lm_change = 0;
2360         r.in.lm_password = NULL;
2361         r.in.lm_verifier = NULL;
2362         r.in.password3 = NULL;
2363         r.out.dominfo = &dominfo;
2364         r.out.reject = &reject;
2365
2366         unix_to_nt_time(&t, time(NULL));
2367
2368         status = dcerpc_samr_ChangePasswordUser3(p, tctx, &r);
2369
2370         if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
2371                 if (reject && reject->reason != SAMR_REJECT_OTHER) {
2372                         printf("expected SAMR_REJECT_OTHER (%d), got %d\n", 
2373                                SAMR_REJECT_OTHER, reject->reason);
2374                         return false;
2375                 }
2376                 /* Perhaps the server has a 'min password age' set? */
2377
2378         } else {
2379                 torture_assert_ntstatus_ok(tctx, status, "ChangePasswordUser3 (on second random password)");
2380                 *password = talloc_strdup(tctx, newpass);
2381         }
2382
2383         return ret;
2384 }
2385
2386
2387 static bool test_GetMembersInAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2388                                   struct policy_handle *alias_handle)
2389 {
2390         struct samr_GetMembersInAlias r;
2391         struct lsa_SidArray sids;
2392         NTSTATUS status;
2393
2394         torture_comment(tctx, "Testing GetMembersInAlias\n");
2395
2396         r.in.alias_handle = alias_handle;
2397         r.out.sids = &sids;
2398
2399         status = dcerpc_samr_GetMembersInAlias(p, tctx, &r);
2400         torture_assert_ntstatus_ok(tctx, status, "GetMembersInAlias");
2401
2402         return true;
2403 }
2404
2405 static bool test_AddMemberToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2406                                   struct policy_handle *alias_handle,
2407                                   const struct dom_sid *domain_sid)
2408 {
2409         struct samr_AddAliasMember r;
2410         struct samr_DeleteAliasMember d;
2411         NTSTATUS status;
2412         struct dom_sid *sid;
2413
2414         sid = dom_sid_add_rid(tctx, domain_sid, 512);
2415
2416         torture_comment(tctx, "testing AddAliasMember\n");
2417         r.in.alias_handle = alias_handle;
2418         r.in.sid = sid;
2419
2420         status = dcerpc_samr_AddAliasMember(p, tctx, &r);
2421         torture_assert_ntstatus_ok(tctx, status, "AddAliasMember");
2422
2423         d.in.alias_handle = alias_handle;
2424         d.in.sid = sid;
2425
2426         status = dcerpc_samr_DeleteAliasMember(p, tctx, &d);
2427         torture_assert_ntstatus_ok(tctx, status, "DelAliasMember");
2428
2429         return true;
2430 }
2431
2432 static bool test_AddMultipleMembersToAlias(struct dcerpc_pipe *p, struct torture_context *tctx,
2433                                            struct policy_handle *alias_handle)
2434 {
2435         struct samr_AddMultipleMembersToAlias a;
2436         struct samr_RemoveMultipleMembersFromAlias r;
2437         NTSTATUS status;
2438         struct lsa_SidArray sids;
2439
2440         torture_comment(tctx, "testing AddMultipleMembersToAlias\n");
2441         a.in.alias_handle = alias_handle;
2442         a.in.sids = &sids;
2443
2444         sids.num_sids = 3;
2445         sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2446
2447         sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2448         sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2449         sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2450
2451         status = dcerpc_samr_AddMultipleMembersToAlias(p, tctx, &a);
2452         torture_assert_ntstatus_ok(tctx, status, "AddMultipleMembersToAlias");
2453
2454
2455         torture_comment(tctx, "testing RemoveMultipleMembersFromAlias\n");
2456         r.in.alias_handle = alias_handle;
2457         r.in.sids = &sids;
2458
2459         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2460         torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2461
2462         /* strange! removing twice doesn't give any error */
2463         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2464         torture_assert_ntstatus_ok(tctx, status, "RemoveMultipleMembersFromAlias");
2465
2466         /* but removing an alias that isn't there does */
2467         sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2468
2469         status = dcerpc_samr_RemoveMultipleMembersFromAlias(p, tctx, &r);
2470         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2471
2472         return true;
2473 }
2474
2475 static bool test_TestPrivateFunctionsUser(struct dcerpc_pipe *p, struct torture_context *tctx,
2476                                             struct policy_handle *user_handle)
2477 {
2478         struct samr_TestPrivateFunctionsUser r;
2479         NTSTATUS status;
2480
2481         torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2482
2483         r.in.user_handle = user_handle;
2484
2485         status = dcerpc_samr_TestPrivateFunctionsUser(p, tctx, &r);
2486         torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2487
2488         return true;
2489 }
2490
2491 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_pipe *p,
2492                                           struct torture_context *tctx,
2493                                           struct policy_handle *handle,
2494                                           bool use_info2,
2495                                           NTTIME *pwdlastset)
2496 {
2497         NTSTATUS status;
2498         uint16_t levels[] = { /* 3, */ 5, 21 };
2499         int i;
2500         NTTIME pwdlastset3 = 0;
2501         NTTIME pwdlastset5 = 0;
2502         NTTIME pwdlastset21 = 0;
2503
2504         torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2505                         use_info2 ? "2":"");
2506
2507         for (i=0; i<ARRAY_SIZE(levels); i++) {
2508
2509                 struct samr_QueryUserInfo r;
2510                 struct samr_QueryUserInfo2 r2;
2511                 union samr_UserInfo *info;
2512
2513                 if (use_info2) {
2514                         r2.in.user_handle = handle;
2515                         r2.in.level = levels[i];
2516                         r2.out.info = &info;
2517                         status = dcerpc_samr_QueryUserInfo2(p, tctx, &r2);
2518
2519                 } else {
2520                         r.in.user_handle = handle;
2521                         r.in.level = levels[i];
2522                         r.out.info = &info;
2523                         status = dcerpc_samr_QueryUserInfo(p, tctx, &r);
2524                 }
2525
2526                 if (!NT_STATUS_IS_OK(status) &&
2527                     !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2528                         printf("QueryUserInfo%s level %u failed - %s\n",
2529                                use_info2 ? "2":"", levels[i], nt_errstr(status));
2530                         return false;
2531                 }
2532
2533                 switch (levels[i]) {
2534                 case 3:
2535                         pwdlastset3 = info->info3.last_password_change;
2536                         break;
2537                 case 5:
2538                         pwdlastset5 = info->info5.last_password_change;
2539                         break;
2540                 case 21:
2541                         pwdlastset21 = info->info21.last_password_change;
2542                         break;
2543                 default:
2544                         return false;
2545                 }
2546         }
2547         /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2548                                     "pwdlastset mixup"); */
2549         torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2550                                  "pwdlastset mixup");
2551
2552         *pwdlastset = pwdlastset21;
2553
2554         torture_comment(tctx, "(pwdlastset: %lld)\n", *pwdlastset);
2555
2556         return true;
2557 }
2558
2559 static bool test_SetPassword_level(struct dcerpc_pipe *p,
2560                                    struct torture_context *tctx,
2561                                    struct policy_handle *handle,
2562                                    uint16_t level,
2563                                    uint32_t fields_present,
2564                                    uint8_t password_expired,
2565                                    bool *matched_expected_error,
2566                                    bool use_setinfo2,
2567                                    char **password,
2568                                    bool use_queryinfo2,
2569                                    NTTIME *pwdlastset)
2570 {
2571         const char *fields = NULL;
2572         bool ret = true;
2573
2574         switch (level) {
2575         case 21:
2576         case 23:
2577         case 25:
2578                 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
2579                                          fields_present);
2580                 break;
2581         default:
2582                 break;
2583         }
2584
2585         torture_comment(tctx, "Testing SetUserInfo%s level %d call "
2586                 "(password_expired: %d) %s\n",
2587                 use_setinfo2 ? "2":"", level, password_expired,
2588                 fields ? fields : "");
2589
2590         switch (level) {
2591                 case 21:
2592                 case 23:
2593                 case 24:
2594                 case 25:
2595                 case 26:
2596                         if (!test_SetUserPass_level_ex(p, tctx, handle, level,
2597                                                        fields_present,
2598                                                        password,
2599                                                        password_expired,
2600                                                        use_setinfo2,
2601                                                        matched_expected_error)) {
2602                                 ret = false;
2603                         }
2604                         break;
2605                 default:
2606                         return false;
2607         }
2608
2609         if (!test_QueryUserInfo_pwdlastset(p, tctx, handle,
2610                                            use_queryinfo2,
2611                                            pwdlastset)) {
2612                 ret = false;
2613         }
2614
2615         return ret;
2616 }
2617
2618 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
2619                                         struct torture_context *tctx,
2620                                         uint32_t acct_flags,
2621                                         struct policy_handle *handle,
2622                                         char **password)
2623 {
2624         int i, s = 0, q = 0, f = 0;
2625         bool ret = true;
2626         int delay = 500000;
2627         bool set_levels[] = { false, true };
2628         bool query_levels[] = { false, true };
2629         uint32_t fields_present[] = {
2630                 0,
2631                 SAMR_FIELD_EXPIRED_FLAG,
2632                 SAMR_FIELD_LAST_PWD_CHANGE,
2633                 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
2634                 SAMR_FIELD_COMMENT,
2635                 SAMR_FIELD_NT_PASSWORD_PRESENT,
2636                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2637                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
2638                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
2639                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2640                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
2641                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
2642         };
2643
2644         struct {
2645                 uint16_t level;
2646                 uint8_t password_expired_nonzero;
2647         } pwd_tests[] = {
2648
2649                 /* level 21 */
2650                 {
2651                         .level                          = 21,
2652                         .password_expired_nonzero       = 1,
2653                 },{
2654                         .level                          = 21,
2655                         .password_expired_nonzero       = 24,
2656
2657                 /* level 23 */
2658                 },{
2659                         .level                          = 23,
2660                         .password_expired_nonzero       = 1,
2661                 },{
2662                         .level                          = 23,
2663                         .password_expired_nonzero       = 24,
2664                 },{
2665
2666                 /* level 24 */
2667
2668                         .level                          = 24,
2669                         .password_expired_nonzero       = 1,
2670                 },{
2671                         .level                          = 24,
2672                         .password_expired_nonzero       = 24,
2673                 },{
2674
2675                 /* level 25 */
2676
2677                         .level                          = 25,
2678                         .password_expired_nonzero       = 1,
2679                 },{
2680                         .level                          = 25,
2681                         .password_expired_nonzero       = 24
2682                 },{
2683
2684                 /* level 26 */
2685
2686                         .level                          = 26,
2687                         .password_expired_nonzero       = 1,
2688                 },{
2689                         .level                          = 26,
2690                         .password_expired_nonzero       = 24,
2691                 }
2692         };
2693
2694         if (torture_setting_bool(tctx, "samba3", false)) {
2695                 delay = 1000000;
2696                 printf("Samba3 has second granularity, setting delay to: %d\n",
2697                         delay);
2698         }
2699
2700         /* set to 1 to enable testing for all possible opcode
2701            (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
2702            combinations */
2703 #if 0
2704 #define TEST_SET_LEVELS 1
2705 #define TEST_QUERY_LEVELS 1
2706 #endif
2707         for (i=0; i<ARRAY_SIZE(pwd_tests); i++) {
2708         for (f=0; f<ARRAY_SIZE(fields_present); f++) {
2709 #ifdef TEST_SET_LEVELS
2710         for (s=0; s<ARRAY_SIZE(set_levels); s++) {
2711 #endif
2712 #ifdef TEST_QUERY_LEVELS
2713         for (q=0; q<ARRAY_SIZE(query_levels); q++) {
2714 #endif
2715                 NTTIME pwdlastset_old = 0;
2716                 NTTIME pwdlastset_new = 0;
2717                 bool matched_expected_error = false;
2718
2719                 torture_comment(tctx, "------------------------------\n"
2720                                 "Testing pwdLastSet attribute for flags: 0x%08x "
2721                                 "(s: %d (l: %d), q: %d)\n",
2722                                 acct_flags, s, pwd_tests[i].level, q);
2723
2724                 /* set #1 */
2725
2726                 /* set a password and force password change (pwdlastset 0) by
2727                  * setting the password expired flag to a non-0 value */
2728
2729                 if (!test_SetPassword_level(p, tctx, handle,
2730                                             pwd_tests[i].level,
2731                                             fields_present[f],
2732                                             pwd_tests[i].password_expired_nonzero,
2733                                             &matched_expected_error,
2734                                             set_levels[s],
2735                                             password,
2736                                             query_levels[q],
2737                                             &pwdlastset_old)) {
2738                         ret = false;
2739                 }
2740
2741                 if (matched_expected_error == true) {
2742                         /* skipping on expected failure */
2743                         continue;
2744                 }
2745
2746                 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2747                  * set without the SAMR_FIELD_EXPIRED_FLAG */
2748
2749                 switch (pwd_tests[i].level) {
2750                 case 21:
2751                 case 23:
2752                 case 25:
2753                         if ((pwdlastset_new != 0) &&
2754                             !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
2755                                 torture_comment(tctx, "not considering a non-0 "
2756                                         "pwdLastSet as a an error as the "
2757                                         "SAMR_FIELD_EXPIRED_FLAG has not "
2758                                         "been set\n");
2759                                 break;
2760                         }
2761                 default:
2762                         if (pwdlastset_new != 0) {
2763                                 torture_warning(tctx, "pwdLastSet test failed: "
2764                                         "expected pwdLastSet 0 but got %lld\n",
2765                                         pwdlastset_old);
2766                                 ret = false;
2767                         }
2768                         break;
2769                 }
2770
2771                 switch (pwd_tests[i].level) {
2772                 case 21:
2773                 case 23:
2774                 case 25:
2775                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2776                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
2777                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2778                              (pwdlastset_old >= pwdlastset_new)) {
2779                                 torture_warning(tctx, "pwdlastset not increasing\n");
2780                                 ret = false;
2781                         }
2782                         break;
2783                 default:
2784                         if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2785                             (pwdlastset_old >= pwdlastset_new)) {
2786                                 torture_warning(tctx, "pwdlastset not increasing\n");
2787                                 ret = false;
2788                         }
2789                         break;
2790                 }
2791
2792                 usleep(delay);
2793
2794                 /* set #2 */
2795
2796                 /* set a password, pwdlastset needs to get updated (increased
2797                  * value), password_expired value used here is 0 */
2798
2799                 if (!test_SetPassword_level(p, tctx, handle,
2800                                             pwd_tests[i].level,
2801                                             fields_present[f],
2802                                             0,
2803                                             &matched_expected_error,
2804                                             set_levels[s],
2805                                             password,
2806                                             query_levels[q],
2807                                             &pwdlastset_new)) {
2808                         ret = false;
2809                 }
2810
2811                 /* when a password has been changed, pwdlastset must not be 0 afterwards
2812                  * and must be larger then the old value */
2813
2814                 switch (pwd_tests[i].level) {
2815                 case 21:
2816                 case 23:
2817                 case 25:
2818
2819                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
2820                          * password has been changed, old and new pwdlastset
2821                          * need to be the same value */
2822
2823                         if (!(pwd_tests[i].fields_present & SAMR_FIELD_EXPIRED_FLAG) &&
2824                             !((pwd_tests[i].fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2825                               (pwd_tests[i].fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT)))
2826                         {
2827                                 torture_assert_int_equal(tctx, pwdlastset_old,
2828                                         pwdlastset_new, "pwdlastset must be equal");
2829                                 break;
2830                         }
2831                 default:
2832                         if (pwdlastset_old >= pwdlastset_new) {
2833                                 torture_warning(tctx, "pwdLastSet test failed: "
2834                                         "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
2835                                         pwdlastset_old, pwdlastset_new);
2836                                 ret = false;
2837                         }
2838                         if (pwdlastset_new == 0) {
2839                                 torture_warning(tctx, "pwdLastSet test failed: "
2840                                         "expected non-0 pwdlastset, got: %lld\n",
2841                                         pwdlastset_new);
2842                                 ret = false;
2843                         }
2844                 }
2845
2846                 switch (pwd_tests[i].level) {
2847                 case 21:
2848                 case 23:
2849                 case 25:
2850                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2851                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
2852                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2853                              (pwdlastset_old >= pwdlastset_new)) {
2854                                 torture_warning(tctx, "pwdlastset not increasing\n");
2855                                 ret = false;
2856                         }
2857                         break;
2858                 default:
2859                         if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2860                             (pwdlastset_old >= pwdlastset_new)) {
2861                                 torture_warning(tctx, "pwdlastset not increasing\n");
2862                                 ret = false;
2863                         }
2864                         break;
2865                 }
2866
2867                 pwdlastset_old = pwdlastset_new;
2868
2869                 usleep(delay);
2870
2871                 /* set #2b */
2872
2873                 /* set a password, pwdlastset needs to get updated (increased
2874                  * value), password_expired value used here is 0 */
2875
2876                 if (!test_SetPassword_level(p, tctx, handle,
2877                                             pwd_tests[i].level,
2878                                             fields_present[f],
2879                                             0,
2880                                             &matched_expected_error,
2881                                             set_levels[s],
2882                                             password,
2883                                             query_levels[q],
2884                                             &pwdlastset_new)) {
2885                         ret = false;
2886                 }
2887
2888                 /* when a password has been changed, pwdlastset must not be 0 afterwards
2889                  * and must be larger then the old value */
2890
2891                 switch (pwd_tests[i].level) {
2892                 case 21:
2893                 case 23:
2894                 case 25:
2895
2896                         /* if no password has been changed, old and new pwdlastset
2897                          * need to be the same value */
2898
2899                         if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2900                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
2901                         {
2902                                 torture_assert_int_equal(tctx, pwdlastset_old,
2903                                         pwdlastset_new, "pwdlastset must be equal");
2904                                 break;
2905                         }
2906                 default:
2907                         if (pwdlastset_old >= pwdlastset_new) {
2908                                 torture_warning(tctx, "pwdLastSet test failed: "
2909                                         "expected last pwdlastset (%lld) < new pwdlastset (%lld)\n",
2910                                         pwdlastset_old, pwdlastset_new);
2911                                 ret = false;
2912                         }
2913                         if (pwdlastset_new == 0) {
2914                                 torture_warning(tctx, "pwdLastSet test failed: "
2915                                         "expected non-0 pwdlastset, got: %lld\n",
2916                                         pwdlastset_new);
2917                                 ret = false;
2918                         }
2919                 }
2920
2921                 /* set #3 */
2922
2923                 /* set a password and force password change (pwdlastset 0) by
2924                  * setting the password expired flag to a non-0 value */
2925
2926                 if (!test_SetPassword_level(p, tctx, handle,
2927                                             pwd_tests[i].level,
2928                                             fields_present[f],
2929                                             pwd_tests[i].password_expired_nonzero,
2930                                             &matched_expected_error,
2931                                             set_levels[s],
2932                                             password,
2933                                             query_levels[q],
2934                                             &pwdlastset_new)) {
2935                         ret = false;
2936                 }
2937
2938                 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
2939                  * set without the SAMR_FIELD_EXPIRED_FLAG */
2940
2941                 switch (pwd_tests[i].level) {
2942                 case 21:
2943                 case 23:
2944                 case 25:
2945                         if ((pwdlastset_new != 0) &&
2946                             !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
2947                                 torture_comment(tctx, "not considering a non-0 "
2948                                         "pwdLastSet as a an error as the "
2949                                         "SAMR_FIELD_EXPIRED_FLAG has not "
2950                                         "been set\n");
2951                                 break;
2952                         }
2953
2954                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
2955                          * password has been changed, old and new pwdlastset
2956                          * need to be the same value */
2957
2958                         if (!(pwd_tests[i].fields_present & SAMR_FIELD_EXPIRED_FLAG) &&
2959                             !((pwd_tests[i].fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2960                               (pwd_tests[i].fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT)))
2961                         {
2962                                 torture_assert_int_equal(tctx, pwdlastset_old,
2963                                         pwdlastset_new, "pwdlastset must be equal");
2964                                 break;
2965                         }
2966                 default:
2967
2968                         if (pwdlastset_old == pwdlastset_new) {
2969                                 torture_warning(tctx, "pwdLastSet test failed: "
2970                                         "expected last pwdlastset (%lld) != new pwdlastset (%lld)\n",
2971                                         pwdlastset_old, pwdlastset_new);
2972                                 ret = false;
2973                         }
2974
2975                         if (pwdlastset_new != 0) {
2976                                 torture_warning(tctx, "pwdLastSet test failed: "
2977                                         "expected pwdLastSet 0, got %lld\n",
2978                                         pwdlastset_old);
2979                                 ret = false;
2980                         }
2981                         break;
2982                 }
2983
2984                 switch (pwd_tests[i].level) {
2985                 case 21:
2986                 case 23:
2987                 case 25:
2988                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
2989                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
2990                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2991                              (pwdlastset_old >= pwdlastset_new)) {
2992                                 torture_warning(tctx, "pwdlastset not increasing\n");
2993                                 ret = false;
2994                         }
2995                         break;
2996                 default:
2997                         if ((pwdlastset_old > 0) && (pwdlastset_new > 0) &&
2998                             (pwdlastset_old >= pwdlastset_new)) {
2999                                 torture_warning(tctx, "pwdlastset not increasing\n");
3000                                 ret = false;
3001                         }
3002                         break;
3003                 }
3004
3005                 switch (pwd_tests[i].level) {
3006                 case 24:
3007                 case 26:
3008                         f = ARRAY_SIZE(fields_present);
3009                         break;
3010                 }
3011
3012 #ifdef TEST_QUERY_LEVELS
3013         }
3014 #endif
3015 #ifdef TEST_SET_LEVELS
3016         }
3017 #endif
3018         }
3019         }
3020
3021 #undef TEST_SET_LEVELS
3022 #undef TEST_QUERY_LEVELS
3023
3024         return ret;
3025 }
3026
3027 static bool test_user_ops(struct dcerpc_pipe *p, 
3028                           struct torture_context *tctx,
3029                           struct policy_handle *user_handle, 
3030                           struct policy_handle *domain_handle, 
3031                           uint32_t base_acct_flags, 
3032                           const char *base_acct_name, enum torture_samr_choice which_ops)
3033 {
3034         char *password = NULL;
3035         struct samr_QueryUserInfo q;
3036         union samr_UserInfo *info;
3037         NTSTATUS status;
3038
3039         bool ret = true;
3040         int i;
3041         uint32_t rid;
3042         const uint32_t password_fields[] = {
3043                 SAMR_FIELD_NT_PASSWORD_PRESENT,
3044                 SAMR_FIELD_LM_PASSWORD_PRESENT,
3045                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3046                 0
3047         };
3048         
3049         status = test_LookupName(p, tctx, domain_handle, base_acct_name, &rid);
3050         if (!NT_STATUS_IS_OK(status)) {
3051                 ret = false;
3052         }
3053
3054         switch (which_ops) {
3055         case TORTURE_SAMR_USER_ATTRIBUTES:
3056                 if (!test_QuerySecurity(p, tctx, user_handle)) {
3057                         ret = false;
3058                 }
3059
3060                 if (!test_QueryUserInfo(p, tctx, user_handle)) {
3061                         ret = false;
3062                 }
3063
3064                 if (!test_QueryUserInfo2(p, tctx, user_handle)) {
3065                         ret = false;
3066                 }
3067
3068                 if (!test_SetUserInfo(p, tctx, user_handle, base_acct_flags,
3069                                       base_acct_name)) {
3070                         ret = false;
3071                 }       
3072
3073                 if (!test_GetUserPwInfo(p, tctx, user_handle)) {
3074                         ret = false;
3075                 }
3076
3077                 if (!test_TestPrivateFunctionsUser(p, tctx, user_handle)) {
3078                         ret = false;
3079                 }
3080
3081                 if (!test_SetUserPass(p, tctx, user_handle, &password)) {
3082                         ret = false;
3083                 }
3084                 break;
3085         case TORTURE_SAMR_PASSWORDS:
3086                 if (base_acct_flags & (ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST)) {
3087                         char simple_pass[9];
3088                         char *v = generate_random_str(tctx, 1);
3089                         
3090                         ZERO_STRUCT(simple_pass);
3091                         memset(simple_pass, *v, sizeof(simple_pass) - 1);
3092
3093                         printf("Testing machine account password policy rules\n");
3094
3095                         /* Workstation trust accounts don't seem to need to honour password quality policy */
3096                         if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3097                                 ret = false;
3098                         }
3099
3100                         if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, simple_pass, false)) {
3101                                 ret = false;
3102                         }
3103
3104                         /* reset again, to allow another 'user' password change */
3105                         if (!test_SetUserPassEx(p, tctx, user_handle, true, &password)) {
3106                                 ret = false;
3107                         }
3108
3109                         /* Try a 'short' password */
3110                         if (!test_ChangePasswordUser2(p, tctx, base_acct_name, &password, samr_rand_pass(tctx, 4), false)) {
3111                                 ret = false;
3112                         }
3113
3114                         /* Try a compleatly random password */
3115                         if (!test_ChangePasswordRandomBytes(p, tctx, base_acct_name, user_handle, &password)) {
3116                                 ret = false;
3117                         }
3118                 }
3119
3120                 for (i = 0; password_fields[i]; i++) {
3121                         if (!test_SetUserPass_23(p, tctx, user_handle, password_fields[i], &password)) {
3122                                 ret = false;
3123                         }       
3124                 
3125                         /* check it was set right */
3126                         if (!test_ChangePasswordUser3(p, tctx, base_acct_name, 0, &password, NULL, 0, false)) {
3127                                 ret = false;
3128                         }
3129                 }               
3130
3131                 for (i = 0; password_fields[i]; i++) {
3132                         if (!test_SetUserPass_25(p, tctx, user_handle, password_fields[i], &password)) {
3133    &nb