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