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