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