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