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