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