fcf40e17d6fa0cd3a0af3de9e19bbafd52f110b0
[metze/samba/wip.git] / source4 / torture / smb2 / create.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    SMB2 create test suite
5
6    Copyright (C) Andrew Tridgell 2008
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 "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "torture/torture.h"
26 #include "torture/util.h"
27 #include "torture/smb2/proto.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "libcli/security/security.h"
30
31 #include "system/filesys.h"
32 #include "auth/credentials/credentials.h"
33 #include "lib/cmdline/popt_common.h"
34 #include "librpc/gen_ndr/security.h"
35 #include "lib/events/events.h"
36
37 #define FNAME "test_create.dat"
38 #define DNAME "smb2_open"
39
40 #define CHECK_STATUS(status, correct) do { \
41         if (!NT_STATUS_EQUAL(status, correct)) { \
42                 torture_result(tctx, TORTURE_FAIL, \
43                         "(%s) Incorrect status %s - should be %s\n", \
44                          __location__, nt_errstr(status), nt_errstr(correct)); \
45                 return false; \
46         }} while (0)
47
48 #define CHECK_EQUAL(v, correct) do { \
49         if (v != correct) { \
50                 torture_result(tctx, TORTURE_FAIL, \
51                         "(%s) Incorrect value for %s 0x%08llx - " \
52                         "should be 0x%08llx\n", \
53                          __location__, #v, \
54                         (unsigned long long)v, \
55                         (unsigned long long)correct); \
56                 return false;                                   \
57         }} while (0)
58
59 #define CHECK_TIME(t, field) do { \
60         time_t t1, t2; \
61         finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
62         finfo.all_info.in.file.handle = h1; \
63         status = smb2_getinfo_file(tree, tctx, &finfo); \
64         CHECK_STATUS(status, NT_STATUS_OK); \
65         t1 = t & ~1; \
66         t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
67         if (abs(t1-t2) > 2) { \
68                 torture_result(tctx, TORTURE_FAIL, \
69                         "(%s) wrong time for field %s  %s - %s\n", \
70                         __location__, #field, \
71                         timestring(tctx, t1), \
72                         timestring(tctx, t2)); \
73                 dump_all_info(tctx, &finfo); \
74                 ret = false; \
75         }} while (0)
76
77 #define CHECK_NTTIME(t, field) do { \
78         NTTIME t2; \
79         finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
80         finfo.all_info.in.file.handle = h1; \
81         status = smb2_getinfo_file(tree, tctx, &finfo); \
82         CHECK_STATUS(status, NT_STATUS_OK); \
83         t2 = finfo.all_info.out.field; \
84         if (t != t2) { \
85                 torture_result(tctx, TORTURE_FAIL, \
86                         "(%s) wrong time for field %s  %s - %s\n", \
87                        __location__, #field, \
88                        nt_time_string(tctx, t), \
89                        nt_time_string(tctx, t2)); \
90                 dump_all_info(tctx, &finfo); \
91                 ret = false; \
92         }} while (0)
93
94 #define CHECK_ALL_INFO(v, field) do { \
95         finfo.all_info.level = RAW_FILEINFO_ALL_INFORMATION; \
96         finfo.all_info.in.file.handle = h1; \
97         status = smb2_getinfo_file(tree, tctx, &finfo); \
98         CHECK_STATUS(status, NT_STATUS_OK); \
99         if ((v) != (finfo.all_info.out.field)) { \
100                torture_result(tctx, TORTURE_FAIL, \
101                         "(%s) wrong value for field %s  0x%x - 0x%x\n", \
102                         __location__, #field, (int)v,\
103                         (int)(finfo.all_info.out.field)); \
104                 dump_all_info(tctx, &finfo); \
105                 ret = false; \
106         }} while (0)
107
108 #define CHECK_VAL(v, correct) do { \
109         if ((v) != (correct)) { \
110                 torture_result(tctx, TORTURE_FAIL, \
111                         "(%s) wrong value for %s  0x%x - should be 0x%x\n", \
112                        __location__, #v, (int)(v), (int)correct); \
113                 ret = false; \
114         }} while (0)
115
116 #define SET_ATTRIB(sattrib) do { \
117         union smb_setfileinfo sfinfo; \
118         ZERO_STRUCT(sfinfo.basic_info.in); \
119         sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
120         sfinfo.basic_info.in.file.handle = h1; \
121         sfinfo.basic_info.in.attrib = sattrib; \
122         status = smb2_setinfo_file(tree, &sfinfo); \
123         if (!NT_STATUS_IS_OK(status)) { \
124                 torture_comment(tctx, \
125                     "(%s) Failed to set attrib 0x%x on %s\n", \
126                        __location__, sattrib, fname); \
127         }} while (0)
128
129 /*
130   test some interesting combinations found by gentest
131  */
132 static bool test_create_gentest(struct torture_context *tctx, struct smb2_tree *tree)
133 {
134         struct smb2_create io;
135         NTSTATUS status;
136         uint32_t access_mask, file_attributes_set;
137         uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
138         uint32_t not_a_directory_mask, unexpected_mask;
139         union smb_fileinfo q;
140
141         ZERO_STRUCT(io);
142         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
143         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
144         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
145         io.in.share_access = 
146                 NTCREATEX_SHARE_ACCESS_DELETE|
147                 NTCREATEX_SHARE_ACCESS_READ|
148                 NTCREATEX_SHARE_ACCESS_WRITE;
149         io.in.create_options = 0;
150         io.in.fname = FNAME;
151
152         status = smb2_create(tree, tctx, &io);
153         CHECK_STATUS(status, NT_STATUS_OK);
154
155         status = smb2_util_close(tree, io.out.file.handle);
156         CHECK_STATUS(status, NT_STATUS_OK);
157
158         io.in.create_options = 0xF0000000;
159         status = smb2_create(tree, tctx, &io);
160         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
161
162         io.in.create_options = 0;
163
164         io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
165         status = smb2_create(tree, tctx, &io);
166         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
167
168         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
169         status = smb2_create(tree, tctx, &io);
170         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
171
172         io.in.create_disposition = NTCREATEX_DISP_OPEN;
173         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
174         status = smb2_create(tree, tctx, &io);
175         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
176         
177         io.in.create_disposition = NTCREATEX_DISP_CREATE;
178         io.in.desired_access = 0x08000000;
179         status = smb2_create(tree, tctx, &io);
180         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
181
182         io.in.desired_access = 0x04000000;
183         status = smb2_create(tree, tctx, &io);
184         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
185
186         io.in.file_attributes = 0;
187         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
188         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
189         ok_mask = 0;
190         not_supported_mask = 0;
191         invalid_parameter_mask = 0;
192         not_a_directory_mask = 0;
193         unexpected_mask = 0;
194         {
195                 int i;
196                 for (i=0;i<32;i++) {
197                         io.in.create_options = 1<<i;
198                         if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
199                                 continue;
200                         }
201                         status = smb2_create(tree, tctx, &io);
202                         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
203                                 not_supported_mask |= 1<<i;
204                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
205                                 invalid_parameter_mask |= 1<<i;
206                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
207                                 not_a_directory_mask |= 1<<i;
208                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
209                                 ok_mask |= 1<<i;
210                                 status = smb2_util_close(tree, io.out.file.handle);
211                                 CHECK_STATUS(status, NT_STATUS_OK);
212                         } else {
213                                 unexpected_mask |= 1<<i;
214                                 torture_comment(tctx,
215                                     "create option 0x%08x returned %s\n",
216                                     1<<i, nt_errstr(status));
217                         }
218                 }
219         }
220         io.in.create_options = 0;
221
222         CHECK_EQUAL(ok_mask,                0x00efcf7e);
223         CHECK_EQUAL(not_a_directory_mask,   0x00000001);
224         CHECK_EQUAL(not_supported_mask,     0x00102080);
225         CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
226         CHECK_EQUAL(unexpected_mask,        0x00000000);
227
228         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
229         io.in.file_attributes = 0;
230         access_mask = 0;
231         {
232                 int i;
233                 for (i=0;i<32;i++) {
234                         io.in.desired_access = 1<<i;
235                         status = smb2_create(tree, tctx, &io);
236                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
237                             NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
238                                 access_mask |= io.in.desired_access;
239                         } else {
240                                 CHECK_STATUS(status, NT_STATUS_OK);
241                                 status = smb2_util_close(tree, io.out.file.handle);
242                                 CHECK_STATUS(status, NT_STATUS_OK);
243                         }
244                 }
245         }
246
247         if (TARGET_IS_WIN7(tctx)) {
248                 CHECK_EQUAL(access_mask, 0x0de0fe00);
249         } else if (torture_setting_bool(tctx, "samba4", false)) {
250                 CHECK_EQUAL(access_mask, 0x0cf0fe00);
251         } else {
252                 CHECK_EQUAL(access_mask, 0x0df0fe00);
253         }
254
255         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
256         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
257         io.in.file_attributes = 0;
258         ok_mask = 0;
259         invalid_parameter_mask = 0;
260         unexpected_mask = 0;
261         file_attributes_set = 0;
262         {
263                 int i;
264                 for (i=0;i<32;i++) {
265                         io.in.file_attributes = 1<<i;
266                         if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
267                                 continue;
268                         }
269                         smb2_deltree(tree, FNAME);
270                         status = smb2_create(tree, tctx, &io);
271                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
272                                 invalid_parameter_mask |= 1<<i;
273                         } else if (NT_STATUS_IS_OK(status)) {
274                                 uint32_t expected;
275                                 ok_mask |= 1<<i;
276
277                                 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
278                                 io.out.file_attr &= ~FILE_ATTRIBUTE_NONINDEXED;
279                                 CHECK_EQUAL(io.out.file_attr, expected);
280                                 file_attributes_set |= io.out.file_attr;
281
282                                 status = smb2_util_close(tree, io.out.file.handle);
283                                 CHECK_STATUS(status, NT_STATUS_OK);
284                         } else {
285                                 unexpected_mask |= 1<<i;
286                                 torture_comment(tctx,
287                                     "file attribute 0x%08x returned %s\n",
288                                     1<<i, nt_errstr(status));
289                         }
290                 }
291         }
292
293         CHECK_EQUAL(ok_mask,                0x00003fb7);
294         CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
295         CHECK_EQUAL(unexpected_mask,        0x00000000);
296         CHECK_EQUAL(file_attributes_set,    0x00001127);
297
298         smb2_deltree(tree, FNAME);
299
300         /*
301          * Standalone servers doesn't support encryption
302          */
303         io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
304         status = smb2_create(tree, tctx, &io);
305         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
306                 torture_comment(tctx,
307                     "FILE_ATTRIBUTE_ENCRYPTED returned %s\n",
308                     nt_errstr(status));
309         } else {
310                 CHECK_STATUS(status, NT_STATUS_OK);
311                 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
312                 status = smb2_util_close(tree, io.out.file.handle);
313                 CHECK_STATUS(status, NT_STATUS_OK);
314         }
315
316         smb2_deltree(tree, FNAME);
317
318         ZERO_STRUCT(io);
319         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
320         io.in.file_attributes    = 0;
321         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
322         io.in.share_access = 
323                 NTCREATEX_SHARE_ACCESS_READ|
324                 NTCREATEX_SHARE_ACCESS_WRITE;
325         io.in.create_options = 0;
326         io.in.fname = FNAME ":stream1";
327         status = smb2_create(tree, tctx, &io);
328         CHECK_STATUS(status, NT_STATUS_OK);
329
330         status = smb2_util_close(tree, io.out.file.handle);
331         CHECK_STATUS(status, NT_STATUS_OK);
332
333         io.in.fname = FNAME;
334         io.in.file_attributes = 0x8040;
335         io.in.share_access = 
336                 NTCREATEX_SHARE_ACCESS_READ;
337         status = smb2_create(tree, tctx, &io);
338         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
339
340         io.in.fname = FNAME;
341         io.in.file_attributes = 0;
342         io.in.desired_access  = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
343         io.in.query_maximal_access = true;
344         status = smb2_create(tree, tctx, &io);
345         CHECK_STATUS(status, NT_STATUS_OK);
346         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
347
348         q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
349         q.access_information.in.file.handle = io.out.file.handle;
350         status = smb2_getinfo_file(tree, tctx, &q);
351         CHECK_STATUS(status, NT_STATUS_OK);
352         CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
353
354         io.in.file_attributes = 0;
355         io.in.desired_access  = 0;
356         io.in.query_maximal_access = false;
357         io.in.share_access = 0;
358         status = smb2_create(tree, tctx, &io);
359         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
360         
361         smb2_deltree(tree, FNAME);
362
363         return true;
364 }
365
366
367 /*
368   try the various request blobs
369  */
370 static bool test_create_blob(struct torture_context *tctx, struct smb2_tree *tree)
371 {
372         struct smb2_create io;
373         NTSTATUS status;
374
375         smb2_deltree(tree, FNAME);
376
377         ZERO_STRUCT(io);
378         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
379         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
380         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
381         io.in.share_access = 
382                 NTCREATEX_SHARE_ACCESS_DELETE|
383                 NTCREATEX_SHARE_ACCESS_READ|
384                 NTCREATEX_SHARE_ACCESS_WRITE;
385         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
386                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
387                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
388                                           0x00200000;
389         io.in.fname = FNAME;
390
391         status = smb2_create(tree, tctx, &io);
392         CHECK_STATUS(status, NT_STATUS_OK);
393
394         status = smb2_util_close(tree, io.out.file.handle);
395         CHECK_STATUS(status, NT_STATUS_OK);
396
397         torture_comment(tctx, "Testing alloc size\n");
398         /* FIXME We use 1M cause that's the rounded size of Samba.
399          * We should ask the server for the cluser size and calulate it
400          * correctly. */
401         io.in.alloc_size = 0x00100000;
402         status = smb2_create(tree, tctx, &io);
403         CHECK_STATUS(status, NT_STATUS_OK);
404         CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
405
406         status = smb2_util_close(tree, io.out.file.handle);
407         CHECK_STATUS(status, NT_STATUS_OK);
408
409         torture_comment(tctx, "Testing durable open\n");
410         io.in.durable_open = true;
411         status = smb2_create(tree, tctx, &io);
412         CHECK_STATUS(status, NT_STATUS_OK);
413
414         status = smb2_util_close(tree, io.out.file.handle);
415         CHECK_STATUS(status, NT_STATUS_OK);
416
417         torture_comment(tctx, "Testing query maximal access\n");
418         io.in.query_maximal_access = true;
419         status = smb2_create(tree, tctx, &io);
420         CHECK_STATUS(status, NT_STATUS_OK);
421         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
422
423         status = smb2_util_close(tree, io.out.file.handle);
424         CHECK_STATUS(status, NT_STATUS_OK);
425
426         torture_comment(tctx, "Testing timewarp\n");
427         io.in.timewarp = 10000;
428         status = smb2_create(tree, tctx, &io);
429         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
430         io.in.timewarp = 0;
431
432         torture_comment(tctx, "Testing query_on_disk\n");
433         io.in.query_on_disk_id = true;
434         status = smb2_create(tree, tctx, &io);
435         CHECK_STATUS(status, NT_STATUS_OK);
436
437         status = smb2_util_close(tree, io.out.file.handle);
438         CHECK_STATUS(status, NT_STATUS_OK);
439
440         torture_comment(tctx, "Testing unknown tag\n");
441         status = smb2_create_blob_add(tctx, &io.in.blobs,
442                                       "FooO", data_blob(NULL, 0));
443         CHECK_STATUS(status, NT_STATUS_OK);
444
445         status = smb2_create(tree, tctx, &io);
446         CHECK_STATUS(status, NT_STATUS_OK);
447
448         status = smb2_util_close(tree, io.out.file.handle);
449         CHECK_STATUS(status, NT_STATUS_OK);
450
451         torture_comment(tctx, "Testing bad tag length 0\n");
452         ZERO_STRUCT(io.in.blobs);
453         status = smb2_create_blob_add(tctx, &io.in.blobs,
454                                       "x", data_blob(NULL, 0));
455         CHECK_STATUS(status, NT_STATUS_OK);
456         status = smb2_create(tree, tctx, &io);
457         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
458
459         torture_comment(tctx, "Testing bad tag length 1\n");
460         ZERO_STRUCT(io.in.blobs);
461         status = smb2_create_blob_add(tctx, &io.in.blobs,
462                                       "x", data_blob(NULL, 0));
463         CHECK_STATUS(status, NT_STATUS_OK);
464         status = smb2_create(tree, tctx, &io);
465         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
466
467         torture_comment(tctx, "Testing bad tag length 2\n");
468         ZERO_STRUCT(io.in.blobs);
469         status = smb2_create_blob_add(tctx, &io.in.blobs,
470                                       "xx", data_blob(NULL, 0));
471         CHECK_STATUS(status, NT_STATUS_OK);
472         status = smb2_create(tree, tctx, &io);
473         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
474
475         torture_comment(tctx, "Testing bad tag length 3\n");
476         ZERO_STRUCT(io.in.blobs);
477         status = smb2_create_blob_add(tctx, &io.in.blobs,
478                                       "xxx", data_blob(NULL, 0));
479         CHECK_STATUS(status, NT_STATUS_OK);
480         status = smb2_create(tree, tctx, &io);
481         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
482
483         torture_comment(tctx, "Testing tag length 4\n");
484         ZERO_STRUCT(io.in.blobs);
485         status = smb2_create_blob_add(tctx, &io.in.blobs,
486                                       "xxxx", data_blob(NULL, 0));
487         CHECK_STATUS(status, NT_STATUS_OK);
488         status = smb2_create(tree, tctx, &io);
489         CHECK_STATUS(status, NT_STATUS_OK);
490
491         torture_comment(tctx, "Testing tag length 5\n");
492         ZERO_STRUCT(io.in.blobs);
493         status = smb2_create_blob_add(tctx, &io.in.blobs,
494                                       "xxxxx", data_blob(NULL, 0));
495         CHECK_STATUS(status, NT_STATUS_OK);
496         status = smb2_create(tree, tctx, &io);
497         CHECK_STATUS(status, NT_STATUS_OK);
498
499         torture_comment(tctx, "Testing tag length 6\n");
500         ZERO_STRUCT(io.in.blobs);
501         status = smb2_create_blob_add(tctx, &io.in.blobs,
502                                       "xxxxxx", data_blob(NULL, 0));
503         CHECK_STATUS(status, NT_STATUS_OK);
504         status = smb2_create(tree, tctx, &io);
505         CHECK_STATUS(status, NT_STATUS_OK);
506
507         torture_comment(tctx, "Testing tag length 7\n");
508         ZERO_STRUCT(io.in.blobs);
509         status = smb2_create_blob_add(tctx, &io.in.blobs,
510                                       "xxxxxxx", data_blob(NULL, 0));
511         CHECK_STATUS(status, NT_STATUS_OK);
512         status = smb2_create(tree, tctx, &io);
513         CHECK_STATUS(status, NT_STATUS_OK);
514
515         torture_comment(tctx, "Testing tag length 8\n");
516         ZERO_STRUCT(io.in.blobs);
517         status = smb2_create_blob_add(tctx, &io.in.blobs,
518                                       "xxxxxxxx", data_blob(NULL, 0));
519         CHECK_STATUS(status, NT_STATUS_OK);
520         status = smb2_create(tree, tctx, &io);
521         CHECK_STATUS(status, NT_STATUS_OK);
522
523         torture_comment(tctx, "Testing tag length 16\n");
524         ZERO_STRUCT(io.in.blobs);
525         status = smb2_create_blob_add(tctx, &io.in.blobs,
526                                       "xxxxxxxxxxxxxxxx", data_blob(NULL, 0));
527         CHECK_STATUS(status, NT_STATUS_OK);
528         status = smb2_create(tree, tctx, &io);
529         CHECK_STATUS(status, NT_STATUS_OK);
530
531         torture_comment(tctx, "Testing tag length 17\n");
532         ZERO_STRUCT(io.in.blobs);
533         status = smb2_create_blob_add(tctx, &io.in.blobs,
534                                       "xxxxxxxxxxxxxxxxx", data_blob(NULL, 0));
535         CHECK_STATUS(status, NT_STATUS_OK);
536         status = smb2_create(tree, tctx, &io);
537         CHECK_STATUS(status, NT_STATUS_OK);
538
539         torture_comment(tctx, "Testing tag length 34\n");
540         ZERO_STRUCT(io.in.blobs);
541         status = smb2_create_blob_add(tctx, &io.in.blobs,
542                                       "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
543                                       data_blob(NULL, 0));
544         CHECK_STATUS(status, NT_STATUS_OK);
545         status = smb2_create(tree, tctx, &io);
546         CHECK_STATUS(status, NT_STATUS_OK);
547
548         smb2_deltree(tree, FNAME);
549         
550         return true;
551 }
552
553 #define FAIL_UNLESS(__cond)                                     \
554         do {                                                    \
555                 if (__cond) {} else {                           \
556                         torture_result(tctx, TORTURE_FAIL, "%s) condition violated: %s\n",      \
557                                __location__, #__cond);          \
558                         ret = false; goto done;                 \
559                 }                                               \
560         } while(0)
561
562 /*
563   try creating with acls
564  */
565 static bool test_create_acl_ext(struct torture_context *tctx, struct smb2_tree *tree, bool test_dir)
566 {
567         bool ret = true;
568         struct smb2_create io;
569         NTSTATUS status;
570         struct security_ace ace;
571         struct security_descriptor *sd;
572         struct dom_sid *test_sid;
573         union smb_fileinfo q = {};
574         uint32_t attrib =
575             FILE_ATTRIBUTE_HIDDEN |
576             FILE_ATTRIBUTE_SYSTEM |
577             (test_dir ? FILE_ATTRIBUTE_DIRECTORY : 0);
578         NTSTATUS (*delete_func)(struct smb2_tree *, const char *) =
579             test_dir ? smb2_util_rmdir : smb2_util_unlink;
580
581         smb2_deltree(tree, FNAME);
582
583         ZERO_STRUCT(io);
584         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
585         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
586         io.in.create_disposition = NTCREATEX_DISP_CREATE;
587         io.in.share_access = 
588                 NTCREATEX_SHARE_ACCESS_DELETE |
589                 NTCREATEX_SHARE_ACCESS_READ |
590                 NTCREATEX_SHARE_ACCESS_WRITE;
591         io.in.create_options = NTCREATEX_OPTIONS_ASYNC_ALERT | 0x00200000 |
592             (test_dir ?  NTCREATEX_OPTIONS_DIRECTORY :
593                 (NTCREATEX_OPTIONS_NON_DIRECTORY_FILE));
594
595         io.in.fname = FNAME;
596
597         torture_comment(tctx, "basic create\n");
598
599         status = smb2_create(tree, tctx, &io);
600         CHECK_STATUS(status, NT_STATUS_OK);
601
602         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
603         q.query_secdesc.in.file.handle = io.out.file.handle;
604         q.query_secdesc.in.secinfo_flags = 
605                 SECINFO_OWNER |
606                 SECINFO_GROUP |
607                 SECINFO_DACL;
608         status = smb2_getinfo_file(tree, tctx, &q);
609         CHECK_STATUS(status, NT_STATUS_OK);
610         sd = q.query_secdesc.out.sd;
611
612         status = smb2_util_close(tree, io.out.file.handle);
613         CHECK_STATUS(status, NT_STATUS_OK);
614         status = delete_func(tree, FNAME);
615         CHECK_STATUS(status, NT_STATUS_OK);
616
617         torture_comment(tctx, "adding a new ACE\n");
618         test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS);
619
620         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
621         ace.flags = 0;
622         ace.access_mask = SEC_STD_ALL;
623         ace.trustee = *test_sid;
624
625         status = security_descriptor_dacl_add(sd, &ace);
626         CHECK_STATUS(status, NT_STATUS_OK);
627
628         torture_comment(tctx, "creating a file with an initial ACL\n");
629
630         io.in.sec_desc = sd;
631         status = smb2_create(tree, tctx, &io);
632         CHECK_STATUS(status, NT_STATUS_OK);
633
634         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
635
636         status = smb2_util_close(tree, io.out.file.handle);
637         CHECK_STATUS(status, NT_STATUS_OK);
638         status = delete_func(tree, FNAME);
639         CHECK_STATUS(status, NT_STATUS_OK);
640
641         torture_comment(tctx, "creating with attributes\n");
642
643         io.in.sec_desc = NULL;
644         io.in.file_attributes = attrib;
645         status = smb2_create(tree, tctx, &io);
646         CHECK_STATUS(status, NT_STATUS_OK);
647
648         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
649
650         status = smb2_util_close(tree, io.out.file.handle);
651         CHECK_STATUS(status, NT_STATUS_OK);
652         status = delete_func(tree, FNAME);
653         CHECK_STATUS(status, NT_STATUS_OK);
654
655         torture_comment(tctx, "creating with attributes and ACL\n");
656
657         io.in.sec_desc = sd;
658         io.in.file_attributes = attrib;
659         status = smb2_create(tree, tctx, &io);
660         CHECK_STATUS(status, NT_STATUS_OK);
661
662         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
663         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
664         
665         status = smb2_util_close(tree, io.out.file.handle);
666         CHECK_STATUS(status, NT_STATUS_OK);
667         status = delete_func(tree, FNAME);
668         CHECK_STATUS(status, NT_STATUS_OK);
669
670         torture_comment(tctx, "creating with attributes, ACL and owner\n");
671         sd = security_descriptor_dacl_create(tctx,
672                                         0, SID_WORLD, SID_BUILTIN_USERS,
673                                         SID_WORLD,
674                                         SEC_ACE_TYPE_ACCESS_ALLOWED,
675                                         SEC_RIGHTS_FILE_READ | SEC_STD_ALL,
676                                         0,
677                                         NULL);
678
679         io.in.sec_desc = sd;
680         io.in.file_attributes = attrib;
681         status = smb2_create(tree, tctx, &io);
682         CHECK_STATUS(status, NT_STATUS_OK);
683
684         FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, io.out.file.handle, sd));
685         FAIL_UNLESS(smb2_util_verify_attrib(tctx, tree, io.out.file.handle, attrib));
686
687  done:
688         status = smb2_util_close(tree, io.out.file.handle);
689         CHECK_STATUS(status, NT_STATUS_OK);
690         status = delete_func(tree, FNAME);
691         CHECK_STATUS(status, NT_STATUS_OK);
692
693         return ret;
694 }
695
696 /*
697   test SMB2 open
698 */
699 static bool test_smb2_open(struct torture_context *tctx,
700                            struct smb2_tree *tree)
701 {
702         union smb_open io;
703         union smb_fileinfo finfo;
704         const char *fname = DNAME "\\torture_ntcreatex.txt";
705         const char *dname = DNAME "\\torture_ntcreatex.dir";
706         NTSTATUS status;
707         struct smb2_handle h, h1;
708         bool ret = true;
709         int i;
710         struct {
711                 uint32_t create_disp;
712                 bool with_file;
713                 NTSTATUS correct_status;
714         } open_funcs[] = {
715                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_OK },
716                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_OK },
717                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
718                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
719                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
720                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
721                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
722                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
723                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_OK },
724                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
725                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_OK },
726                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_OK },
727                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
728                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
729         };
730
731         torture_comment(tctx, "Checking SMB2 Open\n");
732
733         smb2_util_unlink(tree, fname);
734         smb2_util_rmdir(tree, dname);
735
736         status = torture_smb2_testdir(tree, DNAME, &h);
737         CHECK_STATUS(status, NT_STATUS_OK);
738
739         ZERO_STRUCT(io.smb2);
740         /* reasonable default parameters */
741         io.generic.level = RAW_OPEN_SMB2;
742         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
743         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
744         io.smb2.in.alloc_size = 1024*1024;
745         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
746         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
747         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
748         io.smb2.in.create_options = 0;
749         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
750         io.smb2.in.security_flags = 0;
751         io.smb2.in.fname = fname;
752
753         /* test the create disposition */
754         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
755                 if (open_funcs[i].with_file) {
756                         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
757                         status= smb2_create(tree, tctx, &(io.smb2));
758                         if (!NT_STATUS_IS_OK(status)) {
759                                 torture_comment(tctx,
760                                     "Failed to create file %s status %s %d\n",
761                                     fname, nt_errstr(status), i);
762
763                                 ret = false;
764                                 goto done;
765                         }
766                         smb2_util_close(tree, io.smb2.out.file.handle);
767                 }
768                 io.smb2.in.create_disposition = open_funcs[i].create_disp;
769                 status = smb2_create(tree, tctx, &(io.smb2));
770                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
771                         torture_comment(tctx,
772                             "(%s) incorrect status %s should be %s (i=%d "
773                             "with_file=%d open_disp=%d)\n",
774                          __location__, nt_errstr(status),
775                         nt_errstr(open_funcs[i].correct_status),
776                         i, (int)open_funcs[i].with_file,
777                         (int)open_funcs[i].create_disp);
778
779                         ret = false;
780                         goto done;
781                 }
782                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
783                         smb2_util_close(tree, io.smb2.out.file.handle);
784                         smb2_util_unlink(tree, fname);
785                 }
786         }
787
788         /* basic field testing */
789         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
790
791         status = smb2_create(tree, tctx, &(io.smb2));
792         CHECK_STATUS(status, NT_STATUS_OK);
793         h1 = io.smb2.out.file.handle;
794
795         CHECK_VAL(io.smb2.out.oplock_level, 0);
796         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
797         CHECK_NTTIME(io.smb2.out.create_time, create_time);
798         CHECK_NTTIME(io.smb2.out.access_time, access_time);
799         CHECK_NTTIME(io.smb2.out.write_time, write_time);
800         CHECK_NTTIME(io.smb2.out.change_time, change_time);
801         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
802         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
803         CHECK_ALL_INFO(io.smb2.out.size, size);
804
805         /* check fields when the file already existed */
806         smb2_util_close(tree, h1);
807         smb2_util_unlink(tree, fname);
808
809         status = smb2_create_complex_file(tree, fname, &h1);
810         CHECK_STATUS(status, NT_STATUS_OK);
811
812         smb2_util_close(tree, h1);
813
814         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
815         status = smb2_create(tree, tctx, &(io.smb2));
816         CHECK_STATUS(status, NT_STATUS_OK);
817         h1 = io.smb2.out.file.handle;
818
819         CHECK_VAL(io.smb2.out.oplock_level, 0);
820         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_EXISTED);
821         CHECK_NTTIME(io.smb2.out.create_time, create_time);
822         CHECK_NTTIME(io.smb2.out.access_time, access_time);
823         CHECK_NTTIME(io.smb2.out.write_time, write_time);
824         CHECK_NTTIME(io.smb2.out.change_time, change_time);
825         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
826         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
827         CHECK_ALL_INFO(io.smb2.out.size, size);
828         smb2_util_close(tree, h1);
829         smb2_util_unlink(tree, fname);
830
831         /* create a directory */
832         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
833         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
834         io.smb2.in.alloc_size = 0;
835         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
836         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
837         io.smb2.in.create_options = 0;
838         io.smb2.in.fname = dname;
839         fname = dname;
840
841         smb2_util_rmdir(tree, fname);
842         smb2_util_unlink(tree, fname);
843
844         io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
845         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
846         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
847         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
848                                 NTCREATEX_SHARE_ACCESS_WRITE;
849         status = smb2_create(tree, tctx, &(io.smb2));
850         CHECK_STATUS(status, NT_STATUS_OK);
851         h1 = io.smb2.out.file.handle;
852
853         CHECK_VAL(io.smb2.out.oplock_level, 0);
854         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
855         CHECK_NTTIME(io.smb2.out.create_time, create_time);
856         CHECK_NTTIME(io.smb2.out.access_time, access_time);
857         CHECK_NTTIME(io.smb2.out.write_time, write_time);
858         CHECK_NTTIME(io.smb2.out.change_time, change_time);
859         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
860         CHECK_VAL(io.smb2.out.file_attr & ~FILE_ATTRIBUTE_NONINDEXED,
861                   FILE_ATTRIBUTE_DIRECTORY);
862         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
863         CHECK_ALL_INFO(io.smb2.out.size, size);
864         CHECK_VAL(io.smb2.out.size, 0);
865         CHECK_VAL(io.smb2.out.alloc_size, 0);
866         smb2_util_unlink(tree, fname);
867
868 done:
869         smb2_util_close(tree, h1);
870         smb2_util_unlink(tree, fname);
871         smb2_deltree(tree, DNAME);
872         return ret;
873 }
874
875 /*
876   test with an already opened and byte range locked file
877 */
878
879 static bool test_smb2_open_brlocked(struct torture_context *tctx,
880                                     struct smb2_tree *tree)
881 {
882         union smb_open io, io1;
883         union smb_lock io2;
884         struct smb2_lock_element lock[1];
885         const char *fname = DNAME "\\torture_ntcreatex.txt";
886         NTSTATUS status;
887         bool ret = true;
888         struct smb2_handle h;
889         char b = 42;
890
891         torture_comment(tctx,
892                 "Testing SMB2 open with a byte range locked file\n");
893
894         smb2_util_unlink(tree, fname);
895
896         status = torture_smb2_testdir(tree, DNAME, &h);
897         CHECK_STATUS(status, NT_STATUS_OK);
898
899         ZERO_STRUCT(io.smb2);
900         io.generic.level = RAW_OPEN_SMB2;
901         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
902         io.smb2.in.desired_access = 0x2019f;
903         io.smb2.in.alloc_size = 0;
904         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
905         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
906                 NTCREATEX_SHARE_ACCESS_WRITE;
907         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
908         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
909         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
910         io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
911         io.smb2.in.fname = fname;
912
913         status = smb2_create(tree, tctx, &(io.smb2));
914         CHECK_STATUS(status, NT_STATUS_OK);
915
916         status = smb2_util_write(tree, io.smb2.out.file.handle, &b, 0, 1);
917         CHECK_STATUS(status, NT_STATUS_OK);
918
919         ZERO_STRUCT(io2.smb2);
920         io2.smb2.level = RAW_LOCK_SMB2;
921         io2.smb2.in.file.handle = io.smb2.out.file.handle;
922         io2.smb2.in.lock_count = 1;
923
924         ZERO_STRUCT(lock);
925         lock[0].offset = 0;
926         lock[0].length = 1;
927         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
928                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
929         io2.smb2.in.locks = &lock[0];
930         status = smb2_lock(tree, &(io2.smb2));
931         CHECK_STATUS(status, NT_STATUS_OK);
932
933         ZERO_STRUCT(io1.smb2);
934         io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
935         io1.smb2.in.desired_access = 0x20196;
936         io1.smb2.in.alloc_size = 0;
937         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
938         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
939                 NTCREATEX_SHARE_ACCESS_WRITE;
940         io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
941         io1.smb2.in.create_options = 0;
942         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
943         io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
944         io1.smb2.in.fname = fname;
945
946         status = smb2_create(tree, tctx, &(io1.smb2));
947         CHECK_STATUS(status, NT_STATUS_OK);
948
949         smb2_util_close(tree, io.smb2.out.file.handle);
950         smb2_util_close(tree, io1.smb2.out.file.handle);
951         smb2_util_unlink(tree, fname);
952         smb2_deltree(tree, DNAME);
953
954         return ret;
955 }
956
957 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
958
959 static bool test_smb2_open_multi(struct torture_context *tctx,
960                                 struct smb2_tree *tree)
961 {
962         const char *fname = "test_oplock.dat";
963         NTSTATUS status;
964         bool ret = true;
965         union smb_open io;
966         struct smb2_tree **trees;
967         struct smb2_request **requests;
968         union smb_open *ios;
969         int i, num_files = 3;
970         int num_ok = 0;
971         int num_collision = 0;
972
973         torture_comment(tctx,
974                 "Testing SMB2 Open with multiple connections\n");
975         trees = talloc_array(tctx, struct smb2_tree *, num_files);
976         requests = talloc_array(tctx, struct smb2_request *, num_files);
977         ios = talloc_array(tctx, union smb_open, num_files);
978         if ((tctx->ev == NULL) || (trees == NULL) || (requests == NULL) ||
979             (ios == NULL)) {
980                 torture_comment(tctx, ("talloc failed\n"));
981                 ret = false;
982                 goto done;
983         }
984
985         tree->session->transport->options.request_timeout = 60;
986
987         for (i=0; i<num_files; i++) {
988                 if (!torture_smb2_connection(tctx, &(trees[i]))) {
989                         torture_comment(tctx,
990                                 "Could not open %d'th connection\n", i);
991                         ret = false;
992                         goto done;
993                 }
994                 trees[i]->session->transport->options.request_timeout = 60;
995         }
996
997         /* cleanup */
998         smb2_util_unlink(tree, fname);
999
1000         /*
1001           base ntcreatex parms
1002         */
1003         ZERO_STRUCT(io.smb2);
1004         io.generic.level = RAW_OPEN_SMB2;
1005         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1006         io.smb2.in.alloc_size = 0;
1007         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1008         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1009                 NTCREATEX_SHARE_ACCESS_WRITE|
1010                 NTCREATEX_SHARE_ACCESS_DELETE;
1011         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1012         io.smb2.in.create_options = 0;
1013         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1014         io.smb2.in.security_flags = 0;
1015         io.smb2.in.fname = fname;
1016         io.smb2.in.create_flags = 0;
1017
1018         for (i=0; i<num_files; i++) {
1019                 ios[i] = io;
1020                 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
1021                 if (requests[i] == NULL) {
1022                         torture_comment(tctx,
1023                                 "could not send %d'th request\n", i);
1024                         ret = false;
1025                         goto done;
1026                 }
1027         }
1028
1029         torture_comment(tctx, "waiting for replies\n");
1030         while (1) {
1031                 bool unreplied = false;
1032                 for (i=0; i<num_files; i++) {
1033                         if (requests[i] == NULL) {
1034                                 continue;
1035                         }
1036                         if (requests[i]->state < SMB2_REQUEST_DONE) {
1037                                 unreplied = true;
1038                                 break;
1039                         }
1040                         status = smb2_create_recv(requests[i], tctx,
1041                                                   &(ios[i].smb2));
1042
1043                         torture_comment(tctx,
1044                                 "File %d returned status %s\n", i,
1045                                 nt_errstr(status));
1046
1047                         if (NT_STATUS_IS_OK(status)) {
1048                                 num_ok += 1;
1049                         }
1050
1051                         if (NT_STATUS_EQUAL(status,
1052                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
1053                                 num_collision += 1;
1054                         }
1055
1056                         requests[i] = NULL;
1057                 }
1058                 if (!unreplied) {
1059                         break;
1060                 }
1061
1062                 if (tevent_loop_once(tctx->ev) != 0) {
1063                         torture_comment(tctx, "tevent_loop_once failed\n");
1064                         ret = false;
1065                         goto done;
1066                 }
1067         }
1068
1069         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1070                 ret = false;
1071         }
1072 done:
1073         smb2_deltree(tree, fname);
1074
1075         return ret;
1076 }
1077
1078 /*
1079   test opening for delete on a read-only attribute file.
1080 */
1081
1082 static bool test_smb2_open_for_delete(struct torture_context *tctx,
1083                                       struct smb2_tree *tree)
1084 {
1085         union smb_open io;
1086         union smb_fileinfo finfo;
1087         const char *fname = DNAME "\\torture_open_for_delete.txt";
1088         NTSTATUS status;
1089         struct smb2_handle h, h1;
1090         bool ret = true;
1091
1092         torture_comment(tctx,
1093                 "Checking SMB2_OPEN for delete on a readonly file.\n");
1094         smb2_util_unlink(tree, fname);
1095         smb2_deltree(tree, fname);
1096
1097         status = torture_smb2_testdir(tree, DNAME, &h);
1098         CHECK_STATUS(status, NT_STATUS_OK);
1099
1100         /* reasonable default parameters */
1101         ZERO_STRUCT(io.smb2);
1102         io.generic.level = RAW_OPEN_SMB2;
1103         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
1104         io.smb2.in.alloc_size = 0;
1105         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
1106         io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY;
1107         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1108         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1109         io.smb2.in.create_options = 0;
1110         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1111         io.smb2.in.security_flags = 0;
1112         io.smb2.in.fname = fname;
1113
1114         /* Create the readonly file. */
1115
1116         status = smb2_create(tree, tctx, &(io.smb2));
1117         CHECK_STATUS(status, NT_STATUS_OK);
1118         h1 = io.smb2.out.file.handle;
1119
1120         CHECK_VAL(io.smb2.out.oplock_level, 0);
1121         io.smb2.in.create_options = 0;
1122         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
1123         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
1124         smb2_util_close(tree, h1);
1125
1126         /* Now try and open for delete only - should succeed. */
1127         io.smb2.in.desired_access = SEC_STD_DELETE;
1128         io.smb2.in.file_attributes = 0;
1129         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1130                                 NTCREATEX_SHARE_ACCESS_WRITE |
1131                                 NTCREATEX_SHARE_ACCESS_DELETE;
1132         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
1133         status = smb2_create(tree, tctx, &(io.smb2));
1134         CHECK_STATUS(status, NT_STATUS_OK);
1135
1136         smb2_util_unlink(tree, fname);
1137
1138         smb2_util_close(tree, h1);
1139         smb2_util_unlink(tree, fname);
1140         smb2_deltree(tree, DNAME);
1141
1142         return ret;
1143 }
1144
1145 /*
1146   test SMB2 open with a leading slash on the path.
1147   Trying to create a directory with a leading slash
1148   should give NT_STATUS_INVALID_PARAMETER error
1149 */
1150 static bool test_smb2_leading_slash(struct torture_context *tctx,
1151                                     struct smb2_tree *tree)
1152 {
1153         union smb_open io;
1154         const char *dnameslash = "\\"DNAME;
1155         NTSTATUS status;
1156         bool ret = true;
1157
1158         torture_comment(tctx,
1159                 "Trying to create a directory with leading slash on path\n");
1160         smb2_deltree(tree, dnameslash);
1161
1162         ZERO_STRUCT(io.smb2);
1163         io.generic.level = RAW_OPEN_SMB2;
1164         io.smb2.in.oplock_level = 0;
1165         io.smb2.in.desired_access = SEC_RIGHTS_DIR_ALL;
1166         io.smb2.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
1167         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1168         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1169                                 NTCREATEX_SHARE_ACCESS_WRITE |
1170                                 NTCREATEX_SHARE_ACCESS_DELETE;
1171         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1172         io.smb2.in.fname = dnameslash;
1173
1174         status = smb2_create(tree, tree, &(io.smb2));
1175         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1176
1177         smb2_deltree(tree, dnameslash);
1178         return ret;
1179 }
1180
1181
1182 static bool test_create_acl_file(struct torture_context *tctx,
1183     struct smb2_tree *tree)
1184 {
1185         torture_comment(tctx, "Testing nttrans create with sec_desc on files\n");
1186
1187         return test_create_acl_ext(tctx, tree, false);
1188 }
1189
1190 static bool test_create_acl_dir(struct torture_context *tctx,
1191     struct smb2_tree *tree)
1192 {
1193         torture_comment(tctx, "Testing nttrans create with sec_desc on directories\n");
1194
1195         return test_create_acl_ext(tctx, tree, true);
1196 }
1197
1198 #define CHECK_ACCESS_FLAGS(_fh, flags) do { \
1199         union smb_fileinfo _q; \
1200         _q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION; \
1201         _q.access_information.in.file.handle = (_fh); \
1202         status = smb2_getinfo_file(tree, tctx, &_q); \
1203         CHECK_STATUS(status, NT_STATUS_OK); \
1204         if (_q.access_information.out.access_flags != (flags)) { \
1205                 torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect access_flags 0x%08x - should be 0x%08x\n", \
1206                        __location__, _q.access_information.out.access_flags, (flags)); \
1207                 ret = false; \
1208                 goto done; \
1209         } \
1210 } while (0)
1211
1212 /*
1213  * Test creating a file with a NULL DACL.
1214  */
1215 static bool test_create_null_dacl(struct torture_context *tctx,
1216     struct smb2_tree *tree)
1217 {
1218         NTSTATUS status;
1219         struct smb2_create io;
1220         const char *fname = "nulldacl.txt";
1221         bool ret = true;
1222         struct smb2_handle handle;
1223         union smb_fileinfo q;
1224         union smb_setfileinfo s;
1225         struct security_descriptor *sd = security_descriptor_initialise(tctx);
1226         struct security_acl dacl;
1227
1228         torture_comment(tctx, "TESTING SEC_DESC WITH A NULL DACL\n");
1229
1230         smb2_util_unlink(tree, fname);
1231
1232         ZERO_STRUCT(io);
1233         io.level = RAW_OPEN_SMB2;
1234         io.in.create_flags = 0;
1235         io.in.desired_access = SEC_STD_READ_CONTROL | SEC_STD_WRITE_DAC
1236                 | SEC_STD_WRITE_OWNER;
1237         io.in.create_options = 0;
1238         io.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1239         io.in.share_access =
1240                 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1241         io.in.alloc_size = 0;
1242         io.in.create_disposition = NTCREATEX_DISP_CREATE;
1243         io.in.impersonation_level = NTCREATEX_IMPERSONATION_ANONYMOUS;
1244         io.in.security_flags = 0;
1245         io.in.fname = fname;
1246         io.in.sec_desc = sd;
1247         /* XXX create_options ? */
1248         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
1249                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
1250                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
1251                                           0x00200000;
1252
1253         torture_comment(tctx, "creating a file with a empty sd\n");
1254         status = smb2_create(tree, tctx, &io);
1255         CHECK_STATUS(status, NT_STATUS_OK);
1256         handle = io.out.file.handle;
1257
1258         torture_comment(tctx, "get the original sd\n");
1259         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1260         q.query_secdesc.in.file.handle = handle;
1261         q.query_secdesc.in.secinfo_flags =
1262                 SECINFO_OWNER |
1263                 SECINFO_GROUP |
1264                 SECINFO_DACL;
1265         status = smb2_getinfo_file(tree, tctx, &q);
1266         CHECK_STATUS(status, NT_STATUS_OK);
1267
1268         /*
1269          * Testing the created DACL,
1270          * the server should add the inherited DACL
1271          * when SEC_DESC_DACL_PRESENT isn't specified
1272          */
1273         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
1274                 ret = false;
1275                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
1276         }
1277         if (q.query_secdesc.out.sd->dacl == NULL) {
1278                 ret = false;
1279                 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
1280         }
1281
1282         torture_comment(tctx, "set NULL DACL\n");
1283         sd->type |= SEC_DESC_DACL_PRESENT;
1284
1285         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1286         s.set_secdesc.in.file.handle = handle;
1287         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1288         s.set_secdesc.in.sd = sd;
1289         status = smb2_setinfo_file(tree, &s);
1290         CHECK_STATUS(status, NT_STATUS_OK);
1291
1292         torture_comment(tctx, "get the sd\n");
1293         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1294         q.query_secdesc.in.file.handle = handle;
1295         q.query_secdesc.in.secinfo_flags =
1296                 SECINFO_OWNER |
1297                 SECINFO_GROUP |
1298                 SECINFO_DACL;
1299         status = smb2_getinfo_file(tree, tctx, &q);
1300         CHECK_STATUS(status, NT_STATUS_OK);
1301
1302         /* Testing the modified DACL */
1303         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
1304                 ret = false;
1305                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
1306         }
1307         if (q.query_secdesc.out.sd->dacl != NULL) {
1308                 ret = false;
1309                 torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
1310         }
1311
1312         io.in.create_disposition = NTCREATEX_DISP_OPEN;
1313
1314         torture_comment(tctx, "try open for read control\n");
1315         io.in.desired_access = SEC_STD_READ_CONTROL;
1316         status = smb2_create(tree, tctx, &io);
1317         CHECK_STATUS(status, NT_STATUS_OK);
1318         CHECK_ACCESS_FLAGS(io.out.file.handle,
1319                 SEC_STD_READ_CONTROL);
1320         smb2_util_close(tree, io.out.file.handle);
1321
1322         torture_comment(tctx, "try open for write\n");
1323         io.in.desired_access = SEC_FILE_WRITE_DATA;
1324         status = smb2_create(tree, tctx, &io);
1325         CHECK_STATUS(status, NT_STATUS_OK);
1326         CHECK_ACCESS_FLAGS(io.out.file.handle,
1327                 SEC_FILE_WRITE_DATA);
1328         smb2_util_close(tree, io.out.file.handle);
1329
1330         torture_comment(tctx, "try open for read\n");
1331         io.in.desired_access = SEC_FILE_READ_DATA;
1332         status = smb2_create(tree, tctx, &io);
1333         CHECK_STATUS(status, NT_STATUS_OK);
1334         CHECK_ACCESS_FLAGS(io.out.file.handle,
1335                 SEC_FILE_READ_DATA);
1336         smb2_util_close(tree, io.out.file.handle);
1337
1338         torture_comment(tctx, "try open for generic write\n");
1339         io.in.desired_access = SEC_GENERIC_WRITE;
1340         status = smb2_create(tree, tctx, &io);
1341         CHECK_STATUS(status, NT_STATUS_OK);
1342         CHECK_ACCESS_FLAGS(io.out.file.handle,
1343                 SEC_RIGHTS_FILE_WRITE);
1344         smb2_util_close(tree, io.out.file.handle);
1345
1346         torture_comment(tctx, "try open for generic read\n");
1347         io.in.desired_access = SEC_GENERIC_READ;
1348         status = smb2_create(tree, tctx, &io);
1349         CHECK_STATUS(status, NT_STATUS_OK);
1350         CHECK_ACCESS_FLAGS(io.out.file.handle,
1351                 SEC_RIGHTS_FILE_READ);
1352         smb2_util_close(tree, io.out.file.handle);
1353
1354         torture_comment(tctx, "set DACL with 0 aces\n");
1355         ZERO_STRUCT(dacl);
1356         dacl.revision = SECURITY_ACL_REVISION_NT4;
1357         dacl.num_aces = 0;
1358         sd->dacl = &dacl;
1359
1360         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1361         s.set_secdesc.in.file.handle = handle;
1362         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1363         s.set_secdesc.in.sd = sd;
1364         status = smb2_setinfo_file(tree, &s);
1365         CHECK_STATUS(status, NT_STATUS_OK);
1366
1367         torture_comment(tctx, "get the sd\n");
1368         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1369         q.query_secdesc.in.file.handle = handle;
1370         q.query_secdesc.in.secinfo_flags =
1371                 SECINFO_OWNER |
1372                 SECINFO_GROUP |
1373                 SECINFO_DACL;
1374         status = smb2_getinfo_file(tree, tctx, &q);
1375         CHECK_STATUS(status, NT_STATUS_OK);
1376
1377         /* Testing the modified DACL */
1378         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
1379                 ret = false;
1380                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
1381         }
1382         if (q.query_secdesc.out.sd->dacl == NULL) {
1383                 ret = false;
1384                 torture_fail_goto(tctx, done, "no DACL has been created on the server!\n");
1385         }
1386         if (q.query_secdesc.out.sd->dacl->num_aces != 0) {
1387                 torture_result(tctx, TORTURE_FAIL, "DACL has %u aces!\n",
1388                        q.query_secdesc.out.sd->dacl->num_aces);
1389                 ret = false;
1390                 goto done;
1391         }
1392
1393         torture_comment(tctx, "try open for read control\n");
1394         io.in.desired_access = SEC_STD_READ_CONTROL;
1395         status = smb2_create(tree, tctx, &io);
1396         CHECK_STATUS(status, NT_STATUS_OK);
1397         CHECK_ACCESS_FLAGS(io.out.file.handle,
1398                 SEC_STD_READ_CONTROL);
1399         smb2_util_close(tree, io.out.file.handle);
1400
1401         torture_comment(tctx, "try open for write => access_denied\n");
1402         io.in.desired_access = SEC_FILE_WRITE_DATA;
1403         status = smb2_create(tree, tctx, &io);
1404         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1405                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1406         } else {
1407                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1408         }
1409
1410         torture_comment(tctx, "try open for read => access_denied\n");
1411         io.in.desired_access = SEC_FILE_READ_DATA;
1412         status = smb2_create(tree, tctx, &io);
1413         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1414                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1415         } else {
1416                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1417         }
1418
1419         torture_comment(tctx, "try open for generic write => access_denied\n");
1420         io.in.desired_access = SEC_GENERIC_WRITE;
1421         status = smb2_create(tree, tctx, &io);
1422         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1423                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1424         } else {
1425                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1426         }
1427
1428         torture_comment(tctx, "try open for generic read => access_denied\n");
1429         io.in.desired_access = SEC_GENERIC_READ;
1430         status = smb2_create(tree, tctx, &io);
1431         if (torture_setting_bool(tctx, "hide_on_access_denied", false)) {
1432                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1433         } else {
1434                 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1435         }
1436
1437         torture_comment(tctx, "set empty sd\n");
1438         sd->type &= ~SEC_DESC_DACL_PRESENT;
1439         sd->dacl = NULL;
1440
1441         s.set_secdesc.level = RAW_SFILEINFO_SEC_DESC;
1442         s.set_secdesc.in.file.handle = handle;
1443         s.set_secdesc.in.secinfo_flags = SECINFO_DACL;
1444         s.set_secdesc.in.sd = sd;
1445         status = smb2_setinfo_file(tree, &s);
1446         CHECK_STATUS(status, NT_STATUS_OK);
1447
1448         torture_comment(tctx, "get the sd\n");
1449         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
1450         q.query_secdesc.in.file.handle = handle;
1451         q.query_secdesc.in.secinfo_flags =
1452                 SECINFO_OWNER |
1453                 SECINFO_GROUP |
1454                 SECINFO_DACL;
1455         status = smb2_getinfo_file(tree, tctx, &q);
1456         CHECK_STATUS(status, NT_STATUS_OK);
1457
1458         /* Testing the modified DACL */
1459         if (!(q.query_secdesc.out.sd->type & SEC_DESC_DACL_PRESENT)) {
1460                 ret = false;
1461                 torture_fail_goto(tctx, done, "DACL_PRESENT flag not set by the server!\n");
1462         }
1463         if (q.query_secdesc.out.sd->dacl != NULL) {
1464                 ret = false;
1465                 torture_fail_goto(tctx, done, "DACL has been created on the server!\n");
1466         }
1467 done:
1468         smb2_util_close(tree, handle);
1469         smb2_util_unlink(tree, fname);
1470         smb2_tdis(tree);
1471         smb2_logoff(tree->session);
1472         return ret;
1473 }
1474
1475 /*
1476    basic testing of SMB2 read
1477 */
1478 struct torture_suite *torture_smb2_create_init(void)
1479 {
1480         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "create");
1481
1482         torture_suite_add_1smb2_test(suite, "gentest", test_create_gentest);
1483         torture_suite_add_1smb2_test(suite, "blob", test_create_blob);
1484         torture_suite_add_1smb2_test(suite, "open", test_smb2_open);
1485         torture_suite_add_1smb2_test(suite, "brlocked", test_smb2_open_brlocked);
1486         torture_suite_add_1smb2_test(suite, "multi", test_smb2_open_multi);
1487         torture_suite_add_1smb2_test(suite, "delete", test_smb2_open_for_delete);
1488         torture_suite_add_1smb2_test(suite, "leading-slash", test_smb2_leading_slash);
1489         torture_suite_add_1smb2_test(suite, "aclfile", test_create_acl_file);
1490         torture_suite_add_1smb2_test(suite, "acldir", test_create_acl_dir);
1491         torture_suite_add_1smb2_test(suite, "nulldacl", test_create_null_dacl);
1492
1493         suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
1494
1495         return suite;
1496 }