torture: fixed SMB2-LOCK valgrind error
[ira/wip.git] / source4 / torture / smb2 / compound.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    test suite for SMB2 compounded requests
5
6    Copyright (C) Stefan Metzmacher 2009
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
28 #define CHECK_STATUS(status, correct) do { \
29         if (!NT_STATUS_EQUAL(status, correct)) { \
30                 torture_result(tctx, TORTURE_FAIL, __location__": Incorrect status %s - should be %s", \
31                        nt_errstr(status), nt_errstr(correct)); \
32                 ret = false; \
33                 goto done; \
34         }} while (0)
35
36 static bool test_compound_related1(struct torture_context *tctx,
37                                    struct smb2_tree *tree)
38 {
39         struct smb2_handle hd;
40         struct smb2_create cr;
41         NTSTATUS status;
42         const char *fname = "compound_related1.dat";
43         struct smb2_close cl;
44         bool ret = true;
45         struct smb2_request *req[2];
46
47         smb2_transport_credits_ask_num(tree->session->transport, 2);
48
49         smb2_util_unlink(tree, fname);
50
51         smb2_transport_credits_ask_num(tree->session->transport, 1);
52
53         ZERO_STRUCT(cr);
54         cr.in.security_flags            = 0x00;
55         cr.in.oplock_level              = 0;
56         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
57         cr.in.create_flags              = 0x00000000;
58         cr.in.reserved                  = 0x00000000;
59         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
60         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
61         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
62                                           NTCREATEX_SHARE_ACCESS_WRITE |
63                                           NTCREATEX_SHARE_ACCESS_DELETE;
64         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
65         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
66                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
67                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
68                                           0x00200000;
69         cr.in.fname                     = fname;
70
71         smb2_transport_compound_start(tree->session->transport, 2);
72
73         req[0] = smb2_create_send(tree, &cr);
74
75         smb2_transport_compound_set_related(tree->session->transport, true);
76
77         hd.data[0] = UINT64_MAX;
78         hd.data[1] = UINT64_MAX;
79
80         ZERO_STRUCT(cl);
81         cl.in.file.handle = hd;
82         req[1] = smb2_close_send(tree, &cl);
83
84         status = smb2_create_recv(req[0], tree, &cr);
85         CHECK_STATUS(status, NT_STATUS_OK);
86         status = smb2_close_recv(req[1], &cl);
87         CHECK_STATUS(status, NT_STATUS_OK);
88
89         smb2_util_unlink(tree, fname);
90 done:
91         return ret;
92 }
93
94 static bool test_compound_related2(struct torture_context *tctx,
95                                    struct smb2_tree *tree)
96 {
97         struct smb2_handle hd;
98         struct smb2_create cr;
99         NTSTATUS status;
100         const char *fname = "compound_related2.dat";
101         struct smb2_close cl;
102         bool ret = true;
103         struct smb2_request *req[5];
104
105         smb2_transport_credits_ask_num(tree->session->transport, 5);
106
107         smb2_util_unlink(tree, fname);
108
109         smb2_transport_credits_ask_num(tree->session->transport, 1);
110
111         ZERO_STRUCT(cr);
112         cr.in.security_flags            = 0x00;
113         cr.in.oplock_level              = 0;
114         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
115         cr.in.create_flags              = 0x00000000;
116         cr.in.reserved                  = 0x00000000;
117         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
118         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
119         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
120                                           NTCREATEX_SHARE_ACCESS_WRITE |
121                                           NTCREATEX_SHARE_ACCESS_DELETE;
122         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
123         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
124                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
125                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
126                                           0x00200000;
127         cr.in.fname                     = fname;
128
129         smb2_transport_compound_start(tree->session->transport, 5);
130
131         req[0] = smb2_create_send(tree, &cr);
132
133         hd.data[0] = UINT64_MAX;
134         hd.data[1] = UINT64_MAX;
135
136         smb2_transport_compound_set_related(tree->session->transport, true);
137
138         ZERO_STRUCT(cl);
139         cl.in.file.handle = hd;
140         req[1] = smb2_close_send(tree, &cl);
141         req[2] = smb2_close_send(tree, &cl);
142         req[3] = smb2_close_send(tree, &cl);
143         req[4] = smb2_close_send(tree, &cl);
144
145         status = smb2_create_recv(req[0], tree, &cr);
146         CHECK_STATUS(status, NT_STATUS_OK);
147         status = smb2_close_recv(req[1], &cl);
148         CHECK_STATUS(status, NT_STATUS_OK);
149         status = smb2_close_recv(req[2], &cl);
150         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
151         status = smb2_close_recv(req[3], &cl);
152         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
153         status = smb2_close_recv(req[4], &cl);
154         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
155
156         smb2_util_unlink(tree, fname);
157 done:
158         return ret;
159 }
160
161 static bool test_compound_unrelated1(struct torture_context *tctx,
162                                      struct smb2_tree *tree)
163 {
164         struct smb2_handle hd;
165         struct smb2_create cr;
166         NTSTATUS status;
167         const char *fname = "compound_unrelated1.dat";
168         struct smb2_close cl;
169         bool ret = true;
170         struct smb2_request *req[5];
171
172         smb2_transport_credits_ask_num(tree->session->transport, 5);
173
174         smb2_util_unlink(tree, fname);
175
176         smb2_transport_credits_ask_num(tree->session->transport, 1);
177
178         ZERO_STRUCT(cr);
179         cr.in.security_flags            = 0x00;
180         cr.in.oplock_level              = 0;
181         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
182         cr.in.create_flags              = 0x00000000;
183         cr.in.reserved                  = 0x00000000;
184         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
185         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
186         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
187                                           NTCREATEX_SHARE_ACCESS_WRITE |
188                                           NTCREATEX_SHARE_ACCESS_DELETE;
189         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
190         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
191                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
192                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
193                                           0x00200000;
194         cr.in.fname                     = fname;
195
196         smb2_transport_compound_start(tree->session->transport, 5);
197
198         req[0] = smb2_create_send(tree, &cr);
199
200         hd.data[0] = UINT64_MAX;
201         hd.data[1] = UINT64_MAX;
202
203         ZERO_STRUCT(cl);
204         cl.in.file.handle = hd;
205         req[1] = smb2_close_send(tree, &cl);
206         req[2] = smb2_close_send(tree, &cl);
207         req[3] = smb2_close_send(tree, &cl);
208         req[4] = smb2_close_send(tree, &cl);
209
210         status = smb2_create_recv(req[0], tree, &cr);
211         CHECK_STATUS(status, NT_STATUS_OK);
212         status = smb2_close_recv(req[1], &cl);
213         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
214         status = smb2_close_recv(req[2], &cl);
215         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
216         status = smb2_close_recv(req[3], &cl);
217         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
218         status = smb2_close_recv(req[4], &cl);
219         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
220
221         smb2_util_unlink(tree, fname);
222 done:
223         return ret;
224 }
225
226 static bool test_compound_invalid1(struct torture_context *tctx,
227                                    struct smb2_tree *tree)
228 {
229         struct smb2_handle hd;
230         struct smb2_create cr;
231         NTSTATUS status;
232         const char *fname = "compound_invalid1.dat";
233         struct smb2_close cl;
234         bool ret = true;
235         struct smb2_request *req[2];
236
237         smb2_transport_credits_ask_num(tree->session->transport, 2);
238
239         smb2_util_unlink(tree, fname);
240
241         smb2_transport_credits_ask_num(tree->session->transport, 1);
242
243         ZERO_STRUCT(cr);
244         cr.in.security_flags            = 0x00;
245         cr.in.oplock_level              = 0;
246         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
247         cr.in.create_flags              = 0x00000000;
248         cr.in.reserved                  = 0x00000000;
249         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
250         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
251         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
252                                           NTCREATEX_SHARE_ACCESS_WRITE |
253                                           NTCREATEX_SHARE_ACCESS_DELETE;
254         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
255         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
256                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
257                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
258                                           0x00200000;
259         cr.in.fname                     = fname;
260
261         smb2_transport_compound_start(tree->session->transport, 2);
262
263         /* passing the first request with the related flag is invalid */
264         smb2_transport_compound_set_related(tree->session->transport, true);
265
266         req[0] = smb2_create_send(tree, &cr);
267
268         hd.data[0] = UINT64_MAX;
269         hd.data[1] = UINT64_MAX;
270
271         ZERO_STRUCT(cl);
272         cl.in.file.handle = hd;
273         req[1] = smb2_close_send(tree, &cl);
274
275         status = smb2_create_recv(req[0], tree, &cr);
276         /* TODO: check why this fails with --signing=required */
277         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
278         status = smb2_close_recv(req[1], &cl);
279         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
280
281         smb2_util_unlink(tree, fname);
282 done:
283         return ret;
284 }
285
286 static bool test_compound_invalid2(struct torture_context *tctx,
287                                    struct smb2_tree *tree)
288 {
289         struct smb2_handle hd;
290         struct smb2_create cr;
291         NTSTATUS status;
292         const char *fname = "compound_invalid2.dat";
293         struct smb2_close cl;
294         bool ret = true;
295         struct smb2_request *req[5];
296
297         smb2_transport_credits_ask_num(tree->session->transport, 5);
298
299         smb2_util_unlink(tree, fname);
300
301         smb2_transport_credits_ask_num(tree->session->transport, 1);
302
303         ZERO_STRUCT(cr);
304         cr.in.security_flags            = 0x00;
305         cr.in.oplock_level              = 0;
306         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
307         cr.in.create_flags              = 0x00000000;
308         cr.in.reserved                  = 0x00000000;
309         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
310         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
311         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
312                                           NTCREATEX_SHARE_ACCESS_WRITE |
313                                           NTCREATEX_SHARE_ACCESS_DELETE;
314         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
315         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
316                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
317                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
318                                           0x00200000;
319         cr.in.fname                     = fname;
320
321         smb2_transport_compound_start(tree->session->transport, 5);
322
323         req[0] = smb2_create_send(tree, &cr);
324
325         hd.data[0] = UINT64_MAX;
326         hd.data[1] = UINT64_MAX;
327
328         smb2_transport_compound_set_related(tree->session->transport, true);
329
330         ZERO_STRUCT(cl);
331         cl.in.file.handle = hd;
332         req[1] = smb2_close_send(tree, &cl);
333         /* strange that this is not generating invalid parameter */
334         smb2_transport_compound_set_related(tree->session->transport, false);
335         req[2] = smb2_close_send(tree, &cl);
336         req[3] = smb2_close_send(tree, &cl);
337         smb2_transport_compound_set_related(tree->session->transport, true);
338         req[4] = smb2_close_send(tree, &cl);
339
340         status = smb2_create_recv(req[0], tree, &cr);
341         CHECK_STATUS(status, NT_STATUS_OK);
342         status = smb2_close_recv(req[1], &cl);
343         CHECK_STATUS(status, NT_STATUS_OK);
344         status = smb2_close_recv(req[2], &cl);
345         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
346         status = smb2_close_recv(req[3], &cl);
347         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
348         status = smb2_close_recv(req[4], &cl);
349         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
350
351         smb2_util_unlink(tree, fname);
352 done:
353         return ret;
354 }
355
356 static bool test_compound_invalid3(struct torture_context *tctx,
357                                    struct smb2_tree *tree)
358 {
359         struct smb2_handle hd;
360         struct smb2_create cr;
361         NTSTATUS status;
362         const char *fname = "compound_invalid3.dat";
363         struct smb2_close cl;
364         bool ret = true;
365         struct smb2_request *req[5];
366
367         smb2_transport_credits_ask_num(tree->session->transport, 5);
368
369         smb2_util_unlink(tree, fname);
370
371         smb2_transport_credits_ask_num(tree->session->transport, 1);
372
373         ZERO_STRUCT(cr);
374         cr.in.security_flags            = 0x00;
375         cr.in.oplock_level              = 0;
376         cr.in.impersonation_level       = NTCREATEX_IMPERSONATION_IMPERSONATION;
377         cr.in.create_flags              = 0x00000000;
378         cr.in.reserved                  = 0x00000000;
379         cr.in.desired_access            = SEC_RIGHTS_FILE_ALL;
380         cr.in.file_attributes           = FILE_ATTRIBUTE_NORMAL;
381         cr.in.share_access              = NTCREATEX_SHARE_ACCESS_READ |
382                                           NTCREATEX_SHARE_ACCESS_WRITE |
383                                           NTCREATEX_SHARE_ACCESS_DELETE;
384         cr.in.create_disposition        = NTCREATEX_DISP_OPEN_IF;
385         cr.in.create_options            = NTCREATEX_OPTIONS_SEQUENTIAL_ONLY |
386                                           NTCREATEX_OPTIONS_ASYNC_ALERT |
387                                           NTCREATEX_OPTIONS_NON_DIRECTORY_FILE |
388                                           0x00200000;
389         cr.in.fname                     = fname;
390
391         smb2_transport_compound_start(tree->session->transport, 5);
392
393         req[0] = smb2_create_send(tree, &cr);
394
395         hd.data[0] = UINT64_MAX;
396         hd.data[1] = UINT64_MAX;
397
398         ZERO_STRUCT(cl);
399         cl.in.file.handle = hd;
400         req[1] = smb2_close_send(tree, &cl);
401         req[2] = smb2_close_send(tree, &cl);
402         /* flipping the related flag is invalid */
403         smb2_transport_compound_set_related(tree->session->transport, true);
404         req[3] = smb2_close_send(tree, &cl);
405         req[4] = smb2_close_send(tree, &cl);
406
407         status = smb2_create_recv(req[0], tree, &cr);
408         CHECK_STATUS(status, NT_STATUS_OK);
409         status = smb2_close_recv(req[1], &cl);
410         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
411         status = smb2_close_recv(req[2], &cl);
412         CHECK_STATUS(status, NT_STATUS_FILE_CLOSED);
413         status = smb2_close_recv(req[3], &cl);
414         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
415         status = smb2_close_recv(req[4], &cl);
416         CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
417
418         smb2_util_unlink(tree, fname);
419 done:
420         return ret;
421 }
422
423 struct torture_suite *torture_smb2_compound_init(void)
424 {
425         struct torture_suite *suite =
426             torture_suite_create(talloc_autofree_context(), "COMPOUND");
427
428         torture_suite_add_1smb2_test(suite, "RELATED1", test_compound_related1);
429         torture_suite_add_1smb2_test(suite, "RELATED2", test_compound_related2);
430         torture_suite_add_1smb2_test(suite, "UNRELATED1", test_compound_unrelated1);
431         torture_suite_add_1smb2_test(suite, "INVALID1", test_compound_invalid1);
432         torture_suite_add_1smb2_test(suite, "INVALID2", test_compound_invalid2);
433         torture_suite_add_1smb2_test(suite, "INVALID3", test_compound_invalid3);
434
435         suite->description = talloc_strdup(suite, "SMB2-COMPOUND tests");
436
437         return suite;
438 }