58d38a2cb33a55c3425f7a1dc0ab1f6a8ff22542
[kai/samba.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/smb2/proto.h"
27 #include "param/param.h"
28 #include "librpc/gen_ndr/ndr_security.h"
29 #include "libcli/security/security.h"
30
31 #define FNAME "test_create.dat"
32
33 #define CHECK_STATUS(status, correct) do { \
34         if (!NT_STATUS_EQUAL(status, correct)) { \
35                 printf("(%s) Incorrect status %s - should be %s\n", \
36                        __location__, nt_errstr(status), nt_errstr(correct)); \
37                 return false; \
38         }} while (0)
39
40 #define CHECK_EQUAL(v, correct) do { \
41         if (v != correct) { \
42                 printf("(%s) Incorrect value for %s 0x%08llx - should be 0x%08llx\n", \
43                        __location__, #v, (unsigned long long)v, (unsigned long long)correct); \
44                 return false; \
45         }} while (0)
46
47 /*
48   test some interesting combinations found by gentest
49  */
50 static bool test_create_gentest(struct torture_context *torture, struct smb2_tree *tree)
51 {
52         struct smb2_create io;
53         NTSTATUS status;
54         TALLOC_CTX *tmp_ctx = talloc_new(tree);
55         uint32_t access_mask, file_attributes, file_attributes_set, denied_mask;
56
57         ZERO_STRUCT(io);
58         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
59         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
60         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
61         io.in.share_access = 
62                 NTCREATEX_SHARE_ACCESS_DELETE|
63                 NTCREATEX_SHARE_ACCESS_READ|
64                 NTCREATEX_SHARE_ACCESS_WRITE;
65         io.in.create_options = 0;
66         io.in.fname = FNAME;
67
68         status = smb2_create(tree, tmp_ctx, &io);
69         CHECK_STATUS(status, NT_STATUS_OK);
70
71         status = smb2_util_close(tree, io.out.file.handle);
72         CHECK_STATUS(status, NT_STATUS_OK);
73
74         io.in.create_options = 0xF0000000;
75         status = smb2_create(tree, tmp_ctx, &io);
76         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
77
78         io.in.create_options = 0x00100000;
79         status = smb2_create(tree, tmp_ctx, &io);
80         CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED);
81
82         io.in.create_options = 0xF0100000;
83         status = smb2_create(tree, tmp_ctx, &io);
84         CHECK_STATUS(status, NT_STATUS_NOT_SUPPORTED);
85
86         io.in.create_options = 0;
87
88         io.in.file_attributes = FILE_ATTRIBUTE_DEVICE;
89         status = smb2_create(tree, tmp_ctx, &io);
90         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
91
92         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
93         status = smb2_create(tree, tmp_ctx, &io);
94         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
95
96         io.in.create_disposition = NTCREATEX_DISP_OPEN;
97         io.in.file_attributes = FILE_ATTRIBUTE_VOLUME;
98         status = smb2_create(tree, tmp_ctx, &io);
99         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
100         
101         io.in.create_disposition = NTCREATEX_DISP_CREATE;
102         io.in.desired_access = 0x08000000;
103         status = smb2_create(tree, tmp_ctx, &io);
104         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
105
106         io.in.desired_access = 0x04000000;
107         status = smb2_create(tree, tmp_ctx, &io);
108         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
109
110         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
111         io.in.file_attributes = 0;
112         access_mask = 0;
113         {
114                 int i;
115                 for (i=0;i<32;i++) {
116                         io.in.desired_access = 1<<i;
117                         status = smb2_create(tree, tmp_ctx, &io);
118                         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) ||
119                             NT_STATUS_EQUAL(status, NT_STATUS_PRIVILEGE_NOT_HELD)) {
120                                 access_mask |= io.in.desired_access;
121                         } else {
122                                 CHECK_STATUS(status, NT_STATUS_OK);
123                                 status = smb2_util_close(tree, io.out.file.handle);
124                                 CHECK_STATUS(status, NT_STATUS_OK);
125                         }
126                 }
127         }
128
129         CHECK_EQUAL(access_mask, 0x0df0fe00);
130
131         io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
132         io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
133         io.in.file_attributes = 0;
134         file_attributes = 0;
135         file_attributes_set = 0;
136         denied_mask = 0;
137         {
138                 int i;
139                 for (i=0;i<32;i++) {
140                         io.in.file_attributes = 1<<i;
141                         smb2_deltree(tree, FNAME);
142                         status = smb2_create(tree, tmp_ctx, &io);
143                         if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
144                                 file_attributes |= io.in.file_attributes;
145                         } else if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
146                                 denied_mask |= io.in.file_attributes;
147                         } else {
148                                 CHECK_STATUS(status, NT_STATUS_OK);
149                                 status = smb2_util_close(tree, io.out.file.handle);
150                                 CHECK_STATUS(status, NT_STATUS_OK);
151                                 file_attributes_set |= io.out.file_attr;
152                         }
153                 }
154         }
155
156         CHECK_EQUAL(file_attributes, 0xffff8048);
157         CHECK_EQUAL(denied_mask, 0x4000);
158         CHECK_EQUAL(file_attributes_set, 0x00001127);
159
160         smb2_deltree(tree, FNAME);
161
162         ZERO_STRUCT(io);
163         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
164         io.in.file_attributes    = 0;
165         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
166         io.in.share_access = 
167                 NTCREATEX_SHARE_ACCESS_READ|
168                 NTCREATEX_SHARE_ACCESS_WRITE;
169         io.in.create_options = 0;
170         io.in.fname = FNAME ":stream1";
171         status = smb2_create(tree, tmp_ctx, &io);
172         CHECK_STATUS(status, NT_STATUS_OK);
173
174         status = smb2_util_close(tree, io.out.file.handle);
175         CHECK_STATUS(status, NT_STATUS_OK);
176
177         io.in.fname = FNAME;
178         io.in.file_attributes = 0x8040;
179         io.in.share_access = 
180                 NTCREATEX_SHARE_ACCESS_READ;
181         status = smb2_create(tree, tmp_ctx, &io);
182         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
183
184         talloc_free(tmp_ctx);
185
186         smb2_deltree(tree, FNAME);
187         
188         return true;
189 }
190
191
192 /*
193   try the various request blobs
194  */
195 static bool test_create_blob(struct torture_context *torture, struct smb2_tree *tree)
196 {
197         struct smb2_create io;
198         NTSTATUS status;
199         TALLOC_CTX *tmp_ctx = talloc_new(tree);
200
201         smb2_deltree(tree, FNAME);
202
203         ZERO_STRUCT(io);
204         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
205         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
206         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
207         io.in.share_access = 
208                 NTCREATEX_SHARE_ACCESS_DELETE|
209                 NTCREATEX_SHARE_ACCESS_READ|
210                 NTCREATEX_SHARE_ACCESS_WRITE;
211         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
212                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
213                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
214                                           0x00200000;
215         io.in.fname = FNAME;
216
217         status = smb2_create(tree, tmp_ctx, &io);
218         CHECK_STATUS(status, NT_STATUS_OK);
219
220         status = smb2_util_close(tree, io.out.file.handle);
221         CHECK_STATUS(status, NT_STATUS_OK);
222
223         printf("testing alloc size\n");
224         io.in.alloc_size = 4096;
225         status = smb2_create(tree, tmp_ctx, &io);
226         CHECK_STATUS(status, NT_STATUS_OK);
227         CHECK_EQUAL(io.out.alloc_size, io.in.alloc_size);
228
229         status = smb2_util_close(tree, io.out.file.handle);
230         CHECK_STATUS(status, NT_STATUS_OK);
231
232         printf("testing durable open\n");
233         io.in.durable_open = true;
234         status = smb2_create(tree, tmp_ctx, &io);
235         CHECK_STATUS(status, NT_STATUS_OK);
236
237         status = smb2_util_close(tree, io.out.file.handle);
238         CHECK_STATUS(status, NT_STATUS_OK);
239
240         printf("testing query maximal access\n");
241         io.in.query_maximal_access = true;
242         status = smb2_create(tree, tmp_ctx, &io);
243         CHECK_STATUS(status, NT_STATUS_OK);
244
245         status = smb2_util_close(tree, io.out.file.handle);
246         CHECK_STATUS(status, NT_STATUS_OK);
247
248         printf("testing timewarp\n");
249         io.in.timewarp = 10000;
250         status = smb2_create(tree, tmp_ctx, &io);
251         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
252         io.in.timewarp = 0;
253
254         printf("testing query_on_disk\n");
255         io.in.query_on_disk_id = true;
256         status = smb2_create(tree, tmp_ctx, &io);
257         CHECK_STATUS(status, NT_STATUS_OK);
258
259         status = smb2_util_close(tree, io.out.file.handle);
260         CHECK_STATUS(status, NT_STATUS_OK);
261
262         printf("testing unknown tag\n");
263         status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
264                                       "FooO", data_blob(NULL, 0));
265         CHECK_STATUS(status, NT_STATUS_OK);
266
267         status = smb2_create(tree, tmp_ctx, &io);
268         CHECK_STATUS(status, NT_STATUS_OK);
269
270         status = smb2_util_close(tree, io.out.file.handle);
271         CHECK_STATUS(status, NT_STATUS_OK);
272
273         printf("testing bad tag length\n");
274         status = smb2_create_blob_add(tmp_ctx, &io.in.blobs,
275                                       "xxx", data_blob(NULL, 0));
276         CHECK_STATUS(status, NT_STATUS_OK);
277
278         status = smb2_create(tree, tmp_ctx, &io);
279         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
280
281         talloc_free(tmp_ctx);
282
283         smb2_deltree(tree, FNAME);
284         
285         return true;
286 }
287
288 /*
289   try creating with acls
290  */
291 static bool test_create_acl(struct torture_context *torture, struct smb2_tree *tree)
292 {
293         struct smb2_create io;
294         NTSTATUS status;
295         TALLOC_CTX *tmp_ctx = talloc_new(tree);
296         struct security_ace ace;
297         struct security_descriptor *sd, *sd2;
298         struct dom_sid *test_sid;
299         union smb_fileinfo q;
300
301         smb2_deltree(tree, FNAME);
302
303         ZERO_STRUCT(io);
304         io.in.desired_access     = SEC_FLAG_MAXIMUM_ALLOWED;
305         io.in.file_attributes    = FILE_ATTRIBUTE_NORMAL;
306         io.in.create_disposition = NTCREATEX_DISP_OVERWRITE_IF;
307         io.in.share_access = 
308                 NTCREATEX_SHARE_ACCESS_DELETE|
309                 NTCREATEX_SHARE_ACCESS_READ|
310                 NTCREATEX_SHARE_ACCESS_WRITE;
311         io.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
312                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
313                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
314                                           0x00200000;
315         io.in.fname = FNAME;
316
317         status = smb2_create(tree, tmp_ctx, &io);
318         CHECK_STATUS(status, NT_STATUS_OK);
319
320         q.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
321         q.query_secdesc.in.file.handle = io.out.file.handle;
322         q.query_secdesc.in.secinfo_flags = 
323                 SECINFO_OWNER |
324                 SECINFO_GROUP |
325                 SECINFO_DACL;
326         status = smb2_getinfo_file(tree, tmp_ctx, &q);
327         CHECK_STATUS(status, NT_STATUS_OK);
328         sd = q.query_secdesc.out.sd;
329
330         status = smb2_util_close(tree, io.out.file.handle);
331         CHECK_STATUS(status, NT_STATUS_OK);
332
333         smb2_util_unlink(tree, FNAME);
334
335         printf("adding a new ACE\n");
336         test_sid = dom_sid_parse_talloc(tmp_ctx, "S-1-5-32-1234-54321");
337
338         ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
339         ace.flags = 0;
340         ace.access_mask = SEC_STD_ALL;
341         ace.trustee = *test_sid;
342
343         status = security_descriptor_dacl_add(sd, &ace);
344         CHECK_STATUS(status, NT_STATUS_OK);
345         
346         printf("creating a file with an initial ACL\n");
347
348         io.in.sec_desc = sd;
349         status = smb2_create(tree, tmp_ctx, &io);
350         CHECK_STATUS(status, NT_STATUS_OK);
351
352         q.query_secdesc.in.file.handle = io.out.file.handle;
353         status = smb2_getinfo_file(tree, tmp_ctx, &q);
354         CHECK_STATUS(status, NT_STATUS_OK);
355         sd2 = q.query_secdesc.out.sd;
356
357         if (!security_acl_equal(sd->dacl, sd2->dacl)) {
358                 printf("%s: security descriptors don't match!\n", __location__);
359                 printf("got:\n");
360                 NDR_PRINT_DEBUG(security_descriptor, sd2);
361                 printf("expected:\n");
362                 NDR_PRINT_DEBUG(security_descriptor, sd);
363                 return false;
364         }
365
366         talloc_free(tmp_ctx);
367         
368         return true;
369 }
370
371 /* 
372    basic testing of SMB2 read
373 */
374 struct torture_suite *torture_smb2_create_init(void)
375 {
376         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "CREATE");
377
378         torture_suite_add_1smb2_test(suite, "GENTEST", test_create_gentest);
379         torture_suite_add_1smb2_test(suite, "BLOB", test_create_blob);
380         torture_suite_add_1smb2_test(suite, "ACL", test_create_acl);
381
382         suite->description = talloc_strdup(suite, "SMB2-CREATE tests");
383
384         return suite;
385 }