smb2-torture: samba4 allows SEC_FLAG_SECURITY to be used with privileges
[ira/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(torture, 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(torture, 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, torture, &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(torture, TORTURE_FAIL, \
69                         "(%s) wrong time for field %s  %s - %s\n", \
70                         __location__, #field, \
71                         timestring(torture, t1), \
72                         timestring(torture, t2)); \
73                 dump_all_info(torture, &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, torture, &finfo); \
82         CHECK_STATUS(status, NT_STATUS_OK); \
83         t2 = finfo.all_info.out.field; \
84         if (t != t2) { \
85                 torture_result(torture, TORTURE_FAIL, \
86                         "(%s) wrong time for field %s  %s - %s\n", \
87                        __location__, #field, \
88                        nt_time_string(torture, t), \
89                        nt_time_string(torture, t2)); \
90                 dump_all_info(torture, &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, torture, &finfo); \
98         CHECK_STATUS(status, NT_STATUS_OK); \
99         if ((v) != (finfo.all_info.out.field)) { \
100                torture_result(torture, 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(torture, &finfo); \
105                 ret = false; \
106         }} while (0)
107
108 #define CHECK_VAL(v, correct) do { \
109         if ((v) != (correct)) { \
110                 torture_result(torture, 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(torture, \
125                     "(%s) Failed to set attrib 0x%x on %s\n", \
126                        __location__, sattrib, fname); \
127         }} while (0)
128
129 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
130
131 /*
132   test some interesting combinations found by gentest
133  */
134 static bool test_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
135 {
136         struct smb2_create io;
137         NTSTATUS status;
138         TALLOC_CTX *tmp_ctx = talloc_new(tree);
139         uint32_t access_mask, file_attributes_set;
140         uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
141         uint32_t not_a_directory_mask, unexpected_mask;
142         union smb_fileinfo q;
143
144         ZERO_STRUCT(io);
145         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
146         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
147         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
148         io.in.share_access = 
149                 NTCREATEX_SHARE_ACCESS_DELETE|
150                 NTCREATEX_SHARE_ACCESS_READ|
151                 NTCREATEX_SHARE_ACCESS_WRITE;
152         io.in.create_options = 0;
153         io.in.fname = FNAME;
154
155         status = smb2_create(tree, tmp_ctx, &io);
156         CHECK_STATUS(status, NT_STATUS_OK);
157
158         status = smb2_util_close(tree, io.out.file.handle);
159         CHECK_STATUS(status, NT_STATUS_OK);
160
161         io.in.create_options = 0xF0000000;
162         status = smb2_create(tree, tmp_ctx, &io);
163         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
164
165         io.in.create_options = 0;
166
167         io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
168         status = smb2_create(tree, tmp_ctx, &io);
169         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
170
171         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
172         status = smb2_create(tree, tmp_ctx, &io);
173         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
174
175         io.in.create_disposition = NTCREATEX_DISP_OPEN;
176         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
177         status = smb2_create(tree, tmp_ctx, &io);
178         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
179         
180         io.in.create_disposition = NTCREATEX_DISP_CREATE;
181         io.in.desired_access = 0x08000000;
182         status = smb2_create(tree, tmp_ctx, &io);
183         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
184
185         io.in.desired_access = 0x04000000;
186         status = smb2_create(tree, tmp_ctx, &io);
187         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
188
189         io.in.file_attributes = 0;
190         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
191         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
192         ok_mask = 0;
193         not_supported_mask = 0;
194         invalid_parameter_mask = 0;
195         not_a_directory_mask = 0;
196         unexpected_mask = 0;
197         {
198                 int i;
199                 for (i=0;i<32;i++) {
200                         io.in.create_options = 1<<i;
201                         if (io.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
202                                 continue;
203                         }
204                         status = smb2_create(tree, tmp_ctx, &io);
205                         if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
206                                 not_supported_mask |= 1<<i;
207                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
208                                 invalid_parameter_mask |= 1<<i;
209                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
210                                 not_a_directory_mask |= 1<<i;
211                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
212                                 ok_mask |= 1<<i;
213                                 status = smb2_util_close(tree, io.out.file.handle);
214                                 CHECK_STATUS(status, NT_STATUS_OK);
215                         } else {
216                                 unexpected_mask |= 1<<i;
217                                 torture_comment(torture,
218                                     "create option 0x%08x returned %s\n",
219                                     1<<i, nt_errstr(status));
220                         }
221                 }
222         }
223         io.in.create_options = 0;
224
225         CHECK_EQUAL(ok_mask,                0x00efcf7e);
226         CHECK_EQUAL(not_a_directory_mask,   0x00000001);
227         CHECK_EQUAL(not_supported_mask,     0x00102080);
228         CHECK_EQUAL(invalid_parameter_mask, 0xff000000);
229         CHECK_EQUAL(unexpected_mask,        0x00000000);
230
231         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
232         io.in.file_attributes = 0;
233         access_mask = 0;
234         {
235                 int i;
236                 for (i=0;i<32;i++) {
237                         io.in.desired_access = 1<<i;
238                         status = smb2_create(tree, tmp_ctx, &io);
239                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
240                             NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
241                                 access_mask |= io.in.desired_access;
242                         } else {
243                                 CHECK_STATUS(status, NT_STATUS_OK);
244                                 status = smb2_util_close(tree, io.out.file.handle);
245                                 CHECK_STATUS(status, NT_STATUS_OK);
246                         }
247                 }
248         }
249
250         if (TARGET_IS_WIN7(torture)) {
251                 CHECK_EQUAL(access_mask, 0x0de0fe00);
252         } else if (torture_setting_bool(torture, "samba4", false)) {
253                 CHECK_EQUAL(access_mask, 0x0cf0fe00);
254         } else {
255                 CHECK_EQUAL(access_mask, 0x0df0fe00);
256         }
257
258         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
259         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
260         io.in.file_attributes = 0;
261         ok_mask = 0;
262         invalid_parameter_mask = 0;
263         unexpected_mask = 0;
264         file_attributes_set = 0;
265         {
266                 int i;
267                 for (i=0;i<32;i++) {
268                         io.in.file_attributes = 1<<i;
269                         if (io.in.file_attributes & FILE_ATTRIBUTE_ENCRYPTED) {
270                                 continue;
271                         }
272                         smb2_deltree(tree, FNAME);
273                         status = smb2_create(tree, tmp_ctx, &io);
274                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
275                                 invalid_parameter_mask |= 1<<i;
276                         } else if (NT_STATUS_IS_OK(status)) {
277                                 uint32_t expected;
278                                 ok_mask |= 1<<i;
279
280                                 expected = (io.in.file_attributes | FILE_ATTRIBUTE_ARCHIVE) & 0x00005127;
281                                 CHECK_EQUAL(io.out.file_attr, expected);
282                                 file_attributes_set |= io.out.file_attr;
283
284                                 status = smb2_util_close(tree, io.out.file.handle);
285                                 CHECK_STATUS(status, NT_STATUS_OK);
286                         } else {
287                                 unexpected_mask |= 1<<i;
288                                 torture_comment(torture,
289                                     "file attribute 0x%08x returned %s\n",
290                                     1<<i, nt_errstr(status));
291                         }
292                 }
293         }
294
295         CHECK_EQUAL(ok_mask,                0x00003fb7);
296         CHECK_EQUAL(invalid_parameter_mask, 0xffff8048);
297         CHECK_EQUAL(unexpected_mask,        0x00000000);
298         CHECK_EQUAL(file_attributes_set,    0x00001127);
299
300         smb2_deltree(tree, FNAME);
301
302         /*
303          * Standalone servers doesn't support encryption
304          */
305         io.in.file_attributes = FILE_ATTRIBUTE_ENCRYPTED;
306         status = smb2_create(tree, tmp_ctx, &io);
307         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
308                 torture_comment(torture,
309                     "FILE_ATTRIBUTE_ENCRYPTED returned %s\n",
310                     nt_errstr(status));
311         } else {
312                 CHECK_STATUS(status, NT_STATUS_OK);
313                 CHECK_EQUAL(io.out.file_attr, (FILE_ATTRIBUTE_ENCRYPTED | FILE_ATTRIBUTE_ARCHIVE));
314                 status = smb2_util_close(tree, io.out.file.handle);
315                 CHECK_STATUS(status, NT_STATUS_OK);
316         }
317
318         smb2_deltree(tree, FNAME);
319
320         ZERO_STRUCT(io);
321         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
322         io.in.file_attributes    = 0;
323         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
324         io.in.share_access = 
325                 NTCREATEX_SHARE_ACCESS_READ|
326                 NTCREATEX_SHARE_ACCESS_WRITE;
327         io.in.create_options = 0;
328         io.in.fname = FNAME ":stream1";
329         status = smb2_create(tree, tmp_ctx, &io);
330         CHECK_STATUS(status, NT_STATUS_OK);
331
332         status = smb2_util_close(tree, io.out.file.handle);
333         CHECK_STATUS(status, NT_STATUS_OK);
334
335         io.in.fname = FNAME;
336         io.in.file_attributes = 0x8040;
337         io.in.share_access = 
338                 NTCREATEX_SHARE_ACCESS_READ;
339         status = smb2_create(tree, tmp_ctx, &io);
340         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
341
342         io.in.fname = FNAME;
343         io.in.file_attributes = 0;
344         io.in.desired_access  = SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA;
345         io.in.query_maximal_access = true;
346         status = smb2_create(tree, tmp_ctx, &io);
347         CHECK_STATUS(status, NT_STATUS_OK);
348         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
349
350         q.access_information.level = RAW_FILEINFO_ACCESS_INFORMATION;
351         q.access_information.in.file.handle = io.out.file.handle;
352         status = smb2_getinfo_file(tree, tmp_ctx, &q);
353         CHECK_STATUS(status, NT_STATUS_OK);
354         CHECK_EQUAL(q.access_information.out.access_flags, io.in.desired_access);
355
356         io.in.file_attributes = 0;
357         io.in.desired_access  = 0;
358         io.in.query_maximal_access = false;
359         io.in.share_access = 0;
360         status = smb2_create(tree, tmp_ctx, &io);
361         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
362         
363         talloc_free(tmp_ctx);
364
365         smb2_deltree(tree, FNAME);
366         
367         return true;
368 }
369
370
371 /*
372   try the various request blobs
373  */
374 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
375 {
376         struct smb2_create io;
377         NTSTATUS status;
378         TALLOC_CTX *tmp_ctx = talloc_new(tree);
379
380         smb2_deltree(tree, FNAME);
381
382         ZERO_STRUCT(io);
383         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
384         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
385         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
386         io.in.share_access = 
387                 NTCREATEX_SHARE_ACCESS_DELETE|
388                 NTCREATEX_SHARE_ACCESS_READ|
389                 NTCREATEX_SHARE_ACCESS_WRITE;
390         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
391                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
392                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
393                                           0x00200000;
394         io.in.fname = FNAME;
395
396         status = smb2_create(tree, tmp_ctx, &io);
397         CHECK_STATUS(status, NT_STATUS_OK);
398
399         status = smb2_util_close(tree, io.out.file.handle);
400         CHECK_STATUS(status, NT_STATUS_OK);
401
402         torture_comment(torture, "testing alloc size\n");
403         io.in.alloc_size = 4096;
404         status = smb2_create(tree, tmp_ctx, &io);
405         CHECK_STATUS(status, NT_STATUS_OK);
406         CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
407
408         status = smb2_util_close(tree, io.out.file.handle);
409         CHECK_STATUS(status, NT_STATUS_OK);
410
411         torture_comment(torture, "testing durable open\n");
412         io.in.durable_open = true;
413         status = smb2_create(tree, tmp_ctx, &io);
414         CHECK_STATUS(status, NT_STATUS_OK);
415
416         status = smb2_util_close(tree, io.out.file.handle);
417         CHECK_STATUS(status, NT_STATUS_OK);
418
419         torture_comment(torture, "testing query maximal access\n");
420         io.in.query_maximal_access = true;
421         status = smb2_create(tree, tmp_ctx, &io);
422         CHECK_STATUS(status, NT_STATUS_OK);
423         CHECK_EQUAL(io.out.maximal_access, 0x001f01ff);
424
425         status = smb2_util_close(tree, io.out.file.handle);
426         CHECK_STATUS(status, NT_STATUS_OK);
427
428         torture_comment(torture, "testing timewarp\n");
429         io.in.timewarp = 10000;
430         status = smb2_create(tree, tmp_ctx, &io);
431         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
432         io.in.timewarp = 0;
433
434         torture_comment(torture, "testing query_on_disk\n");
435         io.in.query_on_disk_id = true;
436         status = smb2_create(tree, tmp_ctx, &io);
437         CHECK_STATUS(status, NT_STATUS_OK);
438
439         status = smb2_util_close(tree, io.out.file.handle);
440         CHECK_STATUS(status, NT_STATUS_OK);
441
442         torture_comment(torture, "testing unknown tag\n");
443         status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
444                                       "FooO", data_blob(NULL, 0));
445         CHECK_STATUS(status, NT_STATUS_OK);
446
447         status = smb2_create(tree, tmp_ctx, &io);
448         CHECK_STATUS(status, NT_STATUS_OK);
449
450         status = smb2_util_close(tree, io.out.file.handle);
451         CHECK_STATUS(status, NT_STATUS_OK);
452
453         torture_comment(torture, "testing bad tag length\n");
454         status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
455                                       "xxx", data_blob(NULL, 0));
456         CHECK_STATUS(status, NT_STATUS_OK);
457
458         status = smb2_create(tree, tmp_ctx, &io);
459         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
460
461         talloc_free(tmp_ctx);
462
463         smb2_deltree(tree, FNAME);
464         
465         return true;
466 }
467
468 /*
469   try creating with acls
470  */
471 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
472 {
473         struct smb2_create io;
474         NTSTATUS status;
475         TALLOC_CTX *tmp_ctx = talloc_new(tree);
476         struct security_ace ace;
477         struct security_descriptor *sd, *sd2;
478         struct dom_sid *test_sid;
479         union smb_fileinfo q;
480
481         smb2_deltree(tree, FNAME);
482
483         ZERO_STRUCT(io);
484         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
485         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
486         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
487         io.in.share_access = 
488                 NTCREATEX_SHARE_ACCESS_DELETE|
489                 NTCREATEX_SHARE_ACCESS_READ|
490                 NTCREATEX_SHARE_ACCESS_WRITE;
491         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
492                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
493                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
494                                           0x00200000;
495         io.in.fname = FNAME;
496
497         status = smb2_create(tree, tmp_ctx, &io);
498         CHECK_STATUS(status, NT_STATUS_OK);
499
500         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
501         q.query_secdesc.in.file.handle = io.out.file.handle;
502         q.query_secdesc.in.secinfo_flags = 
503                 SECINFO_OWNER |
504                 SECINFO_GROUP |
505                 SECINFO_DACL;
506         status = smb2_getinfo_file(tree, tmp_ctx, &q);
507         CHECK_STATUS(status, NT_STATUS_OK);
508         sd = q.query_secdesc.out.sd;
509
510         status = smb2_util_close(tree, io.out.file.handle);
511         CHECK_STATUS(status, NT_STATUS_OK);
512
513         smb2_util_unlink(tree, FNAME);
514
515         torture_comment(torture, "adding a new ACE\n");
516         test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
517
518         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
519         ace.flags = 0;
520         ace.access_mask = SEC_STD_ALL;
521         ace.trustee = *test_sid;
522
523         status = security_descriptor_dacl_add(sd, &ace);
524         CHECK_STATUS(status, NT_STATUS_OK);
525
526         torture_comment(torture, "creating a file with an initial ACL\n");
527
528         io.in.sec_desc = sd;
529         status = smb2_create(tree, tmp_ctx, &io);
530         CHECK_STATUS(status, NT_STATUS_OK);
531
532         q.query_secdesc.in.file.handle = io.out.file.handle;
533         status = smb2_getinfo_file(tree, tmp_ctx, &q);
534         CHECK_STATUS(status, NT_STATUS_OK);
535         sd2 = q.query_secdesc.out.sd;
536
537         if (!security_acl_equal(sd->dacl, sd2->dacl)) {
538                 torture_comment(torture,
539                     "%s: security descriptors don't match!\n", __location__);
540                 torture_comment(torture, "got:\n");
541                 NDR_PRINT_DEBUG(security_descriptor, sd2);
542                 torture_comment(torture, "expected:\n");
543                 NDR_PRINT_DEBUG(security_descriptor, sd);
544                 return false;
545         }
546
547         talloc_free(tmp_ctx);
548         
549         return true;
550 }
551
552 /*
553   test SMB2 open
554 */
555 static bool test_smb2_open(struct torture_context *torture,
556                            struct smb2_tree *tree)
557 {
558         TALLOC_CTX *mem_ctx = talloc_new(torture);
559         union smb_open io;
560         union smb_fileinfo finfo;
561         const char *fname = DNAME "\\torture_ntcreatex.txt";
562         const char *dname = DNAME "\\torture_ntcreatex.dir";
563         NTSTATUS status;
564         struct smb2_handle h, h1;
565         bool ret = true;
566         int i;
567         struct {
568                 uint32_t create_disp;
569                 bool with_file;
570                 NTSTATUS correct_status;
571         } open_funcs[] = {
572                 { NTCREATEX_DISP_SUPERSEDE,     true,  NT_STATUS_OK },
573                 { NTCREATEX_DISP_SUPERSEDE,     false, NT_STATUS_OK },
574                 { NTCREATEX_DISP_OPEN,          true,  NT_STATUS_OK },
575                 { NTCREATEX_DISP_OPEN,          false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
576                 { NTCREATEX_DISP_CREATE,        true,  NT_STATUS_OBJECT_NAME_COLLISION },
577                 { NTCREATEX_DISP_CREATE,        false, NT_STATUS_OK },
578                 { NTCREATEX_DISP_OPEN_IF,       true,  NT_STATUS_OK },
579                 { NTCREATEX_DISP_OPEN_IF,       false, NT_STATUS_OK },
580                 { NTCREATEX_DISP_OVERWRITE,     true,  NT_STATUS_OK },
581                 { NTCREATEX_DISP_OVERWRITE,     false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
582                 { NTCREATEX_DISP_OVERWRITE_IF,  true,  NT_STATUS_OK },
583                 { NTCREATEX_DISP_OVERWRITE_IF,  false, NT_STATUS_OK },
584                 { 6,                            true,  NT_STATUS_INVALID_PARAMETER },
585                 { 6,                            false, NT_STATUS_INVALID_PARAMETER },
586         };
587
588         torture_comment(torture, "Checking SMB2 Open\n");
589
590         smb2_util_unlink(tree, fname);
591         smb2_util_rmdir(tree, dname);
592
593         status = torture_smb2_testdir(tree, DNAME, &h);
594         CHECK_STATUS(status, NT_STATUS_OK);
595
596         ZERO_STRUCT(io.smb2);
597         /* reasonable default parameters */
598         io.generic.level = RAW_OPEN_SMB2;
599         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
600         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
601         io.smb2.in.alloc_size = 1024*1024;
602         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
603         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
604         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
605         io.smb2.in.create_options = 0;
606         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
607         io.smb2.in.security_flags = 0;
608         io.smb2.in.fname = fname;
609
610         /* test the create disposition */
611         for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
612                 if (open_funcs[i].with_file) {
613                         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
614                         status= smb2_create(tree, mem_ctx, &(io.smb2));
615                         if (!NT_STATUS_IS_OK(status)) {
616                                 torture_comment(torture,
617                                     "Failed to create file %s status %s %d\n",
618                                     fname, nt_errstr(status), i);
619
620                                 ret = false;
621                                 goto done;
622                         }
623                         smb2_util_close(tree, io.smb2.out.file.handle);
624                 }
625                 io.smb2.in.create_disposition = open_funcs[i].create_disp;
626                 status = smb2_create(tree, mem_ctx, &(io.smb2));
627                 if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
628                         torture_comment(torture,
629                             "(%s) incorrect status %s should be %s (i=%d "
630                             "with_file=%d open_disp=%d)\n",
631                          __location__, nt_errstr(status),
632                         nt_errstr(open_funcs[i].correct_status),
633                         i, (int)open_funcs[i].with_file,
634                         (int)open_funcs[i].create_disp);
635
636                         ret = false;
637                         goto done;
638                 }
639                 if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
640                         smb2_util_close(tree, io.smb2.out.file.handle);
641                         smb2_util_unlink(tree, fname);
642                 }
643         }
644
645         /* basic field testing */
646         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
647
648         status = smb2_create(tree, mem_ctx, &(io.smb2));
649         CHECK_STATUS(status, NT_STATUS_OK);
650         h1 = io.smb2.out.file.handle;
651
652         CHECK_VAL(io.smb2.out.oplock_level, 0);
653         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
654         CHECK_NTTIME(io.smb2.out.create_time, create_time);
655         CHECK_NTTIME(io.smb2.out.access_time, access_time);
656         CHECK_NTTIME(io.smb2.out.write_time, write_time);
657         CHECK_NTTIME(io.smb2.out.change_time, change_time);
658         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
659         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
660         CHECK_ALL_INFO(io.smb2.out.size, size);
661
662         /* check fields when the file already existed */
663         smb2_util_close(tree, h1);
664         smb2_util_unlink(tree, fname);
665
666         status = smb2_create_complex_file(tree, fname, &h1);
667         CHECK_STATUS(status, NT_STATUS_OK);
668
669         smb2_util_close(tree, h1);
670
671         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
672         status = smb2_create(tree, mem_ctx, &(io.smb2));
673         CHECK_STATUS(status, NT_STATUS_OK);
674         h1 = io.smb2.out.file.handle;
675
676         CHECK_VAL(io.smb2.out.oplock_level, 0);
677         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_EXISTED);
678         CHECK_NTTIME(io.smb2.out.create_time, create_time);
679         CHECK_NTTIME(io.smb2.out.access_time, access_time);
680         CHECK_NTTIME(io.smb2.out.write_time, write_time);
681         CHECK_NTTIME(io.smb2.out.change_time, change_time);
682         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
683         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
684         CHECK_ALL_INFO(io.smb2.out.size, size);
685         smb2_util_close(tree, h1);
686         smb2_util_unlink(tree, fname);
687
688         /* create a directory */
689         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
690         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
691         io.smb2.in.alloc_size = 0;
692         io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
693         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
694         io.smb2.in.create_options = 0;
695         io.smb2.in.fname = dname;
696         fname = dname;
697
698         smb2_util_rmdir(tree, fname);
699         smb2_util_unlink(tree, fname);
700
701         io.smb2.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
702         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
703         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
704         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
705                                 NTCREATEX_SHARE_ACCESS_WRITE;
706         status = smb2_create(tree, mem_ctx, &(io.smb2));
707         CHECK_STATUS(status, NT_STATUS_OK);
708         h1 = io.smb2.out.file.handle;
709
710         CHECK_VAL(io.smb2.out.oplock_level, 0);
711         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
712         CHECK_NTTIME(io.smb2.out.create_time, create_time);
713         CHECK_NTTIME(io.smb2.out.access_time, access_time);
714         CHECK_NTTIME(io.smb2.out.write_time, write_time);
715         CHECK_NTTIME(io.smb2.out.change_time, change_time);
716         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
717         CHECK_VAL(io.smb2.out.file_attr & ~FILE_ATTRIBUTE_NONINDEXED,
718                   FILE_ATTRIBUTE_DIRECTORY);
719         CHECK_ALL_INFO(io.smb2.out.alloc_size, alloc_size);
720         CHECK_ALL_INFO(io.smb2.out.size, size);
721         CHECK_VAL(io.smb2.out.size, 0);
722         CHECK_VAL(io.smb2.out.alloc_size, 0);
723         smb2_util_unlink(tree, fname);
724
725 done:
726         smb2_util_close(tree, h1);
727         smb2_util_unlink(tree, fname);
728         smb2_deltree(tree, DNAME);
729         talloc_free(mem_ctx);
730         return ret;
731 }
732
733 /*
734   test with an already opened and byte range locked file
735 */
736
737 static bool test_smb2_open_brlocked(struct torture_context *torture,
738                                     struct smb2_tree *tree)
739 {
740         union smb_open io, io1;
741         union smb_lock io2;
742         struct smb2_lock_element lock[1];
743         const char *fname = DNAME "\\torture_ntcreatex.txt";
744         NTSTATUS status;
745         bool ret = true;
746         struct smb2_handle h;
747
748         torture_comment(torture,
749                 "Testing SMB2 open with a byte range locked file\n");
750
751         smb2_util_unlink(tree, fname);
752
753         status = torture_smb2_testdir(tree, DNAME, &h);
754         CHECK_STATUS(status, NT_STATUS_OK);
755
756         ZERO_STRUCT(io.smb2);
757         io.generic.level = RAW_OPEN_SMB2;
758         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
759         io.smb2.in.desired_access = 0x2019f;
760         io.smb2.in.alloc_size = 0;
761         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
762         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
763                 NTCREATEX_SHARE_ACCESS_WRITE;
764         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
765         io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
766         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
767         io.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
768         io.smb2.in.fname = fname;
769
770         status = smb2_create(tree, torture, &(io.smb2));
771         CHECK_STATUS(status, NT_STATUS_OK);
772
773         ZERO_STRUCT(io2.smb2);
774         io2.smb2.level = RAW_LOCK_SMB2;
775         io2.smb2.in.file.handle = io.smb2.out.file.handle;
776         io2.smb2.in.lock_count = 1;
777
778         lock[0].offset = 0;
779         lock[0].flags = SMB2_LOCK_FLAG_EXCLUSIVE |
780                         SMB2_LOCK_FLAG_FAIL_IMMEDIATELY;
781         io2.smb2.in.locks = &lock[0];
782         status = smb2_lock(tree, &(io2.smb2));
783         CHECK_STATUS(status, NT_STATUS_OK);
784
785         ZERO_STRUCT(io1.smb2);
786         io1.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
787         io1.smb2.in.desired_access = 0x20196;
788         io1.smb2.in.alloc_size = 0;
789         io1.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
790         io1.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
791                 NTCREATEX_SHARE_ACCESS_WRITE;
792         io1.smb2.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
793         io1.smb2.in.create_options = 0;
794         io1.smb2.in.impersonation_level = SMB2_IMPERSONATION_IMPERSONATION;
795         io1.smb2.in.security_flags = SMB2_SECURITY_DYNAMIC_TRACKING;
796         io1.smb2.in.fname = fname;
797
798         status = smb2_create(tree, torture, &(io1.smb2));
799         CHECK_STATUS(status, NT_STATUS_OK);
800
801         smb2_util_close(tree, io.smb2.out.file.handle);
802         smb2_util_close(tree, io1.smb2.out.file.handle);
803         smb2_util_unlink(tree, fname);
804         smb2_deltree(tree, DNAME);
805
806         return ret;
807 }
808
809 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
810
811 static bool test_smb2_open_multi(struct torture_context *torture,
812                                 struct smb2_tree *tree)
813 {
814         TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
815         const char *fname = "test_oplock.dat";
816         NTSTATUS status;
817         bool ret = true;
818         union smb_open io;
819         struct smb2_tree **trees;
820         struct smb2_request **requests;
821         union smb_open *ios;
822         int i, num_files = 3;
823         int num_ok = 0;
824         int num_collision = 0;
825
826         if (mem_ctx == NULL) {
827                 ret = false;
828                 goto done;
829         }
830
831         torture_comment(torture,
832                 "Testing SMB2 Open with multiple connections\n");
833         trees = talloc_array(mem_ctx, struct smb2_tree *, num_files);
834         requests = talloc_array(mem_ctx, struct smb2_request *, num_files);
835         ios = talloc_array(mem_ctx, union smb_open, num_files);
836         if ((torture->ev == NULL) || (trees == NULL) || (requests == NULL) ||
837             (ios == NULL)) {
838                 torture_comment(torture, ("talloc failed\n"));
839                 ret = false;
840                 goto done;
841         }
842
843         tree->session->transport->options.request_timeout = 60;
844
845         for (i=0; i<num_files; i++) {
846                 if (!torture_smb2_connection(torture, &(trees[i]))) {
847                         torture_comment(torture,
848                                 "Could not open %d'th connection\n", i);
849                         ret = false;
850                         goto done;
851                 }
852                 trees[i]->session->transport->options.request_timeout = 60;
853         }
854
855         /* cleanup */
856         smb2_util_unlink(tree, fname);
857
858         /*
859           base ntcreatex parms
860         */
861         ZERO_STRUCT(io.smb2);
862         io.generic.level = RAW_OPEN_SMB2;
863         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
864         io.smb2.in.alloc_size = 0;
865         io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
866         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
867                 NTCREATEX_SHARE_ACCESS_WRITE|
868                 NTCREATEX_SHARE_ACCESS_DELETE;
869         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
870         io.smb2.in.create_options = 0;
871         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
872         io.smb2.in.security_flags = 0;
873         io.smb2.in.fname = fname;
874         io.smb2.in.create_flags = 0;
875
876         for (i=0; i<num_files; i++) {
877                 ios[i] = io;
878                 requests[i] = smb2_create_send(trees[i], &(ios[i].smb2));
879                 if (requests[i] == NULL) {
880                         torture_comment(torture,
881                                 "could not send %d'th request\n", i);
882                         ret = false;
883                         goto done;
884                 }
885         }
886
887         torture_comment(torture, "waiting for replies\n");
888         while (1) {
889                 bool unreplied = false;
890                 for (i=0; i<num_files; i++) {
891                         if (requests[i] == NULL) {
892                                 continue;
893                         }
894                         if (requests[i]->state < SMB2_REQUEST_DONE) {
895                                 unreplied = true;
896                                 break;
897                         }
898                         status = smb2_create_recv(requests[i], mem_ctx,
899                                                   &(ios[i].smb2));
900
901                         torture_comment(torture,
902                                 "File %d returned status %s\n", i,
903                                 nt_errstr(status));
904
905                         if (NT_STATUS_IS_OK(status)) {
906                                 num_ok += 1;
907                         }
908
909                         if (NT_STATUS_EQUAL(status,
910                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
911                                 num_collision += 1;
912                         }
913
914                         requests[i] = NULL;
915                 }
916                 if (!unreplied) {
917                         break;
918                 }
919
920                 if (event_loop_once(torture->ev) != 0) {
921                         torture_comment(torture, "event_loop_once failed\n");
922                         ret = false;
923                         goto done;
924                 }
925         }
926
927         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
928                 ret = false;
929         }
930 done:
931         talloc_free(mem_ctx);
932         smb2_deltree(tree, fname);
933
934         return ret;
935 }
936
937 /*
938   test opening for delete on a read-only attribute file.
939 */
940
941 static bool test_smb2_open_for_delete(struct torture_context *torture,
942                                       struct smb2_tree *tree)
943 {
944         union smb_open io;
945         union smb_fileinfo finfo;
946         const char *fname = DNAME "\\torture_open_for_delete.txt";
947         NTSTATUS status;
948         struct smb2_handle h, h1;
949         bool ret = true;
950
951         torture_comment(torture,
952                 "Checking SMB2_OPEN for delete on a readonly file.\n");
953         smb2_util_unlink(tree, fname);
954         smb2_deltree(tree, fname);
955
956         status = torture_smb2_testdir(tree, DNAME, &h);
957         CHECK_STATUS(status, NT_STATUS_OK);
958
959         /* reasonable default parameters */
960         ZERO_STRUCT(io.smb2);
961         io.generic.level = RAW_OPEN_SMB2;
962         io.smb2.in.create_flags = NTCREATEX_FLAGS_EXTENDED;
963         io.smb2.in.alloc_size = 0;
964         io.smb2.in.desired_access = SEC_RIGHTS_FILE_ALL;
965         io.smb2.in.file_attributes = FILE_ATTRIBUTE_READONLY;
966         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
967         io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
968         io.smb2.in.create_options = 0;
969         io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
970         io.smb2.in.security_flags = 0;
971         io.smb2.in.fname = fname;
972
973         /* Create the readonly file. */
974
975         status = smb2_create(tree, torture, &(io.smb2));
976         CHECK_STATUS(status, NT_STATUS_OK);
977         h1 = io.smb2.out.file.handle;
978
979         CHECK_VAL(io.smb2.out.oplock_level, 0);
980         io.smb2.in.create_options = 0;
981         CHECK_VAL(io.smb2.out.create_action, NTCREATEX_ACTION_CREATED);
982         CHECK_ALL_INFO(io.smb2.out.file_attr, attrib);
983         smb2_util_close(tree, h1);
984
985         /* Now try and open for delete only - should succeed. */
986         io.smb2.in.desired_access = SEC_STD_DELETE;
987         io.smb2.in.file_attributes = 0;
988         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
989                                 NTCREATEX_SHARE_ACCESS_WRITE |
990                                 NTCREATEX_SHARE_ACCESS_DELETE;
991         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
992         status = smb2_create(tree, torture, &(io.smb2));
993         CHECK_STATUS(status, NT_STATUS_OK);
994
995         smb2_util_unlink(tree, fname);
996
997         smb2_util_close(tree, h1);
998         smb2_util_unlink(tree, fname);
999         smb2_deltree(tree, DNAME);
1000
1001         return ret;
1002 }
1003
1004 /*
1005   test SMB2 open with a leading slash on the path.
1006   Trying to create a directory with a leading slash
1007   should give NT_STATUS_INVALID_PARAMETER error
1008 */
1009 static bool test_smb2_leading_slash(struct torture_context *torture,
1010                                     struct smb2_tree *tree)
1011 {
1012         union smb_open io;
1013         const char *dnameslash = "\\"DNAME;
1014         NTSTATUS status;
1015         bool ret = true;
1016
1017         torture_comment(torture,
1018                 "Trying to create a directory with leading slash on path\n");
1019         smb2_deltree(tree, dnameslash);
1020
1021         ZERO_STRUCT(io.smb2);
1022         io.generic.level = RAW_OPEN_SMB2;
1023         io.smb2.in.oplock_level = 0;
1024         io.smb2.in.desired_access = SEC_RIGHTS_DIR_ALL;
1025         io.smb2.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
1026         io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1027         io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1028                                 NTCREATEX_SHARE_ACCESS_WRITE |
1029                                 NTCREATEX_SHARE_ACCESS_DELETE;
1030         io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1031         io.smb2.in.fname = dnameslash;
1032
1033         status = smb2_create(tree, tree, &(io.smb2));
1034         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
1035
1036         smb2_deltree(tree, dnameslash);
1037         return ret;
1038 }
1039
1040
1041 /*
1042    basic testing of SMB2 read
1043 */
1044 struct torture_suite *torture_smb2_create_init(void)
1045 {
1046         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
1047
1048         torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
1049         torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
1050         torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
1051         torture_suite_add_1smb2_test(suite, "OPEN", test_smb2_open);
1052         torture_suite_add_1smb2_test(suite, "BRLOCKED", test_smb2_open_brlocked);
1053         torture_suite_add_1smb2_test(suite, "MULTI", test_smb2_open_multi);
1054         torture_suite_add_1smb2_test(suite, "DELETE", test_smb2_open_for_delete);
1055         torture_suite_add_1smb2_test(suite, "LEADING-SLASH", test_smb2_leading_slash);
1056
1057         suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
1058
1059         return suite;
1060 }