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