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