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