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