libsmb: Make cli_notify_send cancellable
[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) Jelmer Vernooij 2005-2007
8    Copyright (C) Guenther Deschner 2008-2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "torture/torture.h"
26 #include <tevent.h>
27 #include "system/time.h"
28 #include "system/network.h"
29 #include "librpc/gen_ndr/lsa.h"
30 #include "librpc/gen_ndr/ndr_netlogon.h"
31 #include "librpc/gen_ndr/ndr_netlogon_c.h"
32 #include "librpc/gen_ndr/ndr_samr_c.h"
33 #include "librpc/gen_ndr/ndr_lsa_c.h"
34 #include "../lib/crypto/crypto.h"
35 #include "libcli/auth/libcli_auth.h"
36 #include "libcli/security/security.h"
37 #include "torture/rpc/torture_rpc.h"
38 #include "param/param.h"
39 #include "auth/gensec/gensec.h"
40 #include "auth/gensec/gensec_proto.h"
41 #include "../libcli/auth/schannel.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 code_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         torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
668                         __location__, __FUNCTION__,
669                         newpass, nt_errstr(s.out.result));
670         if (!NT_STATUS_IS_OK(s.out.result)) {
671                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
672                        s.in.level, nt_errstr(s.out.result));
673                 ret = false;
674         } else {
675                 *password = newpass;
676         }
677
678         return ret;
679 }
680
681
682 static bool test_SetUserPass_23(struct dcerpc_pipe *p, struct torture_context *tctx,
683                                 struct policy_handle *handle, uint32_t fields_present,
684                                 char **password)
685 {
686         NTSTATUS status;
687         struct samr_SetUserInfo s;
688         union samr_UserInfo u;
689         bool ret = true;
690         DATA_BLOB session_key;
691         struct dcerpc_binding_handle *b = p->binding_handle;
692         char *newpass;
693         struct samr_GetUserPwInfo pwp;
694         struct samr_PwInfo info;
695         int policy_min_pw_len = 0;
696         pwp.in.user_handle = handle;
697         pwp.out.info = &info;
698
699         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
700                 "GetUserPwInfo failed");
701         if (NT_STATUS_IS_OK(pwp.out.result)) {
702                 policy_min_pw_len = pwp.out.info->min_password_length;
703         }
704         newpass = samr_rand_pass(tctx, policy_min_pw_len);
705
706         s.in.user_handle = handle;
707         s.in.info = &u;
708         s.in.level = 23;
709
710         ZERO_STRUCT(u);
711
712         u.info23.info.fields_present = fields_present;
713
714         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
715
716         status = dcerpc_fetch_session_key(p, &session_key);
717         if (!NT_STATUS_IS_OK(status)) {
718                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
719                        s.in.level, nt_errstr(status));
720                 return false;
721         }
722
723         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
724
725         torture_comment(tctx, "Testing SetUserInfo level 23 (set password)\n");
726
727         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
728                 "SetUserInfo failed");
729         torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
730                         __location__, __FUNCTION__,
731                         newpass, nt_errstr(s.out.result));
732         if (!NT_STATUS_IS_OK(s.out.result)) {
733                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
734                        s.in.level, nt_errstr(s.out.result));
735                 ret = false;
736         } else {
737                 *password = newpass;
738         }
739
740         encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
741
742         status = dcerpc_fetch_session_key(p, &session_key);
743         if (!NT_STATUS_IS_OK(status)) {
744                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
745                        s.in.level, nt_errstr(status));
746                 return false;
747         }
748
749         /* This should break the key nicely */
750         session_key.length--;
751         arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
752
753         torture_comment(tctx, "Testing SetUserInfo level 23 (set password) with wrong password\n");
754
755         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
756                 "SetUserInfo failed");
757         torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
758                         __location__, __FUNCTION__,
759                         newpass, nt_errstr(s.out.result));
760         if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
761                 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
762                        s.in.level, nt_errstr(s.out.result));
763                 ret = false;
764         }
765
766         return ret;
767 }
768
769
770 static bool test_SetUserPassEx(struct dcerpc_pipe *p, struct torture_context *tctx,
771                                struct policy_handle *handle, bool makeshort,
772                                char **password)
773 {
774         NTSTATUS status;
775         struct samr_SetUserInfo s;
776         union samr_UserInfo u;
777         bool ret = true;
778         DATA_BLOB session_key;
779         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
780         uint8_t confounder[16];
781         char *newpass;
782         struct dcerpc_binding_handle *b = p->binding_handle;
783         MD5_CTX ctx;
784         struct samr_GetUserPwInfo pwp;
785         struct samr_PwInfo info;
786         int policy_min_pw_len = 0;
787         pwp.in.user_handle = handle;
788         pwp.out.info = &info;
789
790         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
791                 "GetUserPwInfo failed");
792         if (NT_STATUS_IS_OK(pwp.out.result)) {
793                 policy_min_pw_len = pwp.out.info->min_password_length;
794         }
795         if (makeshort && policy_min_pw_len) {
796                 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len - 1);
797         } else {
798                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
799         }
800
801         s.in.user_handle = handle;
802         s.in.info = &u;
803         s.in.level = 26;
804
805         encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
806         u.info26.password_expired = 0;
807
808         status = dcerpc_fetch_session_key(p, &session_key);
809         if (!NT_STATUS_IS_OK(status)) {
810                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
811                        s.in.level, nt_errstr(status));
812                 return false;
813         }
814
815         generate_random_buffer((uint8_t *)confounder, 16);
816
817         MD5Init(&ctx);
818         MD5Update(&ctx, confounder, 16);
819         MD5Update(&ctx, session_key.data, session_key.length);
820         MD5Final(confounded_session_key.data, &ctx);
821
822         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
823         memcpy(&u.info26.password.data[516], confounder, 16);
824
825         torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex)\n");
826
827         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
828                 "SetUserInfo failed");
829         torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
830                         __location__, __FUNCTION__,
831                         newpass, nt_errstr(s.out.result));
832         if (!NT_STATUS_IS_OK(s.out.result)) {
833                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
834                        s.in.level, nt_errstr(s.out.result));
835                 ret = false;
836         } else {
837                 *password = newpass;
838         }
839
840         /* This should break the key nicely */
841         confounded_session_key.data[0]++;
842
843         arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
844         memcpy(&u.info26.password.data[516], confounder, 16);
845
846         torture_comment(tctx, "Testing SetUserInfo level 26 (set password ex) with wrong session key\n");
847
848         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
849                 "SetUserInfo failed");
850         torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
851                         __location__, __FUNCTION__,
852                         newpass, nt_errstr(s.out.result));
853         if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
854                 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD: %s\n",
855                        s.in.level, nt_errstr(s.out.result));
856                 ret = false;
857         } else {
858                 *password = newpass;
859         }
860
861         return ret;
862 }
863
864 static bool test_SetUserPass_25(struct dcerpc_pipe *p, struct torture_context *tctx,
865                                 struct policy_handle *handle, uint32_t fields_present,
866                                 char **password)
867 {
868         NTSTATUS status;
869         struct samr_SetUserInfo s;
870         union samr_UserInfo u;
871         bool ret = true;
872         DATA_BLOB session_key;
873         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
874         MD5_CTX ctx;
875         uint8_t confounder[16];
876         char *newpass;
877         struct dcerpc_binding_handle *b = p->binding_handle;
878         struct samr_GetUserPwInfo pwp;
879         struct samr_PwInfo info;
880         int policy_min_pw_len = 0;
881         pwp.in.user_handle = handle;
882         pwp.out.info = &info;
883
884         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
885                 "GetUserPwInfo failed");
886         if (NT_STATUS_IS_OK(pwp.out.result)) {
887                 policy_min_pw_len = pwp.out.info->min_password_length;
888         }
889         newpass = samr_rand_pass(tctx, policy_min_pw_len);
890
891         s.in.user_handle = handle;
892         s.in.info = &u;
893         s.in.level = 25;
894
895         ZERO_STRUCT(u);
896
897         u.info25.info.fields_present = fields_present;
898
899         encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
900
901         status = dcerpc_fetch_session_key(p, &session_key);
902         if (!NT_STATUS_IS_OK(status)) {
903                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
904                        s.in.level, nt_errstr(status));
905                 return false;
906         }
907
908         generate_random_buffer((uint8_t *)confounder, 16);
909
910         MD5Init(&ctx);
911         MD5Update(&ctx, confounder, 16);
912         MD5Update(&ctx, session_key.data, session_key.length);
913         MD5Final(confounded_session_key.data, &ctx);
914
915         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
916         memcpy(&u.info25.password.data[516], confounder, 16);
917
918         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex)\n");
919
920         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
921                 "SetUserInfo failed");
922         torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
923                         __location__, __FUNCTION__,
924                         newpass, nt_errstr(s.out.result));
925         if (!NT_STATUS_IS_OK(s.out.result)) {
926                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
927                        s.in.level, nt_errstr(s.out.result));
928                 ret = false;
929         } else {
930                 *password = newpass;
931         }
932
933         /* This should break the key nicely */
934         confounded_session_key.data[0]++;
935
936         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
937         memcpy(&u.info25.password.data[516], confounder, 16);
938
939         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with wrong session key\n");
940
941         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
942                 "SetUserInfo failed");
943         torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
944                         __location__, __FUNCTION__,
945                         newpass, nt_errstr(s.out.result));
946         if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_WRONG_PASSWORD)) {
947                 torture_warning(tctx, "SetUserInfo level %u should have failed with WRONG_PASSWORD- %s\n",
948                        s.in.level, nt_errstr(s.out.result));
949                 ret = false;
950         }
951
952         return ret;
953 }
954
955 static bool test_SetUserPass_18(struct dcerpc_pipe *p, struct torture_context *tctx,
956                                 struct policy_handle *handle, char **password)
957 {
958         NTSTATUS status;
959         struct samr_SetUserInfo s;
960         union samr_UserInfo u;
961         bool ret = true;
962         DATA_BLOB session_key;
963         char *newpass;
964         struct dcerpc_binding_handle *b = p->binding_handle;
965         struct samr_GetUserPwInfo pwp;
966         struct samr_PwInfo info;
967         int policy_min_pw_len = 0;
968         uint8_t lm_hash[16], nt_hash[16];
969
970         pwp.in.user_handle = handle;
971         pwp.out.info = &info;
972
973         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
974                 "GetUserPwInfo failed");
975         if (NT_STATUS_IS_OK(pwp.out.result)) {
976                 policy_min_pw_len = pwp.out.info->min_password_length;
977         }
978         newpass = samr_rand_pass(tctx, policy_min_pw_len);
979
980         s.in.user_handle = handle;
981         s.in.info = &u;
982         s.in.level = 18;
983
984         ZERO_STRUCT(u);
985
986         u.info18.nt_pwd_active = true;
987         u.info18.lm_pwd_active = true;
988
989         E_md4hash(newpass, nt_hash);
990         E_deshash(newpass, lm_hash);
991
992         status = dcerpc_fetch_session_key(p, &session_key);
993         if (!NT_STATUS_IS_OK(status)) {
994                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
995                        s.in.level, nt_errstr(status));
996                 return false;
997         }
998
999         {
1000                 DATA_BLOB in,out;
1001                 in = data_blob_const(nt_hash, 16);
1002                 out = data_blob_talloc_zero(tctx, 16);
1003                 sess_crypt_blob(&out, &in, &session_key, true);
1004                 memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1005         }
1006         {
1007                 DATA_BLOB in,out;
1008                 in = data_blob_const(lm_hash, 16);
1009                 out = data_blob_talloc_zero(tctx, 16);
1010                 sess_crypt_blob(&out, &in, &session_key, true);
1011                 memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1012         }
1013
1014         torture_comment(tctx, "Testing SetUserInfo level 18 (set password hash)\n");
1015
1016         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1017                 "SetUserInfo failed");
1018         if (!NT_STATUS_IS_OK(s.out.result)) {
1019                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1020                        s.in.level, nt_errstr(s.out.result));
1021                 ret = false;
1022         } else {
1023                 *password = newpass;
1024         }
1025
1026         return ret;
1027 }
1028
1029 static bool test_SetUserPass_21(struct dcerpc_pipe *p, struct torture_context *tctx,
1030                                 struct policy_handle *handle, uint32_t fields_present,
1031                                 char **password)
1032 {
1033         NTSTATUS status;
1034         struct samr_SetUserInfo s;
1035         union samr_UserInfo u;
1036         bool ret = true;
1037         DATA_BLOB session_key;
1038         char *newpass;
1039         struct dcerpc_binding_handle *b = p->binding_handle;
1040         struct samr_GetUserPwInfo pwp;
1041         struct samr_PwInfo info;
1042         int policy_min_pw_len = 0;
1043         uint8_t lm_hash[16], nt_hash[16];
1044
1045         pwp.in.user_handle = handle;
1046         pwp.out.info = &info;
1047
1048         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1049                 "GetUserPwInfo failed");
1050         if (NT_STATUS_IS_OK(pwp.out.result)) {
1051                 policy_min_pw_len = pwp.out.info->min_password_length;
1052         }
1053         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1054
1055         s.in.user_handle = handle;
1056         s.in.info = &u;
1057         s.in.level = 21;
1058
1059         E_md4hash(newpass, nt_hash);
1060         E_deshash(newpass, lm_hash);
1061
1062         ZERO_STRUCT(u);
1063
1064         u.info21.fields_present = fields_present;
1065
1066         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1067                 u.info21.lm_owf_password.length = 16;
1068                 u.info21.lm_owf_password.size = 16;
1069                 u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1070                 u.info21.lm_password_set = true;
1071         }
1072
1073         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1074                 u.info21.nt_owf_password.length = 16;
1075                 u.info21.nt_owf_password.size = 16;
1076                 u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1077                 u.info21.nt_password_set = true;
1078         }
1079
1080         status = dcerpc_fetch_session_key(p, &session_key);
1081         if (!NT_STATUS_IS_OK(status)) {
1082                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1083                        s.in.level, nt_errstr(status));
1084                 return false;
1085         }
1086
1087         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1088                 DATA_BLOB in,out;
1089                 in = data_blob_const(u.info21.lm_owf_password.array,
1090                                      u.info21.lm_owf_password.length);
1091                 out = data_blob_talloc_zero(tctx, 16);
1092                 sess_crypt_blob(&out, &in, &session_key, true);
1093                 u.info21.lm_owf_password.array = (uint16_t *)out.data;
1094         }
1095
1096         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1097                 DATA_BLOB in,out;
1098                 in = data_blob_const(u.info21.nt_owf_password.array,
1099                                      u.info21.nt_owf_password.length);
1100                 out = data_blob_talloc_zero(tctx, 16);
1101                 sess_crypt_blob(&out, &in, &session_key, true);
1102                 u.info21.nt_owf_password.array = (uint16_t *)out.data;
1103         }
1104
1105         torture_comment(tctx, "Testing SetUserInfo level 21 (set password hash)\n");
1106
1107         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1108                 "SetUserInfo failed");
1109         if (!NT_STATUS_IS_OK(s.out.result)) {
1110                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
1111                        s.in.level, nt_errstr(s.out.result));
1112                 ret = false;
1113         } else {
1114                 *password = newpass;
1115         }
1116
1117         /* try invalid length */
1118         if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1119
1120                 u.info21.nt_owf_password.length++;
1121
1122                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1123                         "SetUserInfo failed");
1124                 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1125                         torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1126                                s.in.level, nt_errstr(s.out.result));
1127                         ret = false;
1128                 }
1129         }
1130
1131         if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1132
1133                 u.info21.lm_owf_password.length++;
1134
1135                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1136                         "SetUserInfo failed");
1137                 if (!NT_STATUS_EQUAL(s.out.result, NT_STATUS_INVALID_PARAMETER)) {
1138                         torture_warning(tctx, "SetUserInfo level %u should have failed with NT_STATUS_INVALID_PARAMETER - %s\n",
1139                                s.in.level, nt_errstr(s.out.result));
1140                         ret = false;
1141                 }
1142         }
1143
1144         return ret;
1145 }
1146
1147 static bool test_SetUserPass_level_ex(struct dcerpc_pipe *p,
1148                                       struct torture_context *tctx,
1149                                       struct policy_handle *handle,
1150                                       uint16_t level,
1151                                       uint32_t fields_present,
1152                                       char **password, uint8_t password_expired,
1153                                       bool use_setinfo2,
1154                                       bool *matched_expected_error)
1155 {
1156         NTSTATUS status;
1157         NTSTATUS expected_error = NT_STATUS_OK;
1158         struct samr_SetUserInfo s;
1159         struct samr_SetUserInfo2 s2;
1160         union samr_UserInfo u;
1161         bool ret = true;
1162         DATA_BLOB session_key;
1163         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
1164         MD5_CTX ctx;
1165         uint8_t confounder[16];
1166         char *newpass;
1167         struct dcerpc_binding_handle *b = p->binding_handle;
1168         struct samr_GetUserPwInfo pwp;
1169         struct samr_PwInfo info;
1170         int policy_min_pw_len = 0;
1171         const char *comment = NULL;
1172         uint8_t lm_hash[16], nt_hash[16];
1173
1174         pwp.in.user_handle = handle;
1175         pwp.out.info = &info;
1176
1177         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1178                 "GetUserPwInfo failed");
1179         if (NT_STATUS_IS_OK(pwp.out.result)) {
1180                 policy_min_pw_len = pwp.out.info->min_password_length;
1181         }
1182         newpass = samr_rand_pass_silent(tctx, policy_min_pw_len);
1183
1184         if (use_setinfo2) {
1185                 s2.in.user_handle = handle;
1186                 s2.in.info = &u;
1187                 s2.in.level = level;
1188         } else {
1189                 s.in.user_handle = handle;
1190                 s.in.info = &u;
1191                 s.in.level = level;
1192         }
1193
1194         if (fields_present & SAMR_FIELD_COMMENT) {
1195                 comment = talloc_asprintf(tctx, "comment: %ld\n", (long int) time(NULL));
1196         }
1197
1198         ZERO_STRUCT(u);
1199
1200         switch (level) {
1201         case 18:
1202                 E_md4hash(newpass, nt_hash);
1203                 E_deshash(newpass, lm_hash);
1204
1205                 u.info18.nt_pwd_active = true;
1206                 u.info18.lm_pwd_active = true;
1207                 u.info18.password_expired = password_expired;
1208
1209                 memcpy(u.info18.lm_pwd.hash, lm_hash, 16);
1210                 memcpy(u.info18.nt_pwd.hash, nt_hash, 16);
1211
1212                 break;
1213         case 21:
1214                 E_md4hash(newpass, nt_hash);
1215                 E_deshash(newpass, lm_hash);
1216
1217                 u.info21.fields_present = fields_present;
1218                 u.info21.password_expired = password_expired;
1219                 u.info21.comment.string = comment;
1220
1221                 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1222                         u.info21.lm_owf_password.length = 16;
1223                         u.info21.lm_owf_password.size = 16;
1224                         u.info21.lm_owf_password.array = (uint16_t *)lm_hash;
1225                         u.info21.lm_password_set = true;
1226                 }
1227
1228                 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1229                         u.info21.nt_owf_password.length = 16;
1230                         u.info21.nt_owf_password.size = 16;
1231                         u.info21.nt_owf_password.array = (uint16_t *)nt_hash;
1232                         u.info21.nt_password_set = true;
1233                 }
1234
1235                 break;
1236         case 23:
1237                 u.info23.info.fields_present = fields_present;
1238                 u.info23.info.password_expired = password_expired;
1239                 u.info23.info.comment.string = comment;
1240
1241                 encode_pw_buffer(u.info23.password.data, newpass, STR_UNICODE);
1242
1243                 break;
1244         case 24:
1245                 u.info24.password_expired = password_expired;
1246
1247                 encode_pw_buffer(u.info24.password.data, newpass, STR_UNICODE);
1248
1249                 break;
1250         case 25:
1251                 u.info25.info.fields_present = fields_present;
1252                 u.info25.info.password_expired = password_expired;
1253                 u.info25.info.comment.string = comment;
1254
1255                 encode_pw_buffer(u.info25.password.data, newpass, STR_UNICODE);
1256
1257                 break;
1258         case 26:
1259                 u.info26.password_expired = password_expired;
1260
1261                 encode_pw_buffer(u.info26.password.data, newpass, STR_UNICODE);
1262
1263                 break;
1264         }
1265
1266         status = dcerpc_fetch_session_key(p, &session_key);
1267         if (!NT_STATUS_IS_OK(status)) {
1268                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
1269                        s.in.level, nt_errstr(status));
1270                 return false;
1271         }
1272
1273         generate_random_buffer((uint8_t *)confounder, 16);
1274
1275         MD5Init(&ctx);
1276         MD5Update(&ctx, confounder, 16);
1277         MD5Update(&ctx, session_key.data, session_key.length);
1278         MD5Final(confounded_session_key.data, &ctx);
1279
1280         switch (level) {
1281         case 18:
1282                 {
1283                         DATA_BLOB in,out;
1284                         in = data_blob_const(u.info18.nt_pwd.hash, 16);
1285                         out = data_blob_talloc_zero(tctx, 16);
1286                         sess_crypt_blob(&out, &in, &session_key, true);
1287                         memcpy(u.info18.nt_pwd.hash, out.data, out.length);
1288                 }
1289                 {
1290                         DATA_BLOB in,out;
1291                         in = data_blob_const(u.info18.lm_pwd.hash, 16);
1292                         out = data_blob_talloc_zero(tctx, 16);
1293                         sess_crypt_blob(&out, &in, &session_key, true);
1294                         memcpy(u.info18.lm_pwd.hash, out.data, out.length);
1295                 }
1296
1297                 break;
1298         case 21:
1299                 if (fields_present & SAMR_FIELD_LM_PASSWORD_PRESENT) {
1300                         DATA_BLOB in,out;
1301                         in = data_blob_const(u.info21.lm_owf_password.array,
1302                                              u.info21.lm_owf_password.length);
1303                         out = data_blob_talloc_zero(tctx, 16);
1304                         sess_crypt_blob(&out, &in, &session_key, true);
1305                         u.info21.lm_owf_password.array = (uint16_t *)out.data;
1306                 }
1307                 if (fields_present & SAMR_FIELD_NT_PASSWORD_PRESENT) {
1308                         DATA_BLOB in,out;
1309                         in = data_blob_const(u.info21.nt_owf_password.array,
1310                                              u.info21.nt_owf_password.length);
1311                         out = data_blob_talloc_zero(tctx, 16);
1312                         sess_crypt_blob(&out, &in, &session_key, true);
1313                         u.info21.nt_owf_password.array = (uint16_t *)out.data;
1314                 }
1315                 break;
1316         case 23:
1317                 arcfour_crypt_blob(u.info23.password.data, 516, &session_key);
1318                 break;
1319         case 24:
1320                 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
1321                 break;
1322         case 25:
1323                 arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
1324                 memcpy(&u.info25.password.data[516], confounder, 16);
1325                 break;
1326         case 26:
1327                 arcfour_crypt_blob(u.info26.password.data, 516, &confounded_session_key);
1328                 memcpy(&u.info26.password.data[516], confounder, 16);
1329                 break;
1330         }
1331
1332         if (use_setinfo2) {
1333                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo2_r(b, tctx, &s2),
1334                         "SetUserInfo2 failed");
1335                 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1336                                 __location__, __FUNCTION__,
1337                                 newpass, nt_errstr(s2.out.result));
1338                         status = s2.out.result;
1339         } else {
1340                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
1341                         "SetUserInfo failed");
1342                 torture_comment(tctx, "(%s:%s) new_password[%s] status[%s]\n",
1343                                 __location__, __FUNCTION__,
1344                                 newpass, nt_errstr(s.out.result));
1345                 status = s.out.result;
1346         }
1347
1348         if (!NT_STATUS_IS_OK(status)) {
1349                 if (fields_present == 0) {
1350                         expected_error = NT_STATUS_INVALID_PARAMETER;
1351                 }
1352                 if (fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
1353                         expected_error = NT_STATUS_ACCESS_DENIED;
1354                 }
1355         }
1356
1357         if (!NT_STATUS_IS_OK(expected_error)) {
1358                 if (use_setinfo2) {
1359                         torture_assert_ntstatus_equal(tctx,
1360                                 s2.out.result,
1361                                 expected_error, "SetUserInfo2 failed");
1362                 } else {
1363                         torture_assert_ntstatus_equal(tctx,
1364                                 s.out.result,
1365                                 expected_error, "SetUserInfo failed");
1366                 }
1367                 *matched_expected_error = true;
1368                 return true;
1369         }
1370
1371         if (!NT_STATUS_IS_OK(status)) {
1372                 torture_warning(tctx, "SetUserInfo%s level %u failed - %s\n",
1373                        use_setinfo2 ? "2":"", level, nt_errstr(status));
1374                 ret = false;
1375         } else {
1376                 *password = newpass;
1377         }
1378
1379         return ret;
1380 }
1381
1382 static bool test_SetAliasInfo(struct dcerpc_binding_handle *b,
1383                               struct torture_context *tctx,
1384                               struct policy_handle *handle)
1385 {
1386         struct samr_SetAliasInfo r;
1387         struct samr_QueryAliasInfo q;
1388         union samr_AliasInfo *info;
1389         uint16_t levels[] = {2, 3};
1390         int i;
1391         bool ret = true;
1392
1393         /* Ignoring switch level 1, as that includes the number of members for the alias
1394          * and setting this to a wrong value might have negative consequences
1395          */
1396
1397         for (i=0;i<ARRAY_SIZE(levels);i++) {
1398                 torture_comment(tctx, "Testing SetAliasInfo level %u\n", levels[i]);
1399
1400                 r.in.alias_handle = handle;
1401                 r.in.level = levels[i];
1402                 r.in.info  = talloc(tctx, union samr_AliasInfo);
1403                 switch (r.in.level) {
1404                     case ALIASINFONAME: init_lsa_String(&r.in.info->name,TEST_ALIASNAME); break;
1405                     case ALIASINFODESCRIPTION: init_lsa_String(&r.in.info->description,
1406                                 "Test Description, should test I18N as well"); break;
1407                     case ALIASINFOALL: torture_comment(tctx, "ALIASINFOALL ignored\n"); break;
1408                 }
1409
1410                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetAliasInfo_r(b, tctx, &r),
1411                         "SetAliasInfo failed");
1412                 if (!NT_STATUS_IS_OK(r.out.result)) {
1413                         torture_warning(tctx, "SetAliasInfo level %u failed - %s\n",
1414                                levels[i], nt_errstr(r.out.result));
1415                         ret = false;
1416                 }
1417
1418                 q.in.alias_handle = handle;
1419                 q.in.level = levels[i];
1420                 q.out.info = &info;
1421
1422                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryAliasInfo_r(b, tctx, &q),
1423                         "QueryAliasInfo failed");
1424                 if (!NT_STATUS_IS_OK(q.out.result)) {
1425                         torture_warning(tctx, "QueryAliasInfo level %u failed - %s\n",
1426                                levels[i], nt_errstr(q.out.result));
1427                         ret = false;
1428                 }
1429         }
1430
1431         return ret;
1432 }
1433
1434 static bool test_GetGroupsForUser(struct dcerpc_binding_handle *b,
1435                                   struct torture_context *tctx,
1436                                   struct policy_handle *user_handle)
1437 {
1438         struct samr_GetGroupsForUser r;
1439         struct samr_RidWithAttributeArray *rids = NULL;
1440
1441         torture_comment(tctx, "Testing GetGroupsForUser\n");
1442
1443         r.in.user_handle = user_handle;
1444         r.out.rids = &rids;
1445
1446         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetGroupsForUser_r(b, tctx, &r),
1447                 "GetGroupsForUser failed");
1448         torture_assert_ntstatus_ok(tctx, r.out.result, "GetGroupsForUser failed");
1449
1450         return true;
1451
1452 }
1453
1454 static bool test_GetDomPwInfo(struct dcerpc_pipe *p, struct torture_context *tctx,
1455                               struct lsa_String *domain_name)
1456 {
1457         struct samr_GetDomPwInfo r;
1458         struct samr_PwInfo info;
1459         struct dcerpc_binding_handle *b = p->binding_handle;
1460
1461         r.in.domain_name = domain_name;
1462         r.out.info = &info;
1463
1464         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1465
1466         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1467                 "GetDomPwInfo failed");
1468         torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1469
1470         r.in.domain_name->string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
1471         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1472
1473         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1474                 "GetDomPwInfo failed");
1475         torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1476
1477         r.in.domain_name->string = "\\\\__NONAME__";
1478         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1479
1480         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1481                 "GetDomPwInfo failed");
1482         torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1483
1484         r.in.domain_name->string = "\\\\Builtin";
1485         torture_comment(tctx, "Testing GetDomPwInfo with name %s\n", r.in.domain_name->string);
1486
1487         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &r),
1488                 "GetDomPwInfo failed");
1489         torture_assert_ntstatus_ok(tctx, r.out.result, "GetDomPwInfo failed");
1490
1491         return true;
1492 }
1493
1494 static bool test_GetUserPwInfo(struct dcerpc_binding_handle *b,
1495                                struct torture_context *tctx,
1496                                struct policy_handle *handle)
1497 {
1498         struct samr_GetUserPwInfo r;
1499         struct samr_PwInfo info;
1500
1501         torture_comment(tctx, "Testing GetUserPwInfo\n");
1502
1503         r.in.user_handle = handle;
1504         r.out.info = &info;
1505
1506         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &r),
1507                 "GetUserPwInfo failed");
1508         torture_assert_ntstatus_ok(tctx, r.out.result, "GetUserPwInfo");
1509
1510         return true;
1511 }
1512
1513 static NTSTATUS test_LookupName(struct dcerpc_binding_handle *b,
1514                                 struct torture_context *tctx,
1515                                 struct policy_handle *domain_handle, const char *name,
1516                                 uint32_t *rid)
1517 {
1518         NTSTATUS status;
1519         struct samr_LookupNames n;
1520         struct lsa_String sname[2];
1521         struct samr_Ids rids, types;
1522
1523         init_lsa_String(&sname[0], name);
1524
1525         n.in.domain_handle = domain_handle;
1526         n.in.num_names = 1;
1527         n.in.names = sname;
1528         n.out.rids = &rids;
1529         n.out.types = &types;
1530         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1531         if (!NT_STATUS_IS_OK(status)) {
1532                 return status;
1533         }
1534         if (NT_STATUS_IS_OK(n.out.result)) {
1535                 *rid = n.out.rids->ids[0];
1536         } else {
1537                 return n.out.result;
1538         }
1539
1540         init_lsa_String(&sname[1], "xxNONAMExx");
1541         n.in.num_names = 2;
1542         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1543         if (!NT_STATUS_IS_OK(status)) {
1544                 return status;
1545         }
1546         if (!NT_STATUS_EQUAL(n.out.result, STATUS_SOME_UNMAPPED)) {
1547                 torture_warning(tctx, "LookupNames[2] failed - %s\n", nt_errstr(n.out.result));
1548                 if (NT_STATUS_IS_OK(n.out.result)) {
1549                         return NT_STATUS_UNSUCCESSFUL;
1550                 }
1551                 return n.out.result;
1552         }
1553
1554         n.in.num_names = 0;
1555         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1556         if (!NT_STATUS_IS_OK(status)) {
1557                 return status;
1558         }
1559         if (!NT_STATUS_IS_OK(n.out.result)) {
1560                 torture_warning(tctx, "LookupNames[0] failed - %s\n", nt_errstr(status));
1561                 return n.out.result;
1562         }
1563
1564         init_lsa_String(&sname[0], "xxNONAMExx");
1565         n.in.num_names = 1;
1566         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1567         if (!NT_STATUS_IS_OK(status)) {
1568                 return status;
1569         }
1570         if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1571                 torture_warning(tctx, "LookupNames[1 bad name] failed - %s\n", nt_errstr(n.out.result));
1572                 if (NT_STATUS_IS_OK(n.out.result)) {
1573                         return NT_STATUS_UNSUCCESSFUL;
1574                 }
1575                 return n.out.result;
1576         }
1577
1578         init_lsa_String(&sname[0], "xxNONAMExx");
1579         init_lsa_String(&sname[1], "xxNONAME2xx");
1580         n.in.num_names = 2;
1581         status = dcerpc_samr_LookupNames_r(b, tctx, &n);
1582         if (!NT_STATUS_IS_OK(status)) {
1583                 return status;
1584         }
1585         if (!NT_STATUS_EQUAL(n.out.result, NT_STATUS_NONE_MAPPED)) {
1586                 torture_warning(tctx, "LookupNames[2 bad names] failed - %s\n", nt_errstr(n.out.result));
1587                 if (NT_STATUS_IS_OK(n.out.result)) {
1588                         return NT_STATUS_UNSUCCESSFUL;
1589                 }
1590                 return n.out.result;
1591         }
1592
1593         return NT_STATUS_OK;
1594 }
1595
1596 static NTSTATUS test_OpenUser_byname(struct dcerpc_binding_handle *b,
1597                                      struct torture_context *tctx,
1598                                      struct policy_handle *domain_handle,
1599                                      const char *name, struct policy_handle *user_handle)
1600 {
1601         NTSTATUS status;
1602         struct samr_OpenUser r;
1603         uint32_t rid;
1604
1605         status = test_LookupName(b, tctx, domain_handle, name, &rid);
1606         if (!NT_STATUS_IS_OK(status)) {
1607                 return status;
1608         }
1609
1610         r.in.domain_handle = domain_handle;
1611         r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1612         r.in.rid = rid;
1613         r.out.user_handle = user_handle;
1614         status = dcerpc_samr_OpenUser_r(b, tctx, &r);
1615         if (!NT_STATUS_IS_OK(status)) {
1616                 return status;
1617         }
1618         if (!NT_STATUS_IS_OK(r.out.result)) {
1619                 torture_warning(tctx, "OpenUser_byname(%s -> %d) failed - %s\n", name, rid, nt_errstr(r.out.result));
1620         }
1621
1622         return r.out.result;
1623 }
1624
1625 #if 0
1626 static bool test_ChangePasswordNT3(struct dcerpc_pipe *p,
1627                                    struct torture_context *tctx,
1628                                    struct policy_handle *handle)
1629 {
1630         NTSTATUS status;
1631         struct samr_ChangePasswordUser r;
1632         bool ret = true;
1633         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1634         struct policy_handle user_handle;
1635         char *oldpass = "test";
1636         char *newpass = "test2";
1637         uint8_t old_nt_hash[16], new_nt_hash[16];
1638         uint8_t old_lm_hash[16], new_lm_hash[16];
1639
1640         status = test_OpenUser_byname(p, tctx, handle, "testuser", &user_handle);
1641         if (!NT_STATUS_IS_OK(status)) {
1642                 return false;
1643         }
1644
1645         torture_comment(tctx, "Testing ChangePasswordUser for user 'testuser'\n");
1646
1647         torture_comment(tctx, "old password: %s\n", oldpass);
1648         torture_comment(tctx, "new password: %s\n", newpass);
1649
1650         E_md4hash(oldpass, old_nt_hash);
1651         E_md4hash(newpass, new_nt_hash);
1652         E_deshash(oldpass, old_lm_hash);
1653         E_deshash(newpass, new_lm_hash);
1654
1655         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1656         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1657         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1658         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1659         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1660         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1661
1662         r.in.handle = &user_handle;
1663         r.in.lm_present = 1;
1664         r.in.old_lm_crypted = &hash1;
1665         r.in.new_lm_crypted = &hash2;
1666         r.in.nt_present = 1;
1667         r.in.old_nt_crypted = &hash3;
1668         r.in.new_nt_crypted = &hash4;
1669         r.in.cross1_present = 1;
1670         r.in.nt_cross = &hash5;
1671         r.in.cross2_present = 1;
1672         r.in.lm_cross = &hash6;
1673
1674         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1675                 "ChangePasswordUser failed");
1676         if (!NT_STATUS_IS_OK(r.out.result)) {
1677                 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1678                 ret = false;
1679         }
1680
1681         if (!test_samr_handle_Close(p, tctx, &user_handle)) {
1682                 ret = false;
1683         }
1684
1685         return ret;
1686 }
1687 #endif
1688
1689 static bool test_ChangePasswordUser(struct dcerpc_binding_handle *b,
1690                                     struct torture_context *tctx,
1691                                     const char *acct_name,
1692                                     struct policy_handle *handle, char **password)
1693 {
1694         NTSTATUS status;
1695         struct samr_ChangePasswordUser r;
1696         bool ret = true;
1697         struct samr_Password hash1, hash2, hash3, hash4, hash5, hash6;
1698         struct policy_handle user_handle;
1699         char *oldpass;
1700         uint8_t old_nt_hash[16], new_nt_hash[16];
1701         uint8_t old_lm_hash[16], new_lm_hash[16];
1702         bool changed = true;
1703
1704         char *newpass;
1705         struct samr_GetUserPwInfo pwp;
1706         struct samr_PwInfo info;
1707         int policy_min_pw_len = 0;
1708
1709         status = test_OpenUser_byname(b, tctx, handle, acct_name, &user_handle);
1710         if (!NT_STATUS_IS_OK(status)) {
1711                 return false;
1712         }
1713         pwp.in.user_handle = &user_handle;
1714         pwp.out.info = &info;
1715
1716         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetUserPwInfo_r(b, tctx, &pwp),
1717                 "GetUserPwInfo failed");
1718         if (NT_STATUS_IS_OK(pwp.out.result)) {
1719                 policy_min_pw_len = pwp.out.info->min_password_length;
1720         }
1721         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1722
1723         torture_comment(tctx, "Testing ChangePasswordUser\n");
1724
1725         torture_assert(tctx, *password != NULL,
1726                                    "Failing ChangePasswordUser as old password was NULL.  Previous test failed?");
1727
1728         oldpass = *password;
1729
1730         E_md4hash(oldpass, old_nt_hash);
1731         E_md4hash(newpass, new_nt_hash);
1732         E_deshash(oldpass, old_lm_hash);
1733         E_deshash(newpass, new_lm_hash);
1734
1735         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1736         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1737         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1738         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1739         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1740         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1741
1742         r.in.user_handle = &user_handle;
1743         r.in.lm_present = 1;
1744         /* Break the LM hash */
1745         hash1.hash[0]++;
1746         r.in.old_lm_crypted = &hash1;
1747         r.in.new_lm_crypted = &hash2;
1748         r.in.nt_present = 1;
1749         r.in.old_nt_crypted = &hash3;
1750         r.in.new_nt_crypted = &hash4;
1751         r.in.cross1_present = 1;
1752         r.in.nt_cross = &hash5;
1753         r.in.cross2_present = 1;
1754         r.in.lm_cross = &hash6;
1755
1756         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1757                 "ChangePasswordUser failed");
1758         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1759                         __location__, __FUNCTION__,
1760                         oldpass, newpass, nt_errstr(r.out.result));
1761         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1762                 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1763                         "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we broke the LM hash");
1764         }
1765
1766         /* Unbreak the LM hash */
1767         hash1.hash[0]--;
1768
1769         r.in.user_handle = &user_handle;
1770         r.in.lm_present = 1;
1771         r.in.old_lm_crypted = &hash1;
1772         r.in.new_lm_crypted = &hash2;
1773         /* Break the NT hash */
1774         hash3.hash[0]--;
1775         r.in.nt_present = 1;
1776         r.in.old_nt_crypted = &hash3;
1777         r.in.new_nt_crypted = &hash4;
1778         r.in.cross1_present = 1;
1779         r.in.nt_cross = &hash5;
1780         r.in.cross2_present = 1;
1781         r.in.lm_cross = &hash6;
1782
1783         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1784                 "ChangePasswordUser failed");
1785         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1786                         __location__, __FUNCTION__,
1787                         oldpass, newpass, nt_errstr(r.out.result));
1788         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1789                 torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_WRONG_PASSWORD,
1790                         "expected NT_STATUS_WRONG_PASSWORD because we broke the NT hash");
1791         }
1792
1793         /* Unbreak the NT hash */
1794         hash3.hash[0]--;
1795
1796         r.in.user_handle = &user_handle;
1797         r.in.lm_present = 1;
1798         r.in.old_lm_crypted = &hash1;
1799         r.in.new_lm_crypted = &hash2;
1800         r.in.nt_present = 1;
1801         r.in.old_nt_crypted = &hash3;
1802         r.in.new_nt_crypted = &hash4;
1803         r.in.cross1_present = 1;
1804         r.in.nt_cross = &hash5;
1805         r.in.cross2_present = 1;
1806         /* Break the LM cross */
1807         hash6.hash[0]++;
1808         r.in.lm_cross = &hash6;
1809
1810         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1811                 "ChangePasswordUser failed");
1812         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1813                         __location__, __FUNCTION__,
1814                         oldpass, newpass, nt_errstr(r.out.result));
1815         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1816             !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1817         {
1818                 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the LM cross-hash, got %s\n", nt_errstr(r.out.result));
1819                 ret = false;
1820         }
1821
1822         /* Unbreak the LM cross */
1823         hash6.hash[0]--;
1824
1825         r.in.user_handle = &user_handle;
1826         r.in.lm_present = 1;
1827         r.in.old_lm_crypted = &hash1;
1828         r.in.new_lm_crypted = &hash2;
1829         r.in.nt_present = 1;
1830         r.in.old_nt_crypted = &hash3;
1831         r.in.new_nt_crypted = &hash4;
1832         r.in.cross1_present = 1;
1833         /* Break the NT cross */
1834         hash5.hash[0]++;
1835         r.in.nt_cross = &hash5;
1836         r.in.cross2_present = 1;
1837         r.in.lm_cross = &hash6;
1838
1839         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1840                 "ChangePasswordUser failed");
1841         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1842                         __location__, __FUNCTION__,
1843                         oldpass, newpass, nt_errstr(r.out.result));
1844         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD) &&
1845             !NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION))
1846         {
1847                 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD or NT_STATUS_PASSWORD_RESTRICTION because we broke the NT cross-hash, got %s\n", nt_errstr(r.out.result));
1848                 ret = false;
1849         }
1850
1851         /* Unbreak the NT cross */
1852         hash5.hash[0]--;
1853
1854
1855         /* Reset the hashes to not broken values */
1856         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1857         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1858         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1859         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1860         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1861         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1862
1863         r.in.user_handle = &user_handle;
1864         r.in.lm_present = 1;
1865         r.in.old_lm_crypted = &hash1;
1866         r.in.new_lm_crypted = &hash2;
1867         r.in.nt_present = 1;
1868         r.in.old_nt_crypted = &hash3;
1869         r.in.new_nt_crypted = &hash4;
1870         r.in.cross1_present = 1;
1871         r.in.nt_cross = &hash5;
1872         r.in.cross2_present = 0;
1873         r.in.lm_cross = NULL;
1874
1875         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1876                 "ChangePasswordUser failed");
1877         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1878                         __location__, __FUNCTION__,
1879                         oldpass, newpass, nt_errstr(r.out.result));
1880         if (NT_STATUS_IS_OK(r.out.result)) {
1881                 changed = true;
1882                 *password = newpass;
1883         } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1884                 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1885                 ret = false;
1886         }
1887
1888         oldpass = newpass;
1889         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1890
1891         E_md4hash(oldpass, old_nt_hash);
1892         E_md4hash(newpass, new_nt_hash);
1893         E_deshash(oldpass, old_lm_hash);
1894         E_deshash(newpass, new_lm_hash);
1895
1896
1897         /* Reset the hashes to not broken values */
1898         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1899         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1900         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1901         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1902         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1903         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1904
1905         r.in.user_handle = &user_handle;
1906         r.in.lm_present = 1;
1907         r.in.old_lm_crypted = &hash1;
1908         r.in.new_lm_crypted = &hash2;
1909         r.in.nt_present = 1;
1910         r.in.old_nt_crypted = &hash3;
1911         r.in.new_nt_crypted = &hash4;
1912         r.in.cross1_present = 0;
1913         r.in.nt_cross = NULL;
1914         r.in.cross2_present = 1;
1915         r.in.lm_cross = &hash6;
1916
1917         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1918                 "ChangePasswordUser failed");
1919         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1920                         __location__, __FUNCTION__,
1921                         oldpass, newpass, nt_errstr(r.out.result));
1922         if (NT_STATUS_IS_OK(r.out.result)) {
1923                 changed = true;
1924                 *password = newpass;
1925         } else if (!NT_STATUS_EQUAL(NT_STATUS_PASSWORD_RESTRICTION, r.out.result)) {
1926                 torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_OK, or at least NT_STATUS_PASSWORD_RESTRICTION, got %s\n", nt_errstr(r.out.result));
1927                 ret = false;
1928         }
1929
1930         oldpass = newpass;
1931         newpass = samr_rand_pass(tctx, policy_min_pw_len);
1932
1933         E_md4hash(oldpass, old_nt_hash);
1934         E_md4hash(newpass, new_nt_hash);
1935         E_deshash(oldpass, old_lm_hash);
1936         E_deshash(newpass, new_lm_hash);
1937
1938
1939         /* Reset the hashes to not broken values */
1940         E_old_pw_hash(new_lm_hash, old_lm_hash, hash1.hash);
1941         E_old_pw_hash(old_lm_hash, new_lm_hash, hash2.hash);
1942         E_old_pw_hash(new_nt_hash, old_nt_hash, hash3.hash);
1943         E_old_pw_hash(old_nt_hash, new_nt_hash, hash4.hash);
1944         E_old_pw_hash(old_lm_hash, new_nt_hash, hash5.hash);
1945         E_old_pw_hash(old_nt_hash, new_lm_hash, hash6.hash);
1946
1947         r.in.user_handle = &user_handle;
1948         r.in.lm_present = 1;
1949         r.in.old_lm_crypted = &hash1;
1950         r.in.new_lm_crypted = &hash2;
1951         r.in.nt_present = 1;
1952         r.in.old_nt_crypted = &hash3;
1953         r.in.new_nt_crypted = &hash4;
1954         r.in.cross1_present = 1;
1955         r.in.nt_cross = &hash5;
1956         r.in.cross2_present = 1;
1957         r.in.lm_cross = &hash6;
1958
1959         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1960                 "ChangePasswordUser failed");
1961         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1962                         __location__, __FUNCTION__,
1963                         oldpass, newpass, nt_errstr(r.out.result));
1964         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1965                 torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1966         } else  if (!NT_STATUS_IS_OK(r.out.result)) {
1967                 torture_warning(tctx, "ChangePasswordUser failed - %s\n", nt_errstr(r.out.result));
1968                 ret = false;
1969         } else {
1970                 changed = true;
1971                 *password = newpass;
1972         }
1973
1974         r.in.user_handle = &user_handle;
1975         r.in.lm_present = 1;
1976         r.in.old_lm_crypted = &hash1;
1977         r.in.new_lm_crypted = &hash2;
1978         r.in.nt_present = 1;
1979         r.in.old_nt_crypted = &hash3;
1980         r.in.new_nt_crypted = &hash4;
1981         r.in.cross1_present = 1;
1982         r.in.nt_cross = &hash5;
1983         r.in.cross2_present = 1;
1984         r.in.lm_cross = &hash6;
1985
1986         if (changed) {
1987                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser_r(b, tctx, &r),
1988                         "ChangePasswordUser failed");
1989                 torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
1990                                 __location__, __FUNCTION__,
1991                                 oldpass, newpass, nt_errstr(r.out.result));
1992                 if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
1993                         torture_comment(tctx, "ChangePasswordUser returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
1994                 } else if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
1995                         torture_warning(tctx, "ChangePasswordUser failed: expected NT_STATUS_WRONG_PASSWORD because we already changed the password, got %s\n", nt_errstr(r.out.result));
1996                         ret = false;
1997                 }
1998         }
1999
2000
2001         if (!test_samr_handle_Close(b, tctx, &user_handle)) {
2002                 ret = false;
2003         }
2004
2005         return ret;
2006 }
2007
2008
2009 static bool test_OemChangePasswordUser2(struct dcerpc_pipe *p,
2010                                         struct torture_context *tctx,
2011                                         const char *acct_name,
2012                                         struct policy_handle *handle, char **password)
2013 {
2014         struct samr_OemChangePasswordUser2 r;
2015         bool ret = true;
2016         struct samr_Password lm_verifier;
2017         struct samr_CryptPassword lm_pass;
2018         struct lsa_AsciiString server, account, account_bad;
2019         char *oldpass;
2020         char *newpass;
2021         struct dcerpc_binding_handle *b = p->binding_handle;
2022         uint8_t old_lm_hash[16], new_lm_hash[16];
2023
2024         struct samr_GetDomPwInfo dom_pw_info;
2025         struct samr_PwInfo info;
2026         int policy_min_pw_len = 0;
2027
2028         struct lsa_String domain_name;
2029
2030         domain_name.string = "";
2031         dom_pw_info.in.domain_name = &domain_name;
2032         dom_pw_info.out.info = &info;
2033
2034         torture_comment(tctx, "Testing OemChangePasswordUser2\n");
2035
2036         torture_assert(tctx, *password != NULL,
2037                                    "Failing OemChangePasswordUser2 as old password was NULL.  Previous test failed?");
2038
2039         oldpass = *password;
2040
2041         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2042                 "GetDomPwInfo failed");
2043         if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2044                 policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2045         }
2046
2047         newpass = samr_rand_pass(tctx, policy_min_pw_len);
2048
2049         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2050         account.string = acct_name;
2051
2052         E_deshash(oldpass, old_lm_hash);
2053         E_deshash(newpass, new_lm_hash);
2054
2055         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2056         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2057         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2058
2059         r.in.server = &server;
2060         r.in.account = &account;
2061         r.in.password = &lm_pass;
2062         r.in.hash = &lm_verifier;
2063
2064         /* Break the verification */
2065         lm_verifier.hash[0]++;
2066
2067         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2068                 "OemChangePasswordUser2 failed");
2069         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2070                         __location__, __FUNCTION__,
2071                         oldpass, newpass, nt_errstr(r.out.result));
2072
2073         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2074             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2075                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2076                         nt_errstr(r.out.result));
2077                 ret = false;
2078         }
2079
2080         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2081         /* Break the old password */
2082         old_lm_hash[0]++;
2083         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2084         /* unbreak it for the next operation */
2085         old_lm_hash[0]--;
2086         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2087
2088         r.in.server = &server;
2089         r.in.account = &account;
2090         r.in.password = &lm_pass;
2091         r.in.hash = &lm_verifier;
2092
2093         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2094                 "OemChangePasswordUser2 failed");
2095         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2096                         __location__, __FUNCTION__,
2097                         oldpass, newpass, nt_errstr(r.out.result));
2098
2099         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2100             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2101                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2102                         nt_errstr(r.out.result));
2103                 ret = false;
2104         }
2105
2106         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2107         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2108
2109         r.in.server = &server;
2110         r.in.account = &account;
2111         r.in.password = &lm_pass;
2112         r.in.hash = NULL;
2113
2114         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2115                 "OemChangePasswordUser2 failed");
2116         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2117                         __location__, __FUNCTION__,
2118                         oldpass, newpass, nt_errstr(r.out.result));
2119
2120         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2121             && !NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2122                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER (or at least 'PASSWORD_RESTRICTON') for no supplied validation hash - %s\n",
2123                         nt_errstr(r.out.result));
2124                 ret = false;
2125         }
2126
2127         /* This shouldn't be a valid name */
2128         account_bad.string = TEST_ACCOUNT_NAME "XX";
2129         r.in.account = &account_bad;
2130
2131         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2132                 "OemChangePasswordUser2 failed");
2133         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2134                         __location__, __FUNCTION__,
2135                         oldpass, newpass, nt_errstr(r.out.result));
2136
2137         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2138                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied validation hash and invalid user - %s\n",
2139                         nt_errstr(r.out.result));
2140                 ret = false;
2141         }
2142
2143         /* This shouldn't be a valid name */
2144         account_bad.string = TEST_ACCOUNT_NAME "XX";
2145         r.in.account = &account_bad;
2146         r.in.password = &lm_pass;
2147         r.in.hash = &lm_verifier;
2148
2149         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2150                 "OemChangePasswordUser2 failed");
2151         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2152                         __location__, __FUNCTION__,
2153                         oldpass, newpass, nt_errstr(r.out.result));
2154
2155         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2156                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned WRONG_PASSWORD for invalid user - %s\n",
2157                         nt_errstr(r.out.result));
2158                 ret = false;
2159         }
2160
2161         /* This shouldn't be a valid name */
2162         account_bad.string = TEST_ACCOUNT_NAME "XX";
2163         r.in.account = &account_bad;
2164         r.in.password = NULL;
2165         r.in.hash = &lm_verifier;
2166
2167         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2168                 "OemChangePasswordUser2 failed");
2169         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2170                         __location__, __FUNCTION__,
2171                         oldpass, newpass, nt_errstr(r.out.result));
2172
2173         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_PARAMETER)) {
2174                 torture_warning(tctx, "OemChangePasswordUser2 failed, should have returned INVALID_PARAMETER for no supplied password and invalid user - %s\n",
2175                         nt_errstr(r.out.result));
2176                 ret = false;
2177         }
2178
2179         E_deshash(oldpass, old_lm_hash);
2180         E_deshash(newpass, new_lm_hash);
2181
2182         encode_pw_buffer(lm_pass.data, newpass, STR_ASCII);
2183         arcfour_crypt(lm_pass.data, old_lm_hash, 516);
2184         E_old_pw_hash(new_lm_hash, old_lm_hash, lm_verifier.hash);
2185
2186         r.in.server = &server;
2187         r.in.account = &account;
2188         r.in.password = &lm_pass;
2189         r.in.hash = &lm_verifier;
2190
2191         torture_assert_ntstatus_ok(tctx, dcerpc_samr_OemChangePasswordUser2_r(b, tctx, &r),
2192                 "OemChangePasswordUser2 failed");
2193         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2194                         __location__, __FUNCTION__,
2195                         oldpass, newpass, nt_errstr(r.out.result));
2196
2197         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2198                 torture_comment(tctx, "OemChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2199         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2200                 torture_warning(tctx, "OemChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2201                 ret = false;
2202         } else {
2203                 *password = newpass;
2204         }
2205
2206         return ret;
2207 }
2208
2209
2210 static bool test_ChangePasswordUser2(struct dcerpc_pipe *p, struct torture_context *tctx,
2211                                      const char *acct_name,
2212                                      char **password,
2213                                      char *newpass, bool allow_password_restriction)
2214 {
2215         struct samr_ChangePasswordUser2 r;
2216         bool ret = true;
2217         struct lsa_String server, account;
2218         struct samr_CryptPassword nt_pass, lm_pass;
2219         struct samr_Password nt_verifier, lm_verifier;
2220         char *oldpass;
2221         struct dcerpc_binding_handle *b = p->binding_handle;
2222         uint8_t old_nt_hash[16], new_nt_hash[16];
2223         uint8_t old_lm_hash[16], new_lm_hash[16];
2224
2225         struct samr_GetDomPwInfo dom_pw_info;
2226         struct samr_PwInfo info;
2227
2228         struct lsa_String domain_name;
2229
2230         domain_name.string = "";
2231         dom_pw_info.in.domain_name = &domain_name;
2232         dom_pw_info.out.info = &info;
2233
2234         torture_comment(tctx, "Testing ChangePasswordUser2 on %s\n", acct_name);
2235
2236         torture_assert(tctx, *password != NULL,
2237                                    "Failing ChangePasswordUser2 as old password was NULL.  Previous test failed?");
2238         oldpass = *password;
2239
2240         if (!newpass) {
2241                 int policy_min_pw_len = 0;
2242                 torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetDomPwInfo_r(b, tctx, &dom_pw_info),
2243                         "GetDomPwInfo failed");
2244                 if (NT_STATUS_IS_OK(dom_pw_info.out.result)) {
2245                         policy_min_pw_len = dom_pw_info.out.info->min_password_length;
2246                 }
2247
2248                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2249         }
2250
2251         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2252         init_lsa_String(&account, acct_name);
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_ASCII|STR_TERMINATE);
2261         arcfour_crypt(lm_pass.data, old_lm_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         r.in.server = &server;
2269         r.in.account = &account;
2270         r.in.nt_password = &nt_pass;
2271         r.in.nt_verifier = &nt_verifier;
2272         r.in.lm_change = 1;
2273         r.in.lm_password = &lm_pass;
2274         r.in.lm_verifier = &lm_verifier;
2275
2276         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser2_r(b, tctx, &r),
2277                 "ChangePasswordUser2 failed");
2278         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2279                         __location__, __FUNCTION__,
2280                         oldpass, newpass, nt_errstr(r.out.result));
2281
2282         if (allow_password_restriction && NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2283                 torture_comment(tctx, "ChangePasswordUser2 returned: %s perhaps min password age? (not fatal)\n", nt_errstr(r.out.result));
2284         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2285                 torture_warning(tctx, "ChangePasswordUser2 failed - %s\n", nt_errstr(r.out.result));
2286                 ret = false;
2287         } else {
2288                 *password = newpass;
2289         }
2290
2291         return ret;
2292 }
2293
2294
2295 bool test_ChangePasswordUser3(struct dcerpc_pipe *p, struct torture_context *tctx,
2296                               const char *account_string,
2297                               int policy_min_pw_len,
2298                               char **password,
2299                               const char *newpass,
2300                               NTTIME last_password_change,
2301                               bool handle_reject_reason)
2302 {
2303         struct samr_ChangePasswordUser3 r;
2304         bool ret = true;
2305         struct lsa_String server, account, account_bad;
2306         struct samr_CryptPassword nt_pass, lm_pass;
2307         struct samr_Password nt_verifier, lm_verifier;
2308         char *oldpass;
2309         struct dcerpc_binding_handle *b = p->binding_handle;
2310         uint8_t old_nt_hash[16], new_nt_hash[16];
2311         uint8_t old_lm_hash[16], new_lm_hash[16];
2312         NTTIME t;
2313         struct samr_DomInfo1 *dominfo = NULL;
2314         struct userPwdChangeFailureInformation *reject = NULL;
2315
2316         torture_comment(tctx, "Testing ChangePasswordUser3\n");
2317
2318         if (newpass == NULL) {
2319                 do {
2320                         if (policy_min_pw_len == 0) {
2321                                 newpass = samr_rand_pass(tctx, policy_min_pw_len);
2322                         } else {
2323                                 newpass = samr_rand_pass_fixed_len(tctx, policy_min_pw_len);
2324                         }
2325                 } while (check_password_quality(newpass) == false);
2326         } else {
2327                 torture_comment(tctx, "Using password '%s'\n", newpass);
2328         }
2329
2330         torture_assert(tctx, *password != NULL,
2331                                    "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
2332
2333         oldpass = *password;
2334         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2335         init_lsa_String(&account, account_string);
2336
2337         E_md4hash(oldpass, old_nt_hash);
2338         E_md4hash(newpass, new_nt_hash);
2339
2340         E_deshash(oldpass, old_lm_hash);
2341         E_deshash(newpass, new_lm_hash);
2342
2343         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2344         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2345         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2346
2347         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2348         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2349         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2350
2351         /* Break the verification */
2352         nt_verifier.hash[0]++;
2353
2354         r.in.server = &server;
2355         r.in.account = &account;
2356         r.in.nt_password = &nt_pass;
2357         r.in.nt_verifier = &nt_verifier;
2358         r.in.lm_change = 1;
2359         r.in.lm_password = &lm_pass;
2360         r.in.lm_verifier = &lm_verifier;
2361         r.in.password3 = NULL;
2362         r.out.dominfo = &dominfo;
2363         r.out.reject = &reject;
2364
2365         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2366                 "ChangePasswordUser3 failed");
2367         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2368                         __location__, __FUNCTION__,
2369                         oldpass, newpass, nt_errstr(r.out.result));
2370         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2371             (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2372                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalid password verifier - %s\n",
2373                         nt_errstr(r.out.result));
2374                 ret = false;
2375         }
2376
2377         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2378         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2379         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2380
2381         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2382         /* Break the NT hash */
2383         old_nt_hash[0]++;
2384         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2385         /* Unbreak it again */
2386         old_nt_hash[0]--;
2387         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2388
2389         r.in.server = &server;
2390         r.in.account = &account;
2391         r.in.nt_password = &nt_pass;
2392         r.in.nt_verifier = &nt_verifier;
2393         r.in.lm_change = 1;
2394         r.in.lm_password = &lm_pass;
2395         r.in.lm_verifier = &lm_verifier;
2396         r.in.password3 = NULL;
2397         r.out.dominfo = &dominfo;
2398         r.out.reject = &reject;
2399
2400         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2401                 "ChangePasswordUser3 failed");
2402         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2403                         __location__, __FUNCTION__,
2404                         oldpass, newpass, nt_errstr(r.out.result));
2405         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION) &&
2406             (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD))) {
2407                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD (or at least 'PASSWORD_RESTRICTON') for invalidly encrpted password - %s\n",
2408                         nt_errstr(r.out.result));
2409                 ret = false;
2410         }
2411
2412         /* This shouldn't be a valid name */
2413         init_lsa_String(&account_bad, talloc_asprintf(tctx, "%sXX", account_string));
2414
2415         r.in.account = &account_bad;
2416         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2417                 "ChangePasswordUser3 failed");
2418         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2419                         __location__, __FUNCTION__,
2420                         oldpass, newpass, nt_errstr(r.out.result));
2421         if (!NT_STATUS_EQUAL(r.out.result, NT_STATUS_WRONG_PASSWORD)) {
2422                 torture_warning(tctx, "ChangePasswordUser3 failed, should have returned WRONG_PASSWORD for invalid username - %s\n",
2423                         nt_errstr(r.out.result));
2424                 ret = false;
2425         }
2426
2427         E_md4hash(oldpass, old_nt_hash);
2428         E_md4hash(newpass, new_nt_hash);
2429
2430         E_deshash(oldpass, old_lm_hash);
2431         E_deshash(newpass, new_lm_hash);
2432
2433         encode_pw_buffer(lm_pass.data, newpass, STR_UNICODE);
2434         arcfour_crypt(lm_pass.data, old_nt_hash, 516);
2435         E_old_pw_hash(new_nt_hash, old_lm_hash, lm_verifier.hash);
2436
2437         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2438         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2439         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2440
2441         r.in.server = &server;
2442         r.in.account = &account;
2443         r.in.nt_password = &nt_pass;
2444         r.in.nt_verifier = &nt_verifier;
2445         r.in.lm_change = 1;
2446         r.in.lm_password = &lm_pass;
2447         r.in.lm_verifier = &lm_verifier;
2448         r.in.password3 = NULL;
2449         r.out.dominfo = &dominfo;
2450         r.out.reject = &reject;
2451
2452         unix_to_nt_time(&t, time(NULL));
2453
2454         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2455                 "ChangePasswordUser3 failed");
2456         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2457                         __location__, __FUNCTION__,
2458                         oldpass, newpass, nt_errstr(r.out.result));
2459
2460         torture_comment(tctx, "(%s): dominfo[%s], reject[%s], handle_reject_reason[%s], "
2461                         "last_password_change[%s], dominfo->min_password_age[%lld]\n",
2462                         __location__,
2463                         (dominfo == NULL)? "NULL" : "present",
2464                         reject ? "true" : "false",
2465                         handle_reject_reason ? "true" : "false",
2466                         null_nttime(last_password_change) ? "null" : "not null",
2467                         dominfo ? (long long)dominfo->min_password_age : (long long)0);
2468
2469         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)
2470             && dominfo
2471             && reject
2472             && handle_reject_reason
2473             && (!null_nttime(last_password_change) || !dominfo->min_password_age)) {
2474                 if (dominfo->password_properties & DOMAIN_REFUSE_PASSWORD_CHANGE ) {
2475
2476                         if (reject && (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR)) {
2477                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2478                                         SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2479                                 return false;
2480                         }
2481                 }
2482
2483                 /* We tested the order of precendence which is as follows:
2484
2485                 * pwd min_age
2486                 * pwd length
2487                 * pwd complexity
2488                 * pwd history
2489
2490                 Guenther */
2491
2492                 if ((dominfo->min_password_age < 0) && !null_nttime(last_password_change) &&
2493                            (last_password_change - dominfo->min_password_age > t)) {
2494
2495                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2496                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2497                                         SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2498                                 return false;
2499                         }
2500
2501                 } else if ((dominfo->min_password_length > 0) &&
2502                            (strlen(newpass) < dominfo->min_password_length)) {
2503
2504                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2505                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_PASSWORD_TOO_SHORT (%d), got %d\n",
2506                                         SAM_PWD_CHANGE_PASSWORD_TOO_SHORT, reject->extendedFailureReason);
2507                                 return false;
2508                         }
2509
2510                 } else if ((dominfo->password_history_length > 0) &&
2511                             strequal(oldpass, newpass)) {
2512
2513                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_PWD_IN_HISTORY) {
2514                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_PWD_IN_HISTORY (%d), got %d\n",
2515                                         SAM_PWD_CHANGE_PWD_IN_HISTORY, reject->extendedFailureReason);
2516                                 return false;
2517                         }
2518                 } else if (dominfo->password_properties & DOMAIN_PASSWORD_COMPLEX) {
2519
2520                         if (reject->extendedFailureReason != SAM_PWD_CHANGE_NOT_COMPLEX) {
2521                                 torture_warning(tctx, "expected SAM_PWD_CHANGE_NOT_COMPLEX (%d), got %d\n",
2522                                         SAM_PWD_CHANGE_NOT_COMPLEX, reject->extendedFailureReason);
2523                                 return false;
2524                         }
2525
2526                 }
2527
2528                 if (reject->extendedFailureReason == SAM_PWD_CHANGE_PASSWORD_TOO_SHORT) {
2529                         /* retry with adjusted size */
2530                         return test_ChangePasswordUser3(p, tctx, account_string,
2531                                                         dominfo->min_password_length,
2532                                                         password, NULL, 0, false);
2533
2534                 }
2535
2536         } else if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2537                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2538                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2539                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2540                         return false;
2541                 }
2542                 /* Perhaps the server has a 'min password age' set? */
2543
2544         } else {
2545                 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3");
2546
2547                 *password = talloc_strdup(tctx, newpass);
2548         }
2549
2550         return ret;
2551 }
2552
2553 bool test_ChangePasswordRandomBytes(struct dcerpc_pipe *p, struct torture_context *tctx,
2554                                     const char *account_string,
2555                                     struct policy_handle *handle,
2556                                     char **password)
2557 {
2558         NTSTATUS status;
2559         struct samr_ChangePasswordUser3 r;
2560         struct samr_SetUserInfo s;
2561         union samr_UserInfo u;
2562         DATA_BLOB session_key;
2563         DATA_BLOB confounded_session_key = data_blob_talloc(tctx, NULL, 16);
2564         uint8_t confounder[16];
2565         MD5_CTX ctx;
2566
2567         bool ret = true;
2568         struct lsa_String server, account;
2569         struct samr_CryptPassword nt_pass;
2570         struct samr_Password nt_verifier;
2571         DATA_BLOB new_random_pass;
2572         char *newpass;
2573         char *oldpass;
2574         struct dcerpc_binding_handle *b = p->binding_handle;
2575         uint8_t old_nt_hash[16], new_nt_hash[16];
2576         NTTIME t;
2577         struct samr_DomInfo1 *dominfo = NULL;
2578         struct userPwdChangeFailureInformation *reject = NULL;
2579
2580         new_random_pass = samr_very_rand_pass(tctx, 128);
2581
2582         torture_assert(tctx, *password != NULL,
2583                                    "Failing ChangePasswordUser3 as old password was NULL.  Previous test failed?");
2584
2585         oldpass = *password;
2586         server.string = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
2587         init_lsa_String(&account, account_string);
2588
2589         s.in.user_handle = handle;
2590         s.in.info = &u;
2591         s.in.level = 25;
2592
2593         ZERO_STRUCT(u);
2594
2595         u.info25.info.fields_present = SAMR_FIELD_NT_PASSWORD_PRESENT;
2596
2597         set_pw_in_buffer(u.info25.password.data, &new_random_pass);
2598
2599         status = dcerpc_fetch_session_key(p, &session_key);
2600         if (!NT_STATUS_IS_OK(status)) {
2601                 torture_warning(tctx, "SetUserInfo level %u - no session key - %s\n",
2602                        s.in.level, nt_errstr(status));
2603                 return false;
2604         }
2605
2606         generate_random_buffer((uint8_t *)confounder, 16);
2607
2608         MD5Init(&ctx);
2609         MD5Update(&ctx, confounder, 16);
2610         MD5Update(&ctx, session_key.data, session_key.length);
2611         MD5Final(confounded_session_key.data, &ctx);
2612
2613         arcfour_crypt_blob(u.info25.password.data, 516, &confounded_session_key);
2614         memcpy(&u.info25.password.data[516], confounder, 16);
2615
2616         torture_comment(tctx, "Testing SetUserInfo level 25 (set password ex) with a password made up of only random bytes\n");
2617
2618         torture_assert_ntstatus_ok(tctx, dcerpc_samr_SetUserInfo_r(b, tctx, &s),
2619                 "SetUserInfo failed");
2620         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2621                         __location__, __FUNCTION__,
2622                         oldpass, "RANDOM", nt_errstr(s.out.result));
2623         if (!NT_STATUS_IS_OK(s.out.result)) {
2624                 torture_warning(tctx, "SetUserInfo level %u failed - %s\n",
2625                        s.in.level, nt_errstr(s.out.result));
2626                 ret = false;
2627         }
2628
2629         torture_comment(tctx, "Testing ChangePasswordUser3 with a password made up of only random bytes\n");
2630
2631         mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2632
2633         new_random_pass = samr_very_rand_pass(tctx, 128);
2634
2635         mdfour(new_nt_hash, new_random_pass.data, new_random_pass.length);
2636
2637         set_pw_in_buffer(nt_pass.data, &new_random_pass);
2638         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2639         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2640
2641         r.in.server = &server;
2642         r.in.account = &account;
2643         r.in.nt_password = &nt_pass;
2644         r.in.nt_verifier = &nt_verifier;
2645         r.in.lm_change = 0;
2646         r.in.lm_password = NULL;
2647         r.in.lm_verifier = NULL;
2648         r.in.password3 = NULL;
2649         r.out.dominfo = &dominfo;
2650         r.out.reject = &reject;
2651
2652         unix_to_nt_time(&t, time(NULL));
2653
2654         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2655                 "ChangePasswordUser3 failed");
2656         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2657                         __location__, __FUNCTION__,
2658                         oldpass, "RANDOM", nt_errstr(r.out.result));
2659
2660         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2661                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2662                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2663                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2664                         return false;
2665                 }
2666                 /* Perhaps the server has a 'min password age' set? */
2667
2668         } else if (!NT_STATUS_IS_OK(r.out.result)) {
2669                 torture_warning(tctx, "ChangePasswordUser3 failed - %s\n", nt_errstr(r.out.result));
2670                 ret = false;
2671         }
2672
2673         newpass = samr_rand_pass(tctx, 128);
2674
2675         mdfour(old_nt_hash, new_random_pass.data, new_random_pass.length);
2676
2677         E_md4hash(newpass, new_nt_hash);
2678
2679         encode_pw_buffer(nt_pass.data, newpass, STR_UNICODE);
2680         arcfour_crypt(nt_pass.data, old_nt_hash, 516);
2681         E_old_pw_hash(new_nt_hash, old_nt_hash, nt_verifier.hash);
2682
2683         r.in.server = &server;
2684         r.in.account = &account;
2685         r.in.nt_password = &nt_pass;
2686         r.in.nt_verifier = &nt_verifier;
2687         r.in.lm_change = 0;
2688         r.in.lm_password = NULL;
2689         r.in.lm_verifier = NULL;
2690         r.in.password3 = NULL;
2691         r.out.dominfo = &dominfo;
2692         r.out.reject = &reject;
2693
2694         unix_to_nt_time(&t, time(NULL));
2695
2696         torture_assert_ntstatus_ok(tctx, dcerpc_samr_ChangePasswordUser3_r(b, tctx, &r),
2697                 "ChangePasswordUser3 failed");
2698         torture_comment(tctx, "(%s:%s) old_password[%s] new_password[%s] status[%s]\n",
2699                         __location__, __FUNCTION__,
2700                         oldpass, newpass, nt_errstr(r.out.result));
2701
2702         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_PASSWORD_RESTRICTION)) {
2703                 if (reject && reject->extendedFailureReason != SAM_PWD_CHANGE_NO_ERROR) {
2704                         torture_warning(tctx, "expected SAM_PWD_CHANGE_NO_ERROR (%d), got %d\n",
2705                                SAM_PWD_CHANGE_NO_ERROR, reject->extendedFailureReason);
2706                         return false;
2707                 }
2708                 /* Perhaps the server has a 'min password age' set? */
2709
2710         } else {
2711                 torture_assert_ntstatus_ok(tctx, r.out.result, "ChangePasswordUser3 (on second random password)");
2712                 *password = talloc_strdup(tctx, newpass);
2713         }
2714
2715         return ret;
2716 }
2717
2718
2719 static bool test_GetMembersInAlias(struct dcerpc_binding_handle *b,
2720                                    struct torture_context *tctx,
2721                                    struct policy_handle *alias_handle)
2722 {
2723         struct samr_GetMembersInAlias r;
2724         struct lsa_SidArray sids;
2725
2726         torture_comment(tctx, "Testing GetMembersInAlias\n");
2727
2728         r.in.alias_handle = alias_handle;
2729         r.out.sids = &sids;
2730
2731         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetMembersInAlias_r(b, tctx, &r),
2732                 "GetMembersInAlias failed");
2733         torture_assert_ntstatus_ok(tctx, r.out.result, "GetMembersInAlias failed");
2734
2735         return true;
2736 }
2737
2738 static bool test_AddMemberToAlias(struct dcerpc_binding_handle *b,
2739                                   struct torture_context *tctx,
2740                                   struct policy_handle *alias_handle,
2741                                   const struct dom_sid *domain_sid)
2742 {
2743         struct samr_AddAliasMember r;
2744         struct samr_DeleteAliasMember d;
2745         struct dom_sid *sid;
2746
2747         sid = dom_sid_add_rid(tctx, domain_sid, 512);
2748
2749         torture_comment(tctx, "Testing AddAliasMember\n");
2750         r.in.alias_handle = alias_handle;
2751         r.in.sid = sid;
2752
2753         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddAliasMember_r(b, tctx, &r),
2754                 "AddAliasMember failed");
2755         torture_assert_ntstatus_ok(tctx, r.out.result, "AddAliasMember failed");
2756
2757         d.in.alias_handle = alias_handle;
2758         d.in.sid = sid;
2759
2760         torture_assert_ntstatus_ok(tctx, dcerpc_samr_DeleteAliasMember_r(b, tctx, &d),
2761                 "DeleteAliasMember failed");
2762         torture_assert_ntstatus_ok(tctx, d.out.result, "DelAliasMember failed");
2763
2764         return true;
2765 }
2766
2767 static bool test_AddMultipleMembersToAlias(struct dcerpc_binding_handle *b,
2768                                            struct torture_context *tctx,
2769                                            struct policy_handle *alias_handle)
2770 {
2771         struct samr_AddMultipleMembersToAlias a;
2772         struct samr_RemoveMultipleMembersFromAlias r;
2773         struct lsa_SidArray sids;
2774
2775         torture_comment(tctx, "Testing AddMultipleMembersToAlias\n");
2776         a.in.alias_handle = alias_handle;
2777         a.in.sids = &sids;
2778
2779         sids.num_sids = 3;
2780         sids.sids = talloc_array(tctx, struct lsa_SidPtr, 3);
2781
2782         sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2783         sids.sids[1].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-2");
2784         sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-3");
2785
2786         torture_assert_ntstatus_ok(tctx, dcerpc_samr_AddMultipleMembersToAlias_r(b, tctx, &a),
2787                 "AddMultipleMembersToAlias failed");
2788         torture_assert_ntstatus_ok(tctx, a.out.result, "AddMultipleMembersToAlias");
2789
2790
2791         torture_comment(tctx, "Testing RemoveMultipleMembersFromAlias\n");
2792         r.in.alias_handle = alias_handle;
2793         r.in.sids = &sids;
2794
2795         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2796                 "RemoveMultipleMembersFromAlias failed");
2797         torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2798
2799         /* strange! removing twice doesn't give any error */
2800         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2801                 "RemoveMultipleMembersFromAlias failed");
2802         torture_assert_ntstatus_ok(tctx, r.out.result, "RemoveMultipleMembersFromAlias failed");
2803
2804         /* but removing an alias that isn't there does */
2805         sids.sids[2].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-4");
2806
2807         torture_assert_ntstatus_ok(tctx, dcerpc_samr_RemoveMultipleMembersFromAlias_r(b, tctx, &r),
2808                 "RemoveMultipleMembersFromAlias failed");
2809         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_OBJECT_NAME_NOT_FOUND, "RemoveMultipleMembersFromAlias");
2810
2811         return true;
2812 }
2813
2814 static bool test_GetAliasMembership(struct dcerpc_binding_handle *b,
2815                                     struct torture_context *tctx,
2816                                     struct policy_handle *domain_handle)
2817 {
2818         struct samr_GetAliasMembership r;
2819         struct lsa_SidArray sids;
2820         struct samr_Ids rids;
2821
2822         torture_comment(tctx, "Testing GetAliasMembership\n");
2823
2824         r.in.domain_handle      = domain_handle;
2825         r.in.sids               = &sids;
2826         r.out.rids              = &rids;
2827
2828         sids.num_sids = 0;
2829         sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2830
2831         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2832                 "GetAliasMembership failed");
2833         torture_assert_ntstatus_ok(tctx, r.out.result,
2834                 "samr_GetAliasMembership failed");
2835
2836         torture_assert_int_equal(tctx, sids.num_sids, rids.count,
2837                 "protocol misbehaviour");
2838
2839         sids.num_sids = 1;
2840         sids.sids = talloc_zero_array(tctx, struct lsa_SidPtr, sids.num_sids);
2841         sids.sids[0].sid = dom_sid_parse_talloc(tctx, "S-1-5-32-1-2-3-1");
2842
2843         torture_assert_ntstatus_ok(tctx, dcerpc_samr_GetAliasMembership_r(b, tctx, &r),
2844                 "samr_GetAliasMembership failed");
2845         torture_assert_ntstatus_ok(tctx, r.out.result,
2846                 "samr_GetAliasMembership failed");
2847
2848 #if 0
2849         /* only true for w2k8 it seems
2850          * win7, xp, w2k3 will return a 0 length array pointer */
2851
2852         if (rids.ids && (rids.count == 0)) {
2853                 torture_fail(tctx, "samr_GetAliasMembership returned 0 count and a rids array");
2854         }
2855 #endif
2856         if (!rids.ids && rids.count) {
2857                 torture_fail(tctx, "samr_GetAliasMembership returned non-0 count but no rids");
2858         }
2859
2860         return true;
2861 }
2862
2863 static bool test_TestPrivateFunctionsUser(struct dcerpc_binding_handle *b,
2864                                           struct torture_context *tctx,
2865                                           struct policy_handle *user_handle)
2866 {
2867         struct samr_TestPrivateFunctionsUser r;
2868
2869         torture_comment(tctx, "Testing TestPrivateFunctionsUser\n");
2870
2871         r.in.user_handle = user_handle;
2872
2873         torture_assert_ntstatus_ok(tctx, dcerpc_samr_TestPrivateFunctionsUser_r(b, tctx, &r),
2874                 "TestPrivateFunctionsUser failed");
2875         torture_assert_ntstatus_equal(tctx, r.out.result, NT_STATUS_NOT_IMPLEMENTED, "TestPrivateFunctionsUser");
2876
2877         return true;
2878 }
2879
2880 static bool test_QueryUserInfo_pwdlastset(struct dcerpc_binding_handle *b,
2881                                           struct torture_context *tctx,
2882                                           struct policy_handle *handle,
2883                                           bool use_info2,
2884                                           NTTIME *pwdlastset)
2885 {
2886         NTSTATUS status;
2887         uint16_t levels[] = { /* 3, */ 5, 21 };
2888         int i;
2889         NTTIME pwdlastset3 = 0;
2890         NTTIME pwdlastset5 = 0;
2891         NTTIME pwdlastset21 = 0;
2892
2893         torture_comment(tctx, "Testing QueryUserInfo%s level 5 and 21 call ",
2894                         use_info2 ? "2":"");
2895
2896         for (i=0; i<ARRAY_SIZE(levels); i++) {
2897
2898                 struct samr_QueryUserInfo r;
2899                 struct samr_QueryUserInfo2 r2;
2900                 union samr_UserInfo *info;
2901
2902                 if (use_info2) {
2903                         r2.in.user_handle = handle;
2904                         r2.in.level = levels[i];
2905                         r2.out.info = &info;
2906                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo2_r(b, tctx, &r2),
2907                                 "QueryUserInfo2 failed");
2908                         status = r2.out.result;
2909
2910                 } else {
2911                         r.in.user_handle = handle;
2912                         r.in.level = levels[i];
2913                         r.out.info = &info;
2914                         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
2915                                 "QueryUserInfo failed");
2916                         status = r.out.result;
2917                 }
2918
2919                 if (!NT_STATUS_IS_OK(status) &&
2920                     !NT_STATUS_EQUAL(status, NT_STATUS_INVALID_INFO_CLASS)) {
2921                         torture_warning(tctx, "QueryUserInfo%s level %u failed - %s\n",
2922                                use_info2 ? "2":"", levels[i], nt_errstr(status));
2923                         return false;
2924                 }
2925
2926                 switch (levels[i]) {
2927                 case 3:
2928                         pwdlastset3 = info->info3.last_password_change;
2929                         break;
2930                 case 5:
2931                         pwdlastset5 = info->info5.last_password_change;
2932                         break;
2933                 case 21:
2934                         pwdlastset21 = info->info21.last_password_change;
2935                         break;
2936                 default:
2937                         return false;
2938                 }
2939         }
2940         /* torture_assert_int_equal(tctx, pwdlastset3, pwdlastset5,
2941                                     "pwdlastset mixup"); */
2942         torture_assert_int_equal(tctx, pwdlastset5, pwdlastset21,
2943                                  "pwdlastset mixup");
2944
2945         *pwdlastset = pwdlastset21;
2946
2947         torture_comment(tctx, "(pwdlastset: %llu)\n",
2948                         (unsigned long long) *pwdlastset);
2949
2950         return true;
2951 }
2952
2953 static bool test_SamLogon(struct torture_context *tctx,
2954                           struct dcerpc_pipe *p,
2955                           struct cli_credentials *machine_credentials,
2956                           struct cli_credentials *test_credentials,
2957                           NTSTATUS expected_result,
2958                           bool interactive)
2959 {
2960         NTSTATUS status;
2961         struct netr_LogonSamLogonEx r;
2962         union netr_LogonLevel logon;
2963         union netr_Validation validation;
2964         uint8_t authoritative;
2965         struct netr_IdentityInfo identity;
2966         struct netr_NetworkInfo ninfo;
2967         struct netr_PasswordInfo pinfo;
2968         DATA_BLOB names_blob, chal, lm_resp, nt_resp;
2969         int flags = CLI_CRED_NTLM_AUTH;
2970         uint32_t samlogon_flags = 0;
2971         struct netlogon_creds_CredentialState *creds;
2972         struct netr_Authenticator a;
2973         struct dcerpc_binding_handle *b = p->binding_handle;
2974
2975         torture_assert(tctx, (creds = cli_credentials_get_netlogon_creds(machine_credentials)), "");
2976
2977         if (lpcfg_client_lanman_auth(tctx->lp_ctx)) {
2978                 flags |= CLI_CRED_LANMAN_AUTH;
2979         }
2980
2981         if (lpcfg_client_ntlmv2_auth(tctx->lp_ctx)) {
2982                 flags |= CLI_CRED_NTLMv2_AUTH;
2983         }
2984
2985         cli_credentials_get_ntlm_username_domain(test_credentials, tctx,
2986                                                  &identity.account_name.string,
2987                                                  &identity.domain_name.string);
2988
2989         identity.parameter_control =
2990                 MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
2991                 MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
2992         identity.logon_id_low = 0;
2993         identity.logon_id_high = 0;
2994         identity.workstation.string = cli_credentials_get_workstation(test_credentials);
2995
2996         if (interactive) {
2997                 netlogon_creds_client_authenticator(creds, &a);
2998
2999                 if (!E_deshash(cli_credentials_get_password(test_credentials), pinfo.lmpassword.hash)) {
3000                         ZERO_STRUCT(pinfo.lmpassword.hash);
3001                 }
3002                 E_md4hash(cli_credentials_get_password(test_credentials), pinfo.ntpassword.hash);
3003
3004                 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
3005                         netlogon_creds_aes_encrypt(creds, pinfo.lmpassword.hash, 16);
3006                         netlogon_creds_aes_encrypt(creds, pinfo.ntpassword.hash, 16);
3007                 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
3008                         netlogon_creds_arcfour_crypt(creds, pinfo.lmpassword.hash, 16);
3009                         netlogon_creds_arcfour_crypt(creds, pinfo.ntpassword.hash, 16);
3010                 } else {
3011                         netlogon_creds_des_encrypt(creds, &pinfo.lmpassword);
3012                         netlogon_creds_des_encrypt(creds, &pinfo.ntpassword);
3013                 }
3014
3015                 pinfo.identity_info = identity;
3016                 logon.password = &pinfo;
3017
3018                 r.in.logon_level = NetlogonInteractiveInformation;
3019         } else {
3020                 generate_random_buffer(ninfo.challenge,
3021                                        sizeof(ninfo.challenge));
3022                 chal = data_blob_const(ninfo.challenge,
3023                                        sizeof(ninfo.challenge));
3024
3025                 names_blob = NTLMv2_generate_names_blob(tctx, cli_credentials_get_workstation(test_credentials),
3026                                                         cli_credentials_get_domain(test_credentials));
3027
3028                 status = cli_credentials_get_ntlm_response(test_credentials, tctx,
3029                                                            &flags,
3030                                                            chal,
3031                                                            names_blob,
3032                                                            &lm_resp, &nt_resp,
3033                                                            NULL, NULL);
3034                 torture_assert_ntstatus_ok(tctx, status, "cli_credentials_get_ntlm_response failed");
3035
3036                 ninfo.lm.data = lm_resp.data;
3037                 ninfo.lm.length = lm_resp.length;
3038
3039                 ninfo.nt.data = nt_resp.data;
3040                 ninfo.nt.length = nt_resp.length;
3041
3042                 ninfo.identity_info = identity;
3043                 logon.network = &ninfo;
3044
3045                 r.in.logon_level = NetlogonNetworkInformation;
3046         }
3047
3048         r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
3049         r.in.computer_name = cli_credentials_get_workstation(test_credentials);
3050         r.in.logon = &logon;
3051         r.in.flags = &samlogon_flags;
3052         r.out.flags = &samlogon_flags;
3053         r.out.validation = &validation;
3054         r.out.authoritative = &authoritative;
3055
3056         torture_comment(tctx, "Testing LogonSamLogon with name %s\n", identity.account_name.string);
3057
3058         r.in.validation_level = 6;
3059
3060         torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3061                 "netr_LogonSamLogonEx failed");
3062         if (NT_STATUS_EQUAL(r.out.result, NT_STATUS_INVALID_INFO_CLASS)) {
3063                 r.in.validation_level = 3;
3064                 torture_assert_ntstatus_ok(tctx, dcerpc_netr_LogonSamLogonEx_r(b, tctx, &r),
3065                         "netr_LogonSamLogonEx failed");
3066         }
3067         if (!NT_STATUS_IS_OK(r.out.result)) {
3068                 torture_assert_ntstatus_equal(tctx, r.out.result, expected_result, "LogonSamLogonEx failed");
3069                 return true;
3070         } else {
3071                 torture_assert_ntstatus_ok(tctx, r.out.result, "LogonSamLogonEx failed");
3072         }
3073
3074         return true;
3075 }
3076
3077 static bool test_SamLogon_with_creds(struct torture_context *tctx,
3078                                      struct dcerpc_pipe *p,
3079                                      struct cli_credentials *machine_creds,
3080                                      const char *acct_name,
3081                                      const char *password,
3082                                      NTSTATUS expected_samlogon_result,
3083                                      bool interactive)
3084 {
3085         bool ret = true;
3086         struct cli_credentials *test_credentials;
3087
3088         test_credentials = cli_credentials_init(tctx);
3089
3090         cli_credentials_set_workstation(test_credentials,
3091                                         cli_credentials_get_workstation(machine_creds), CRED_SPECIFIED);
3092         cli_credentials_set_domain(test_credentials,
3093                                    cli_credentials_get_domain(machine_creds), CRED_SPECIFIED);
3094         cli_credentials_set_username(test_credentials,
3095                                      acct_name, CRED_SPECIFIED);
3096         cli_credentials_set_password(test_credentials,
3097                                      password, CRED_SPECIFIED);
3098
3099         torture_comment(tctx, "Testing samlogon (%s) as %s password: %s\n",
3100                 interactive ? "interactive" : "network", acct_name, password);
3101
3102         if (!test_SamLogon(tctx, p, machine_creds, test_credentials,
3103                             expected_samlogon_result, interactive)) {
3104                 torture_warning(tctx, "new password did not work\n");
3105                 ret = false;
3106         }
3107
3108         return ret;
3109 }
3110
3111 static bool test_SetPassword_level(struct dcerpc_pipe *p,
3112                                    struct dcerpc_pipe *np,
3113                                    struct torture_context *tctx,
3114                                    struct policy_handle *handle,
3115                                    uint16_t level,
3116                                    uint32_t fields_present,
3117                                    uint8_t password_expired,
3118                                    bool *matched_expected_error,
3119                                    bool use_setinfo2,
3120                                    const char *acct_name,
3121                                    char **password,
3122                                    struct cli_credentials *machine_creds,
3123                                    bool use_queryinfo2,
3124                                    NTTIME *pwdlastset,
3125                                    NTSTATUS expected_samlogon_result)
3126 {
3127         const char *fields = NULL;
3128         bool ret = true;
3129         struct dcerpc_binding_handle *b = p->binding_handle;
3130
3131         switch (level) {
3132         case 21:
3133         case 23:
3134         case 25:
3135                 fields = talloc_asprintf(tctx, "(fields_present: 0x%08x)",
3136                                          fields_present);
3137                 break;
3138         default:
3139                 break;
3140         }
3141
3142         torture_comment(tctx, "Testing SetUserInfo%s level %d call "
3143                 "(password_expired: %d) %s\n",
3144                 use_setinfo2 ? "2":"", level, password_expired,
3145                 fields ? fields : "");
3146
3147         if (!test_SetUserPass_level_ex(p, tctx, handle, level,
3148                                        fields_present,
3149                                        password,
3150                                        password_expired,
3151                                        use_setinfo2,
3152                                        matched_expected_error)) {
3153                 ret = false;
3154         }
3155
3156         if (!test_QueryUserInfo_pwdlastset(b, tctx, handle,
3157                                            use_queryinfo2,
3158                                            pwdlastset)) {
3159                 ret = false;
3160         }
3161
3162         if (*matched_expected_error == true) {
3163                 return ret;
3164         }
3165
3166         if (!test_SamLogon_with_creds(tctx, np,
3167                                       machine_creds,
3168                                       acct_name,
3169                                       *password,
3170                                       expected_samlogon_result,
3171                                       false)) {
3172                 ret = false;
3173         }
3174
3175         return ret;
3176 }
3177
3178 static bool setup_schannel_netlogon_pipe(struct torture_context *tctx,
3179                                          struct cli_credentials *credentials,
3180                                          struct dcerpc_pipe **p)
3181 {
3182         struct dcerpc_binding *b;
3183
3184         torture_assert_ntstatus_ok(tctx, torture_rpc_binding(tctx, &b),
3185                 "failed to get rpc binding");
3186
3187         /* We have to use schannel, otherwise the SamLogonEx fails
3188          * with INTERNAL_ERROR */
3189
3190         b->flags &= ~DCERPC_AUTH_OPTIONS;
3191         b->flags |= DCERPC_SCHANNEL | DCERPC_SIGN | DCERPC_SCHANNEL_AUTO;
3192
3193         torture_assert_ntstatus_ok(tctx,
3194                 dcerpc_pipe_connect_b(tctx, p, b, &ndr_table_netlogon,
3195                                       credentials, tctx->ev, tctx->lp_ctx),
3196                 "failed to bind to netlogon");
3197
3198         return true;
3199 }
3200
3201 static bool test_SetPassword_pwdlastset(struct dcerpc_pipe *p,
3202                                         struct torture_context *tctx,
3203                                         uint32_t acct_flags,
3204                                         const char *acct_name,
3205                                         struct policy_handle *handle,
3206                                         char **password,
3207                                         struct cli_credentials *machine_credentials)
3208 {
3209         int s = 0, q = 0, f = 0, l = 0, z = 0;
3210         bool ret = true;
3211         int delay = 50000;
3212         bool set_levels[] = { false, true };
3213         bool query_levels[] = { false, true };
3214         uint32_t levels[] = { 18, 21, 26, 23, 24, 25 }; /* Second half only used when TEST_ALL_LEVELS defined */
3215         uint32_t nonzeros[] = { 1, 24 };
3216         uint32_t fields_present[] = {
3217                 0,
3218                 SAMR_FIELD_EXPIRED_FLAG,
3219                 SAMR_FIELD_LAST_PWD_CHANGE,
3220                 SAMR_FIELD_EXPIRED_FLAG | SAMR_FIELD_LAST_PWD_CHANGE,
3221                 SAMR_FIELD_COMMENT,
3222                 SAMR_FIELD_NT_PASSWORD_PRESENT,
3223                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3224                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT,
3225                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE,
3226                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3227                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_EXPIRED_FLAG,
3228                 SAMR_FIELD_NT_PASSWORD_PRESENT | SAMR_FIELD_LM_PASSWORD_PRESENT | SAMR_FIELD_LAST_PWD_CHANGE | SAMR_FIELD_EXPIRED_FLAG
3229         };
3230         struct dcerpc_pipe *np = NULL;
3231
3232         if (torture_setting_bool(tctx, "samba3", false) ||
3233             torture_setting_bool(tctx, "samba4", false)) {
3234                 delay = 999999;
3235                 torture_comment(tctx, "Samba3 has second granularity, setting delay to: %d\n",
3236                         delay);
3237         }
3238
3239         torture_assert(tctx, setup_schannel_netlogon_pipe(tctx, machine_credentials, &np), "");
3240
3241         /* set to 1 to enable testing for all possible opcode
3242            (SetUserInfo, SetUserInfo2, QueryUserInfo, QueryUserInfo2)
3243            combinations */
3244 #if 0
3245 #define TEST_ALL_LEVELS 1
3246 #define TEST_SET_LEVELS 1
3247 #define TEST_QUERY_LEVELS 1
3248 #endif
3249 #ifdef TEST_ALL_LEVELS
3250         for (l=0; l<ARRAY_SIZE(levels); l++) {
3251 #else
3252         for (l=0; l<(ARRAY_SIZE(levels))/2; l++) {
3253 #endif
3254         for (z=0; z<ARRAY_SIZE(nonzeros); z++) {
3255         for (f=0; f<ARRAY_SIZE(fields_present); f++) {
3256 #ifdef TEST_SET_LEVELS
3257         for (s=0; s<ARRAY_SIZE(set_levels); s++) {
3258 #endif
3259 #ifdef TEST_QUERY_LEVELS
3260         for (q=0; q<ARRAY_SIZE(query_levels); q++) {
3261 #endif
3262                 NTTIME pwdlastset_old = 0;
3263                 NTTIME pwdlastset_new = 0;
3264                 bool matched_expected_error = false;
3265                 NTSTATUS expected_samlogon_result = NT_STATUS_ACCOUNT_DISABLED;
3266
3267                 torture_comment(tctx, "------------------------------\n"
3268                                 "Testing pwdLastSet attribute for flags: 0x%08x "
3269                                 "(s: %d (l: %d), q: %d)\n",
3270                                 acct_flags, s, levels[l], q);
3271
3272                 switch (levels[l]) {
3273                 case 21:
3274                 case 23:
3275                 case 25:
3276                         if (!((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3277                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT))) {
3278                                 expected_samlogon_result = NT_STATUS_WRONG_PASSWORD;
3279                         }
3280                         break;
3281                 }
3282
3283
3284                 /* set #1 */
3285
3286                 /* set a password and force password change (pwdlastset 0) by
3287                  * setting the password expired flag to a non-0 value */
3288
3289                 if (!test_SetPassword_level(p, np, tctx, handle,
3290                                             levels[l],
3291                                             fields_present[f],
3292                                             nonzeros[z],
3293                                             &matched_expected_error,
3294                                             set_levels[s],
3295                                             acct_name,
3296                                             password,
3297                                             machine_credentials,
3298                                             query_levels[q],
3299                                             &pwdlastset_new,
3300                                             expected_samlogon_result)) {
3301                         ret = false;
3302                 }
3303
3304                 if (matched_expected_error == true) {
3305                         /* skipping on expected failure */
3306                         continue;
3307                 }
3308
3309                 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3310                  * set without the SAMR_FIELD_EXPIRED_FLAG */
3311
3312                 switch (levels[l]) {
3313                 case 21:
3314                 case 23:
3315                 case 25:
3316                         if ((pwdlastset_new != 0) &&
3317                             !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3318                                 torture_comment(tctx, "not considering a non-0 "
3319                                         "pwdLastSet as a an error as the "
3320                                         "SAMR_FIELD_EXPIRED_FLAG has not "
3321                                         "been set\n");
3322                                 break;
3323                         }
3324                         break;
3325                 default:
3326                         if (pwdlastset_new != 0) {
3327                                 torture_warning(tctx, "pwdLastSet test failed: "
3328                                         "expected pwdLastSet 0 but got %llu\n",
3329                                         (unsigned long long) pwdlastset_old);
3330                                 ret = false;
3331                         }
3332                         break;
3333                 }
3334
3335                 switch (levels[l]) {
3336                 case 21:
3337                 case 23:
3338                 case 25:
3339                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3340                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3341                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3342                              (pwdlastset_old >= pwdlastset_new)) {
3343                                 torture_warning(tctx, "pwdlastset not increasing\n");
3344                                 ret = false;
3345                         }
3346                         break;
3347                 }
3348
3349                 pwdlastset_old = pwdlastset_new;
3350
3351                 usleep(delay);
3352
3353                 /* set #2 */
3354
3355                 /* set a password, pwdlastset needs to get updated (increased
3356                  * value), password_expired value used here is 0 */
3357
3358                 if (!test_SetPassword_level(p, np, tctx, handle,
3359                                             levels[l],
3360                                             fields_present[f],
3361                                             0,
3362                                             &matched_expected_error,
3363                                             set_levels[s],
3364                                             acct_name,
3365                                             password,
3366                                             machine_credentials,
3367                                             query_levels[q],
3368                                             &pwdlastset_new,
3369                                             expected_samlogon_result)) {
3370                         ret = false;
3371                 }
3372
3373                 /* when a password has been changed, pwdlastset must not be 0 afterwards
3374                  * and must be larger then the old value */
3375
3376                 switch (levels[l]) {
3377                 case 21:
3378                 case 23:
3379                 case 25:
3380                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3381                          * password has been changed, old and new pwdlastset
3382                          * need to be the same value */
3383
3384                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3385                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3386                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3387                         {
3388                                 torture_assert_int_equal(tctx, pwdlastset_old,
3389                                         pwdlastset_new, "pwdlastset must be equal");
3390                                 break;
3391                         }
3392                         break;
3393                 default:
3394                         if (pwdlastset_old >= pwdlastset_new) {
3395                                 torture_warning(tctx, "pwdLastSet test failed: "
3396                                         "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3397                                         (unsigned long long) pwdlastset_old,
3398                                         (unsigned long long) pwdlastset_new);
3399                                 ret = false;
3400                         }
3401                         if (pwdlastset_new == 0) {
3402                                 torture_warning(tctx, "pwdLastSet test failed: "
3403                                         "expected non-0 pwdlastset, got: %llu\n",
3404                                         (unsigned long long) pwdlastset_new);
3405                                 ret = false;
3406                         }
3407                         break;
3408                 }
3409
3410                 switch (levels[l]) {
3411                 case 21:
3412                 case 23:
3413                 case 25:
3414                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3415                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3416                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3417                              (pwdlastset_old >= pwdlastset_new)) {
3418                                 torture_warning(tctx, "pwdlastset not increasing\n");
3419                                 ret = false;
3420                         }
3421                         break;
3422                 }
3423
3424                 pwdlastset_old = pwdlastset_new;
3425
3426                 usleep(delay);
3427
3428                 /* set #2b */
3429
3430                 /* set a password, pwdlastset needs to get updated (increased
3431                  * value), password_expired value used here is 0 */
3432
3433                 if (!test_SetPassword_level(p, np, tctx, handle,
3434                                             levels[l],
3435                                             fields_present[f],
3436                                             0,
3437                                             &matched_expected_error,
3438                                             set_levels[s],
3439                                             acct_name,
3440                                             password,
3441                                             machine_credentials,
3442                                             query_levels[q],
3443                                             &pwdlastset_new,
3444                                             expected_samlogon_result)) {
3445                         ret = false;
3446                 }
3447
3448                 /* when a password has been changed, pwdlastset must not be 0 afterwards
3449                  * and must be larger then the old value */
3450
3451                 switch (levels[l]) {
3452                 case 21:
3453                 case 23:
3454                 case 25:
3455
3456                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3457                          * password has been changed, old and new pwdlastset
3458                          * need to be the same value */
3459
3460                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3461                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3462                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3463                         {
3464                                 torture_assert_int_equal(tctx, pwdlastset_old,
3465                                         pwdlastset_new, "pwdlastset must be equal");
3466                                 break;
3467                         }
3468                         break;
3469                 default:
3470                         if (pwdlastset_old >= pwdlastset_new) {
3471                                 torture_warning(tctx, "pwdLastSet test failed: "
3472                                         "expected last pwdlastset (%llu) < new pwdlastset (%llu)\n",
3473                                         (unsigned long long) pwdlastset_old,
3474                                         (unsigned long long) pwdlastset_new);
3475                                 ret = false;
3476                         }
3477                         if (pwdlastset_new == 0) {
3478                                 torture_warning(tctx, "pwdLastSet test failed: "
3479                                         "expected non-0 pwdlastset, got: %llu\n",
3480                                         (unsigned long long) pwdlastset_new);
3481                                 ret = false;
3482                         }
3483                         break;
3484                 }
3485
3486                 switch (levels[l]) {
3487                 case 21:
3488                 case 23:
3489                 case 25:
3490                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3491                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3492                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3493                              (pwdlastset_old >= pwdlastset_new)) {
3494                                 torture_warning(tctx, "pwdlastset not increasing\n");
3495                                 ret = false;
3496                         }
3497                         break;
3498                 }
3499
3500                 pwdlastset_old = pwdlastset_new;
3501
3502                 usleep(delay);
3503
3504                 /* set #3 */
3505
3506                 /* set a password and force password change (pwdlastset 0) by
3507                  * setting the password expired flag to a non-0 value */
3508
3509                 if (!test_SetPassword_level(p, np, tctx, handle,
3510                                             levels[l],
3511                                             fields_present[f],
3512                                             nonzeros[z],
3513                                             &matched_expected_error,
3514                                             set_levels[s],
3515                                             acct_name,
3516                                             password,
3517                                             machine_credentials,
3518                                             query_levels[q],
3519                                             &pwdlastset_new,
3520                                             expected_samlogon_result)) {
3521                         ret = false;
3522                 }
3523
3524                 /* pwdlastset must be 0 afterwards, except for a level 21, 23 and 25
3525                  * set without the SAMR_FIELD_EXPIRED_FLAG */
3526
3527                 switch (levels[l]) {
3528                 case 21:
3529                 case 23:
3530                 case 25:
3531                         if ((pwdlastset_new != 0) &&
3532                             !(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG)) {
3533                                 torture_comment(tctx, "not considering a non-0 "
3534                                         "pwdLastSet as a an error as the "
3535                                         "SAMR_FIELD_EXPIRED_FLAG has not "
3536                                         "been set\n");
3537                                 break;
3538                         }
3539
3540                         /* SAMR_FIELD_EXPIRED_FLAG has not been set and no
3541                          * password has been changed, old and new pwdlastset
3542                          * need to be the same value */
3543
3544                         if (!(fields_present[f] & SAMR_FIELD_EXPIRED_FLAG) &&
3545                             !((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3546                               (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)))
3547                         {
3548                                 torture_assert_int_equal(tctx, pwdlastset_old,
3549                                         pwdlastset_new, "pwdlastset must be equal");
3550                                 break;
3551                         }
3552                         break;
3553                 default:
3554                         if (pwdlastset_new != 0) {
3555                                 torture_warning(tctx, "pwdLastSet test failed: "
3556                                         "expected pwdLastSet 0, got %llu\n",
3557                                         (unsigned long long) pwdlastset_old);
3558                                 ret = false;
3559                         }
3560                         break;
3561                 }
3562
3563                 switch (levels[l]) {
3564                 case 21:
3565                 case 23:
3566                 case 25:
3567                         if (((fields_present[f] & SAMR_FIELD_NT_PASSWORD_PRESENT) ||
3568                              (fields_present[f] & SAMR_FIELD_LM_PASSWORD_PRESENT)) &&
3569                              (pwdlastset_old > 0) && (pwdlastset_new > 0) &&
3570                              (pwdlastset_old >= pwdlastset_new)) {
3571                                 torture_warning(tctx, "pwdlastset not increasing\n");
3572                                 ret = false;
3573                         }
3574                         break;
3575                 }
3576
3577                 /* if the level we are testing does not have a fields_present
3578                  * field, skip all fields present tests by setting f to to
3579                  * arraysize */
3580                 switch (levels[l]) {
3581                 case 18:
3582                 case 24:
3583                 case 26:
3584                         f = ARRAY_SIZE(fields_present);
3585                         break;
3586                 }
3587
3588 #ifdef TEST_QUERY_LEVELS
3589         }
3590 #endif
3591 #ifdef TEST_SET_LEVELS
3592         }
3593 #endif
3594         } /* fields present */
3595         } /* nonzeros */
3596         } /* levels */
3597
3598 #undef TEST_SET_LEVELS
3599 #undef TEST_QUERY_LEVELS
3600
3601         talloc_free(np);
3602
3603         return ret;
3604 }
3605
3606 static bool test_QueryUserInfo_badpwdcount(struct dcerpc_binding_handle *b,
3607                                            struct torture_context *tctx,
3608                                            struct policy_handle *handle,
3609                                            uint32_t *badpwdcount)
3610 {
3611         union samr_UserInfo *info;
3612         struct samr_QueryUserInfo r;
3613
3614         r.in.user_handle = handle;
3615         r.in.level = 3;
3616         r.out.info = &info;
3617
3618         torture_comment(tctx, "Testing QueryUserInfo level %d", r.in.level);
3619
3620         torture_assert_ntstatus_ok(tctx, dcerpc_samr_QueryUserInfo_r(b, tctx, &r),
3621                 "failed to query userinfo");
3622         torture_assert_ntstatus_ok(tctx, r.out.result,