Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : SMB2 rename test suite
5 :
6 : Copyright (C) Christian Ambach 2012
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 <tevent.h>
26 : #include "lib/util/tevent_ntstatus.h"
27 :
28 : #include "torture/torture.h"
29 : #include "torture/util.h"
30 : #include "torture/smb2/proto.h"
31 :
32 : #include "librpc/gen_ndr/security.h"
33 :
34 : #define CHECK_VAL(v, correct) \
35 : do { \
36 : if ((v) != (correct)) { \
37 : torture_result(torture, \
38 : TORTURE_FAIL, \
39 : "(%s): wrong value for %s got " \
40 : "0x%llx - should be 0x%llx\n", \
41 : __location__, #v, \
42 : (unsigned long long)v, \
43 : (unsigned long long)correct); \
44 : ret = false; \
45 : goto done; \
46 : }} while (0)
47 :
48 : #define CHECK_CREATED(__io, __created, __attribute) \
49 : do { \
50 : CHECK_VAL((__io)->out.create_action, NTCREATEX_ACTION_ ## __created); \
51 : CHECK_VAL((__io)->out.size, 0); \
52 : CHECK_VAL((__io)->out.file_attr, (__attribute)); \
53 : CHECK_VAL((__io)->out.reserved2, 0); \
54 : } while(0)
55 :
56 : #define CHECK_STATUS(status, correct) do { \
57 : if (!NT_STATUS_EQUAL(status, correct)) { \
58 : torture_result(torture, TORTURE_FAIL, \
59 : "(%s) Incorrect status %s - should be %s\n", \
60 : __location__, nt_errstr(status), nt_errstr(correct)); \
61 : ret = false; \
62 : goto done; \
63 : }} while (0)
64 :
65 : #define BASEDIR "test_rename"
66 :
67 : /*
68 : * basic testing of rename: open file with DELETE access
69 : * this should pass
70 : */
71 :
72 2 : static bool torture_smb2_rename_simple(struct torture_context *torture,
73 : struct smb2_tree *tree1)
74 : {
75 2 : bool ret = true;
76 0 : NTSTATUS status;
77 0 : union smb_open io;
78 0 : union smb_close cl;
79 0 : union smb_setfileinfo sinfo;
80 0 : union smb_fileinfo fi;
81 0 : struct smb2_handle h1;
82 :
83 2 : ZERO_STRUCT(h1);
84 :
85 2 : smb2_deltree(tree1, BASEDIR);
86 2 : smb2_util_rmdir(tree1, BASEDIR);
87 :
88 2 : torture_comment(torture, "Creating base directory\n");
89 :
90 2 : smb2_util_mkdir(tree1, BASEDIR);
91 :
92 :
93 2 : torture_comment(torture, "Creating test file\n");
94 :
95 2 : ZERO_STRUCT(io.smb2);
96 2 : io.generic.level = RAW_OPEN_SMB2;
97 2 : io.smb2.in.create_flags = 0;
98 2 : io.smb2.in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE;
99 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
100 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
101 2 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
102 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
103 2 : io.smb2.in.alloc_size = 0;
104 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
105 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
106 2 : io.smb2.in.security_flags = 0;
107 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
108 :
109 2 : status = smb2_create(tree1, torture, &(io.smb2));
110 2 : CHECK_STATUS(status, NT_STATUS_OK);
111 2 : h1 = io.smb2.out.file.handle;
112 :
113 2 : torture_comment(torture, "Renaming test file\n");
114 :
115 2 : ZERO_STRUCT(sinfo);
116 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
117 2 : sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
118 2 : sinfo.rename_information.in.overwrite = 0;
119 2 : sinfo.rename_information.in.root_fid = 0;
120 2 : sinfo.rename_information.in.new_name =
121 : BASEDIR "\\newname.txt";
122 2 : status = smb2_setinfo_file(tree1, &sinfo);
123 2 : CHECK_STATUS(status, NT_STATUS_OK);
124 :
125 2 : torture_comment(torture, "Checking for new filename\n");
126 :
127 2 : ZERO_STRUCT(fi);
128 2 : fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
129 2 : fi.generic.in.file.handle = h1;
130 2 : status = smb2_getinfo_file(tree1, torture, &fi);
131 2 : CHECK_STATUS(status, NT_STATUS_OK);
132 :
133 :
134 2 : torture_comment(torture, "Closing test file\n");
135 :
136 2 : ZERO_STRUCT(cl.smb2);
137 2 : cl.smb2.level = RAW_CLOSE_SMB2;
138 2 : cl.smb2.in.file.handle = h1;
139 2 : status = smb2_close(tree1, &(cl.smb2));
140 2 : CHECK_STATUS(status, NT_STATUS_OK);
141 :
142 2 : ZERO_STRUCT(h1);
143 :
144 2 : done:
145 :
146 2 : torture_comment(torture, "Cleaning up\n");
147 :
148 2 : if (h1.data[0] || h1.data[1]) {
149 0 : ZERO_STRUCT(cl.smb2);
150 0 : cl.smb2.level = RAW_CLOSE_SMB2;
151 0 : cl.smb2.in.file.handle = h1;
152 0 : status = smb2_close(tree1, &(cl.smb2));
153 : }
154 2 : smb2_deltree(tree1, BASEDIR);
155 2 : return ret;
156 : }
157 :
158 : /*
159 : * basic testing of rename, this time do not request DELETE access
160 : * for the file, this should fail
161 : */
162 :
163 2 : static bool torture_smb2_rename_simple2(struct torture_context *torture,
164 : struct smb2_tree *tree1)
165 : {
166 2 : bool ret = true;
167 0 : NTSTATUS status;
168 0 : union smb_open io;
169 0 : union smb_close cl;
170 0 : union smb_setfileinfo sinfo;
171 0 : struct smb2_handle h1;
172 :
173 2 : ZERO_STRUCT(h1);
174 :
175 2 : smb2_deltree(tree1, BASEDIR);
176 2 : smb2_util_rmdir(tree1, BASEDIR);
177 :
178 2 : torture_comment(torture, "Creating base directory\n");
179 :
180 2 : smb2_util_mkdir(tree1, BASEDIR);
181 :
182 :
183 2 : torture_comment(torture, "Creating test file\n");
184 :
185 2 : ZERO_STRUCT(io.smb2);
186 2 : io.generic.level = RAW_OPEN_SMB2;
187 2 : io.smb2.in.create_flags = 0;
188 2 : io.smb2.in.desired_access = SEC_FILE_ALL;
189 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
190 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
191 2 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
192 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
193 2 : io.smb2.in.alloc_size = 0;
194 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
195 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
196 2 : io.smb2.in.security_flags = 0;
197 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
198 :
199 2 : status = smb2_create(tree1, torture, &(io.smb2));
200 2 : CHECK_STATUS(status, NT_STATUS_OK);
201 2 : h1 = io.smb2.out.file.handle;
202 :
203 2 : torture_comment(torture, "Renaming test file\n");
204 :
205 2 : ZERO_STRUCT(sinfo);
206 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
207 2 : sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
208 2 : sinfo.rename_information.in.overwrite = 0;
209 2 : sinfo.rename_information.in.root_fid = 0;
210 2 : sinfo.rename_information.in.new_name =
211 : BASEDIR "\\newname.txt";
212 2 : status = smb2_setinfo_file(tree1, &sinfo);
213 2 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
214 :
215 0 : torture_comment(torture, "Closing test file\n");
216 :
217 0 : ZERO_STRUCT(cl.smb2);
218 0 : cl.smb2.level = RAW_CLOSE_SMB2;
219 0 : cl.smb2.in.file.handle = h1;
220 0 : status = smb2_close(tree1, &(cl.smb2));
221 0 : CHECK_STATUS(status, NT_STATUS_OK);
222 :
223 0 : ZERO_STRUCT(h1);
224 :
225 2 : done:
226 :
227 2 : torture_comment(torture, "Cleaning up\n");
228 :
229 2 : if (h1.data[0] || h1.data[1]) {
230 2 : ZERO_STRUCT(cl.smb2);
231 2 : cl.smb2.level = RAW_CLOSE_SMB2;
232 2 : cl.smb2.in.file.handle = h1;
233 2 : status = smb2_close(tree1, &(cl.smb2));
234 : }
235 2 : smb2_deltree(tree1, BASEDIR);
236 2 : return ret;
237 : }
238 :
239 :
240 : /*
241 : * testing of rename with no sharing allowed on file
242 : * this should work
243 : */
244 :
245 2 : static bool torture_smb2_rename_no_sharemode(struct torture_context *torture,
246 : struct smb2_tree *tree1)
247 : {
248 2 : bool ret = true;
249 0 : NTSTATUS status;
250 0 : union smb_open io;
251 0 : union smb_close cl;
252 0 : union smb_setfileinfo sinfo;
253 0 : union smb_fileinfo fi;
254 0 : struct smb2_handle h1;
255 :
256 2 : ZERO_STRUCT(h1);
257 :
258 2 : smb2_deltree(tree1, BASEDIR);
259 2 : smb2_util_rmdir(tree1, BASEDIR);
260 :
261 2 : torture_comment(torture, "Creating base directory\n");
262 :
263 2 : smb2_util_mkdir(tree1, BASEDIR);
264 :
265 :
266 2 : torture_comment(torture, "Creating test file\n");
267 :
268 2 : ZERO_STRUCT(io.smb2);
269 2 : io.generic.level = RAW_OPEN_SMB2;
270 2 : io.smb2.in.create_flags = 0;
271 2 : io.smb2.in.desired_access = 0x0017019f;
272 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
273 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
274 2 : io.smb2.in.share_access = 0;
275 2 : io.smb2.in.alloc_size = 0;
276 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
277 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
278 2 : io.smb2.in.security_flags = 0;
279 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
280 :
281 2 : status = smb2_create(tree1, torture, &(io.smb2));
282 2 : CHECK_STATUS(status, NT_STATUS_OK);
283 2 : h1 = io.smb2.out.file.handle;
284 :
285 2 : torture_comment(torture, "Renaming test file\n");
286 :
287 2 : ZERO_STRUCT(sinfo);
288 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
289 2 : sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
290 2 : sinfo.rename_information.in.overwrite = 0;
291 2 : sinfo.rename_information.in.root_fid = 0;
292 2 : sinfo.rename_information.in.new_name =
293 : BASEDIR "\\newname.txt";
294 2 : status = smb2_setinfo_file(tree1, &sinfo);
295 2 : CHECK_STATUS(status, NT_STATUS_OK);
296 :
297 2 : torture_comment(torture, "Checking for new filename\n");
298 :
299 2 : ZERO_STRUCT(fi);
300 2 : fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
301 2 : fi.generic.in.file.handle = h1;
302 2 : status = smb2_getinfo_file(tree1, torture, &fi);
303 2 : CHECK_STATUS(status, NT_STATUS_OK);
304 :
305 :
306 2 : torture_comment(torture, "Closing test file\n");
307 :
308 2 : ZERO_STRUCT(cl.smb2);
309 2 : cl.smb2.level = RAW_CLOSE_SMB2;
310 2 : cl.smb2.in.file.handle = h1;
311 2 : status = smb2_close(tree1, &(cl.smb2));
312 2 : CHECK_STATUS(status, NT_STATUS_OK);
313 :
314 2 : ZERO_STRUCT(h1);
315 :
316 2 : done:
317 :
318 2 : torture_comment(torture, "Cleaning up\n");
319 :
320 2 : if (h1.data[0] || h1.data[1]) {
321 0 : ZERO_STRUCT(cl.smb2);
322 0 : cl.smb2.level = RAW_CLOSE_SMB2;
323 0 : cl.smb2.in.file.handle = h1;
324 0 : status = smb2_close(tree1, &(cl.smb2));
325 : }
326 2 : smb2_deltree(tree1, BASEDIR);
327 2 : return ret;
328 : }
329 :
330 : /*
331 : * testing of rename when opening parent dir with delete access and delete
332 : * sharing allowed
333 : * should result in sharing violation
334 : */
335 :
336 2 : static bool torture_smb2_rename_with_delete_access(struct torture_context *torture,
337 : struct smb2_tree *tree1)
338 : {
339 2 : bool ret = true;
340 0 : NTSTATUS status;
341 0 : union smb_open io;
342 0 : union smb_close cl;
343 0 : union smb_setfileinfo sinfo;
344 0 : struct smb2_handle fh, dh;
345 :
346 2 : ZERO_STRUCT(fh);
347 2 : ZERO_STRUCT(dh);
348 :
349 2 : smb2_deltree(tree1, BASEDIR);
350 2 : smb2_util_rmdir(tree1, BASEDIR);
351 :
352 2 : torture_comment(torture, "Creating base directory\n");
353 :
354 2 : smb2_util_mkdir(tree1, BASEDIR);
355 :
356 2 : torture_comment(torture, "Opening parent directory\n");
357 :
358 2 : ZERO_STRUCT(io.smb2);
359 2 : io.generic.level = RAW_OPEN_SMB2;
360 2 : io.smb2.in.create_flags = 0;
361 2 : io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
362 : SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
363 : SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
364 : SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
365 : SEC_FILE_WRITE_DATA;
366 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
367 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
368 2 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
369 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
370 2 : io.smb2.in.alloc_size = 0;
371 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
372 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
373 2 : io.smb2.in.security_flags = 0;
374 2 : io.smb2.in.fname = BASEDIR;
375 :
376 2 : status = smb2_create(tree1, torture, &(io.smb2));
377 2 : CHECK_STATUS(status, NT_STATUS_OK);
378 2 : dh = io.smb2.out.file.handle;
379 :
380 :
381 2 : torture_comment(torture, "Creating test file\n");
382 :
383 2 : ZERO_STRUCT(io.smb2);
384 2 : io.generic.level = RAW_OPEN_SMB2;
385 2 : io.smb2.in.create_flags = 0;
386 2 : io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
387 : SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
388 : SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
389 : SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
390 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
391 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
392 2 : io.smb2.in.share_access = 0;
393 2 : io.smb2.in.alloc_size = 0;
394 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
395 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
396 2 : io.smb2.in.security_flags = 0;
397 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
398 :
399 2 : status = smb2_create(tree1, torture, &(io.smb2));
400 2 : CHECK_STATUS(status, NT_STATUS_OK);
401 2 : fh = io.smb2.out.file.handle;
402 :
403 2 : torture_comment(torture, "Renaming test file\n");
404 :
405 2 : ZERO_STRUCT(sinfo);
406 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
407 2 : sinfo.rename_information.in.file.handle = fh;
408 2 : sinfo.rename_information.in.overwrite = 0;
409 2 : sinfo.rename_information.in.root_fid = 0;
410 2 : sinfo.rename_information.in.new_name =
411 : BASEDIR "\\newname.txt";
412 2 : status = smb2_setinfo_file(tree1, &sinfo);
413 2 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
414 :
415 2 : torture_comment(torture, "Closing test file\n");
416 :
417 2 : ZERO_STRUCT(cl.smb2);
418 2 : cl.smb2.level = RAW_CLOSE_SMB2;
419 2 : cl.smb2.in.file.handle = fh;
420 2 : status = smb2_close(tree1, &(cl.smb2));
421 2 : CHECK_STATUS(status, NT_STATUS_OK);
422 :
423 2 : ZERO_STRUCT(fh);
424 :
425 2 : torture_comment(torture, "Closing directory\n");
426 :
427 2 : ZERO_STRUCT(cl.smb2);
428 2 : cl.smb2.level = RAW_CLOSE_SMB2;
429 2 : cl.smb2.in.file.handle = dh;
430 2 : status = smb2_close(tree1, &(cl.smb2));
431 2 : CHECK_STATUS(status, NT_STATUS_OK);
432 :
433 2 : ZERO_STRUCT(dh);
434 :
435 :
436 2 : done:
437 :
438 2 : torture_comment(torture, "Cleaning up\n");
439 :
440 2 : if (fh.data[0] || fh.data[1]) {
441 0 : ZERO_STRUCT(cl.smb2);
442 0 : cl.smb2.level = RAW_CLOSE_SMB2;
443 0 : cl.smb2.in.file.handle = fh;
444 0 : status = smb2_close(tree1, &(cl.smb2));
445 : }
446 2 : if (dh.data[0] || dh.data[1]) {
447 0 : ZERO_STRUCT(cl.smb2);
448 0 : cl.smb2.level = RAW_CLOSE_SMB2;
449 0 : cl.smb2.in.file.handle = dh;
450 0 : status = smb2_close(tree1, &(cl.smb2));
451 : }
452 :
453 2 : smb2_deltree(tree1, BASEDIR);
454 2 : return ret;
455 : }
456 :
457 :
458 : /*
459 : * testing of rename with delete access on parent dir
460 : * this is a variation of the test above: parent dir is opened
461 : * without share_delete, so rename must fail
462 : */
463 :
464 2 : static bool torture_smb2_rename_with_delete_access2(struct torture_context *torture,
465 : struct smb2_tree *tree1)
466 : {
467 2 : bool ret = true;
468 0 : NTSTATUS status;
469 0 : union smb_open io;
470 0 : union smb_close cl;
471 0 : union smb_setfileinfo sinfo;
472 0 : struct smb2_handle fh, dh;
473 :
474 2 : ZERO_STRUCT(fh);
475 2 : ZERO_STRUCT(dh);
476 :
477 2 : smb2_deltree(tree1, BASEDIR);
478 2 : smb2_util_rmdir(tree1, BASEDIR);
479 :
480 2 : torture_comment(torture, "Creating base directory\n");
481 :
482 2 : smb2_util_mkdir(tree1, BASEDIR);
483 :
484 2 : torture_comment(torture, "Opening parent directory\n");
485 :
486 2 : ZERO_STRUCT(io.smb2);
487 2 : io.generic.level = RAW_OPEN_SMB2;
488 2 : io.smb2.in.create_flags = 0;
489 2 : io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
490 : SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
491 : SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
492 : SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
493 : SEC_FILE_WRITE_DATA;
494 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
495 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
496 2 : io.smb2.in.share_access = 0;
497 2 : io.smb2.in.alloc_size = 0;
498 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
499 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
500 2 : io.smb2.in.security_flags = 0;
501 2 : io.smb2.in.fname = BASEDIR;
502 :
503 2 : status = smb2_create(tree1, torture, &(io.smb2));
504 2 : CHECK_STATUS(status, NT_STATUS_OK);
505 2 : dh = io.smb2.out.file.handle;
506 :
507 :
508 2 : torture_comment(torture, "Creating test file\n");
509 :
510 2 : ZERO_STRUCT(io.smb2);
511 2 : io.generic.level = RAW_OPEN_SMB2;
512 2 : io.smb2.in.create_flags = 0;
513 2 : io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
514 : SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
515 : SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
516 : SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
517 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
518 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
519 2 : io.smb2.in.share_access = 0;
520 2 : io.smb2.in.alloc_size = 0;
521 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
522 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
523 2 : io.smb2.in.security_flags = 0;
524 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
525 :
526 2 : status = smb2_create(tree1, torture, &(io.smb2));
527 2 : CHECK_STATUS(status, NT_STATUS_OK);
528 2 : fh = io.smb2.out.file.handle;
529 :
530 2 : torture_comment(torture, "Renaming test file\n");
531 :
532 2 : ZERO_STRUCT(sinfo);
533 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
534 2 : sinfo.rename_information.in.file.handle = fh;
535 2 : sinfo.rename_information.in.overwrite = 0;
536 2 : sinfo.rename_information.in.root_fid = 0;
537 2 : sinfo.rename_information.in.new_name =
538 : BASEDIR "\\newname.txt";
539 2 : status = smb2_setinfo_file(tree1, &sinfo);
540 2 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
541 :
542 2 : torture_comment(torture, "Closing test file\n");
543 :
544 2 : ZERO_STRUCT(cl.smb2);
545 2 : cl.smb2.level = RAW_CLOSE_SMB2;
546 2 : cl.smb2.in.file.handle = fh;
547 2 : status = smb2_close(tree1, &(cl.smb2));
548 2 : CHECK_STATUS(status, NT_STATUS_OK);
549 :
550 2 : ZERO_STRUCT(fh);
551 :
552 2 : torture_comment(torture, "Closing directory\n");
553 :
554 2 : ZERO_STRUCT(cl.smb2);
555 2 : cl.smb2.level = RAW_CLOSE_SMB2;
556 2 : cl.smb2.in.file.handle = dh;
557 2 : status = smb2_close(tree1, &(cl.smb2));
558 2 : CHECK_STATUS(status, NT_STATUS_OK);
559 :
560 2 : ZERO_STRUCT(dh);
561 :
562 :
563 2 : done:
564 :
565 2 : torture_comment(torture, "Cleaning up\n");
566 :
567 2 : if (fh.data[0] || fh.data[1]) {
568 0 : ZERO_STRUCT(cl.smb2);
569 0 : cl.smb2.level = RAW_CLOSE_SMB2;
570 0 : cl.smb2.in.file.handle = fh;
571 0 : status = smb2_close(tree1, &(cl.smb2));
572 : }
573 2 : if (dh.data[0] || dh.data[1]) {
574 0 : ZERO_STRUCT(cl.smb2);
575 0 : cl.smb2.level = RAW_CLOSE_SMB2;
576 0 : cl.smb2.in.file.handle = dh;
577 0 : status = smb2_close(tree1, &(cl.smb2));
578 : }
579 :
580 2 : smb2_deltree(tree1, BASEDIR);
581 2 : return ret;
582 : }
583 :
584 : /*
585 : * testing of rename when opening parent dir with no delete access and delete
586 : * sharing allowed
587 : * this should pass
588 : */
589 :
590 2 : static bool torture_smb2_rename_no_delete_access(struct torture_context *torture,
591 : struct smb2_tree *tree1)
592 : {
593 2 : bool ret = true;
594 0 : NTSTATUS status;
595 0 : union smb_open io;
596 0 : union smb_close cl;
597 0 : union smb_setfileinfo sinfo;
598 0 : union smb_fileinfo fi;
599 0 : struct smb2_handle fh, dh;
600 :
601 2 : ZERO_STRUCT(fh);
602 2 : ZERO_STRUCT(dh);
603 :
604 2 : smb2_deltree(tree1, BASEDIR);
605 2 : smb2_util_rmdir(tree1, BASEDIR);
606 :
607 2 : torture_comment(torture, "Creating base directory\n");
608 :
609 2 : smb2_util_mkdir(tree1, BASEDIR);
610 :
611 2 : torture_comment(torture, "Opening parent directory\n");
612 :
613 2 : ZERO_STRUCT(io.smb2);
614 2 : io.generic.level = RAW_OPEN_SMB2;
615 2 : io.smb2.in.create_flags = 0;
616 2 : io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
617 : SEC_STD_READ_CONTROL | SEC_FILE_WRITE_ATTRIBUTE |
618 : SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
619 : SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
620 : SEC_FILE_WRITE_DATA;
621 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
622 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
623 2 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
624 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
625 2 : io.smb2.in.alloc_size = 0;
626 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
627 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
628 2 : io.smb2.in.security_flags = 0;
629 2 : io.smb2.in.fname = BASEDIR;
630 :
631 2 : status = smb2_create(tree1, torture, &(io.smb2));
632 2 : CHECK_STATUS(status, NT_STATUS_OK);
633 2 : dh = io.smb2.out.file.handle;
634 :
635 :
636 2 : torture_comment(torture, "Creating test file\n");
637 :
638 2 : ZERO_STRUCT(io.smb2);
639 2 : io.generic.level = RAW_OPEN_SMB2;
640 2 : io.smb2.in.create_flags = 0;
641 2 : io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
642 : SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
643 : SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
644 : SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
645 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
646 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
647 2 : io.smb2.in.share_access = 0;
648 2 : io.smb2.in.alloc_size = 0;
649 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
650 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
651 2 : io.smb2.in.security_flags = 0;
652 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
653 :
654 2 : status = smb2_create(tree1, torture, &(io.smb2));
655 2 : CHECK_STATUS(status, NT_STATUS_OK);
656 2 : fh = io.smb2.out.file.handle;
657 :
658 2 : torture_comment(torture, "Renaming test file\n");
659 :
660 2 : ZERO_STRUCT(sinfo);
661 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
662 2 : sinfo.rename_information.in.file.handle = fh;
663 2 : sinfo.rename_information.in.overwrite = 0;
664 2 : sinfo.rename_information.in.root_fid = 0;
665 2 : sinfo.rename_information.in.new_name =
666 : BASEDIR "\\newname.txt";
667 2 : status = smb2_setinfo_file(tree1, &sinfo);
668 2 : CHECK_STATUS(status, NT_STATUS_OK);
669 :
670 2 : torture_comment(torture, "Checking for new filename\n");
671 :
672 2 : ZERO_STRUCT(fi);
673 2 : fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
674 2 : fi.generic.in.file.handle = fh;
675 2 : status = smb2_getinfo_file(tree1, torture, &fi);
676 2 : CHECK_STATUS(status, NT_STATUS_OK);
677 :
678 :
679 2 : torture_comment(torture, "Closing test file\n");
680 :
681 2 : ZERO_STRUCT(cl.smb2);
682 2 : cl.smb2.level = RAW_CLOSE_SMB2;
683 2 : cl.smb2.in.file.handle = fh;
684 2 : status = smb2_close(tree1, &(cl.smb2));
685 2 : CHECK_STATUS(status, NT_STATUS_OK);
686 :
687 2 : ZERO_STRUCT(fh);
688 :
689 2 : torture_comment(torture, "Closing directory\n");
690 :
691 2 : ZERO_STRUCT(cl.smb2);
692 2 : cl.smb2.level = RAW_CLOSE_SMB2;
693 2 : cl.smb2.in.file.handle = dh;
694 2 : status = smb2_close(tree1, &(cl.smb2));
695 2 : CHECK_STATUS(status, NT_STATUS_OK);
696 :
697 2 : ZERO_STRUCT(dh);
698 :
699 :
700 2 : done:
701 :
702 2 : torture_comment(torture, "Cleaning up\n");
703 :
704 2 : if (fh.data[0] || fh.data[1]) {
705 0 : ZERO_STRUCT(cl.smb2);
706 0 : cl.smb2.level = RAW_CLOSE_SMB2;
707 0 : cl.smb2.in.file.handle = fh;
708 0 : status = smb2_close(tree1, &(cl.smb2));
709 : }
710 2 : if (dh.data[0] || dh.data[1]) {
711 0 : ZERO_STRUCT(cl.smb2);
712 0 : cl.smb2.level = RAW_CLOSE_SMB2;
713 0 : cl.smb2.in.file.handle = dh;
714 0 : status = smb2_close(tree1, &(cl.smb2));
715 : }
716 :
717 2 : smb2_deltree(tree1, BASEDIR);
718 2 : return ret;
719 : }
720 :
721 :
722 : /*
723 : * testing of rename with no delete access on parent dir
724 : * this is the negative case of the test above: parent dir is opened
725 : * without share_delete, so rename must fail
726 : */
727 :
728 2 : static bool torture_smb2_rename_no_delete_access2(struct torture_context *torture,
729 : struct smb2_tree *tree1)
730 : {
731 2 : bool ret = true;
732 0 : NTSTATUS status;
733 0 : union smb_open io;
734 0 : union smb_close cl;
735 0 : union smb_setfileinfo sinfo;
736 0 : struct smb2_handle fh, dh;
737 :
738 2 : ZERO_STRUCT(fh);
739 2 : ZERO_STRUCT(dh);
740 :
741 2 : smb2_deltree(tree1, BASEDIR);
742 2 : smb2_util_rmdir(tree1, BASEDIR);
743 :
744 2 : torture_comment(torture, "Creating base directory\n");
745 :
746 2 : smb2_util_mkdir(tree1, BASEDIR);
747 :
748 2 : torture_comment(torture, "Opening parent directory\n");
749 :
750 2 : ZERO_STRUCT(io.smb2);
751 2 : io.generic.level = RAW_OPEN_SMB2;
752 2 : io.smb2.in.create_flags = 0;
753 2 : io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
754 : SEC_STD_READ_CONTROL | SEC_FILE_WRITE_ATTRIBUTE |
755 : SEC_FILE_READ_ATTRIBUTE | SEC_FILE_EXECUTE | SEC_FILE_WRITE_EA |
756 : SEC_FILE_READ_EA | SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA |
757 : SEC_FILE_WRITE_DATA;
758 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
759 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
760 2 : io.smb2.in.share_access = 0;
761 2 : io.smb2.in.alloc_size = 0;
762 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
763 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
764 2 : io.smb2.in.security_flags = 0;
765 2 : io.smb2.in.fname = BASEDIR;
766 :
767 2 : status = smb2_create(tree1, torture, &(io.smb2));
768 2 : CHECK_STATUS(status, NT_STATUS_OK);
769 2 : dh = io.smb2.out.file.handle;
770 :
771 :
772 2 : torture_comment(torture, "Creating test file\n");
773 :
774 2 : ZERO_STRUCT(io.smb2);
775 2 : io.generic.level = RAW_OPEN_SMB2;
776 2 : io.smb2.in.create_flags = 0;
777 2 : io.smb2.in.desired_access = SEC_STD_SYNCHRONIZE | SEC_STD_WRITE_DAC |
778 : SEC_STD_READ_CONTROL | SEC_STD_DELETE | SEC_FILE_WRITE_ATTRIBUTE |
779 : SEC_FILE_READ_ATTRIBUTE | SEC_FILE_WRITE_EA | SEC_FILE_READ_EA |
780 : SEC_FILE_APPEND_DATA | SEC_FILE_READ_DATA | SEC_FILE_WRITE_DATA;
781 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
782 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
783 2 : io.smb2.in.share_access = 0;
784 2 : io.smb2.in.alloc_size = 0;
785 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
786 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
787 2 : io.smb2.in.security_flags = 0;
788 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
789 :
790 2 : status = smb2_create(tree1, torture, &(io.smb2));
791 2 : CHECK_STATUS(status, NT_STATUS_OK);
792 2 : fh = io.smb2.out.file.handle;
793 :
794 2 : torture_comment(torture, "Renaming test file\n");
795 :
796 2 : ZERO_STRUCT(sinfo);
797 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
798 2 : sinfo.rename_information.in.file.handle = fh;
799 2 : sinfo.rename_information.in.overwrite = 0;
800 2 : sinfo.rename_information.in.root_fid = 0;
801 2 : sinfo.rename_information.in.new_name =
802 : BASEDIR "\\newname.txt";
803 2 : status = smb2_setinfo_file(tree1, &sinfo);
804 2 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
805 :
806 0 : torture_comment(torture, "Closing test file\n");
807 :
808 0 : ZERO_STRUCT(cl.smb2);
809 0 : cl.smb2.level = RAW_CLOSE_SMB2;
810 0 : cl.smb2.in.file.handle = fh;
811 0 : status = smb2_close(tree1, &(cl.smb2));
812 0 : CHECK_STATUS(status, NT_STATUS_OK);
813 :
814 0 : ZERO_STRUCT(fh);
815 :
816 0 : torture_comment(torture, "Closing directory\n");
817 :
818 0 : ZERO_STRUCT(cl.smb2);
819 0 : cl.smb2.level = RAW_CLOSE_SMB2;
820 0 : cl.smb2.in.file.handle = dh;
821 0 : status = smb2_close(tree1, &(cl.smb2));
822 0 : CHECK_STATUS(status, NT_STATUS_OK);
823 :
824 0 : ZERO_STRUCT(dh);
825 :
826 :
827 2 : done:
828 :
829 2 : torture_comment(torture, "Cleaning up\n");
830 :
831 2 : if (fh.data[0] || fh.data[1]) {
832 2 : ZERO_STRUCT(cl.smb2);
833 2 : cl.smb2.level = RAW_CLOSE_SMB2;
834 2 : cl.smb2.in.file.handle = fh;
835 2 : status = smb2_close(tree1, &(cl.smb2));
836 : }
837 2 : if (dh.data[0] || dh.data[1]) {
838 2 : ZERO_STRUCT(cl.smb2);
839 2 : cl.smb2.level = RAW_CLOSE_SMB2;
840 2 : cl.smb2.in.file.handle = dh;
841 2 : status = smb2_close(tree1, &(cl.smb2));
842 : }
843 :
844 2 : smb2_deltree(tree1, BASEDIR);
845 2 : return ret;
846 : }
847 :
848 : /*
849 : * this is a replay of how Word 2010 saves a file
850 : * this should pass
851 : */
852 :
853 2 : static bool torture_smb2_rename_msword(struct torture_context *torture,
854 : struct smb2_tree *tree1)
855 : {
856 2 : bool ret = true;
857 0 : NTSTATUS status;
858 0 : union smb_open io;
859 0 : union smb_close cl;
860 0 : union smb_setfileinfo sinfo;
861 0 : union smb_fileinfo fi;
862 0 : struct smb2_handle fh, dh;
863 :
864 2 : ZERO_STRUCT(fh);
865 2 : ZERO_STRUCT(dh);
866 :
867 2 : smb2_deltree(tree1, BASEDIR);
868 2 : smb2_util_rmdir(tree1, BASEDIR);
869 :
870 2 : torture_comment(torture, "Creating base directory\n");
871 :
872 2 : smb2_util_mkdir(tree1, BASEDIR);
873 :
874 2 : torture_comment(torture, "Creating test file\n");
875 :
876 2 : ZERO_STRUCT(io.smb2);
877 2 : io.generic.level = RAW_OPEN_SMB2;
878 2 : io.smb2.in.create_flags = 0;
879 2 : io.smb2.in.desired_access = 0x0017019f;
880 2 : io.smb2.in.create_options = 0x60;
881 2 : io.smb2.in.file_attributes = 0;
882 2 : io.smb2.in.share_access = 0;
883 2 : io.smb2.in.alloc_size = 0;
884 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
885 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
886 2 : io.smb2.in.security_flags = 0;
887 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
888 :
889 2 : status = smb2_create(tree1, torture, &(io.smb2));
890 2 : CHECK_STATUS(status, NT_STATUS_OK);
891 2 : fh = io.smb2.out.file.handle;
892 :
893 2 : torture_comment(torture, "Opening parent directory\n");
894 :
895 2 : ZERO_STRUCT(io.smb2);
896 2 : io.generic.level = RAW_OPEN_SMB2;
897 2 : io.smb2.in.create_flags = 0;
898 2 : io.smb2.in.desired_access = 0x00100080;
899 2 : io.smb2.in.create_options = 0x00800021;
900 2 : io.smb2.in.file_attributes = 0;
901 2 : io.smb2.in.share_access = 0;
902 2 : io.smb2.in.alloc_size = 0;
903 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
904 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
905 2 : io.smb2.in.security_flags = 0;
906 2 : io.smb2.in.fname = BASEDIR;
907 :
908 2 : status = smb2_create(tree1, torture, &(io.smb2));
909 2 : CHECK_STATUS(status, NT_STATUS_OK);
910 2 : dh = io.smb2.out.file.handle;
911 :
912 2 : torture_comment(torture, "Renaming test file\n");
913 :
914 2 : ZERO_STRUCT(sinfo);
915 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
916 2 : sinfo.rename_information.in.file.handle = fh;
917 2 : sinfo.rename_information.in.overwrite = 0;
918 2 : sinfo.rename_information.in.root_fid = 0;
919 2 : sinfo.rename_information.in.new_name =
920 : BASEDIR "\\newname.txt";
921 2 : status = smb2_setinfo_file(tree1, &sinfo);
922 2 : CHECK_STATUS(status, NT_STATUS_OK);
923 :
924 2 : torture_comment(torture, "Checking for new filename\n");
925 :
926 2 : ZERO_STRUCT(fi);
927 2 : fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
928 2 : fi.generic.in.file.handle = fh;
929 2 : status = smb2_getinfo_file(tree1, torture, &fi);
930 2 : CHECK_STATUS(status, NT_STATUS_OK);
931 :
932 :
933 2 : torture_comment(torture, "Closing test file\n");
934 :
935 2 : ZERO_STRUCT(cl.smb2);
936 2 : cl.smb2.level = RAW_CLOSE_SMB2;
937 2 : cl.smb2.in.file.handle = fh;
938 2 : status = smb2_close(tree1, &(cl.smb2));
939 2 : CHECK_STATUS(status, NT_STATUS_OK);
940 :
941 2 : ZERO_STRUCT(fh);
942 :
943 2 : torture_comment(torture, "Closing directory\n");
944 :
945 2 : ZERO_STRUCT(cl.smb2);
946 2 : cl.smb2.level = RAW_CLOSE_SMB2;
947 2 : cl.smb2.in.file.handle = dh;
948 2 : status = smb2_close(tree1, &(cl.smb2));
949 2 : CHECK_STATUS(status, NT_STATUS_OK);
950 :
951 2 : ZERO_STRUCT(dh);
952 :
953 :
954 2 : done:
955 :
956 2 : torture_comment(torture, "Cleaning up\n");
957 :
958 2 : if (fh.data[0] || fh.data[1]) {
959 0 : ZERO_STRUCT(cl.smb2);
960 0 : cl.smb2.level = RAW_CLOSE_SMB2;
961 0 : cl.smb2.in.file.handle = fh;
962 0 : status = smb2_close(tree1, &(cl.smb2));
963 : }
964 2 : if (dh.data[0] || dh.data[1]) {
965 0 : ZERO_STRUCT(cl.smb2);
966 0 : cl.smb2.level = RAW_CLOSE_SMB2;
967 0 : cl.smb2.in.file.handle = dh;
968 0 : status = smb2_close(tree1, &(cl.smb2));
969 : }
970 :
971 2 : smb2_deltree(tree1, BASEDIR);
972 2 : return ret;
973 : }
974 :
975 2 : static bool torture_smb2_rename_dir_openfile(struct torture_context *torture,
976 : struct smb2_tree *tree1)
977 : {
978 2 : bool ret = true;
979 0 : NTSTATUS status;
980 0 : union smb_open io;
981 0 : union smb_close cl;
982 0 : union smb_setfileinfo sinfo;
983 0 : struct smb2_handle d1, h1;
984 :
985 2 : ZERO_STRUCT(d1);
986 2 : ZERO_STRUCT(h1);
987 :
988 2 : smb2_deltree(tree1, BASEDIR);
989 2 : smb2_util_rmdir(tree1, BASEDIR);
990 :
991 2 : torture_comment(torture, "Creating base directory\n");
992 :
993 2 : ZERO_STRUCT(io.smb2);
994 2 : io.generic.level = RAW_OPEN_SMB2;
995 2 : io.smb2.in.create_flags = 0;
996 2 : io.smb2.in.desired_access = 0x0017019f;
997 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
998 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
999 2 : io.smb2.in.share_access = 0;
1000 2 : io.smb2.in.alloc_size = 0;
1001 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1002 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1003 2 : io.smb2.in.security_flags = 0;
1004 2 : io.smb2.in.fname = BASEDIR;
1005 :
1006 2 : status = smb2_create(tree1, torture, &(io.smb2));
1007 2 : CHECK_STATUS(status, NT_STATUS_OK);
1008 2 : d1 = io.smb2.out.file.handle;
1009 :
1010 2 : torture_comment(torture, "Creating test file\n");
1011 :
1012 2 : ZERO_STRUCT(io.smb2);
1013 2 : io.generic.level = RAW_OPEN_SMB2;
1014 2 : io.smb2.in.create_flags = 0;
1015 2 : io.smb2.in.desired_access = 0x0017019f;
1016 2 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1017 2 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1018 2 : io.smb2.in.share_access = 0;
1019 2 : io.smb2.in.alloc_size = 0;
1020 2 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1021 2 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1022 2 : io.smb2.in.security_flags = 0;
1023 2 : io.smb2.in.fname = BASEDIR "\\file.txt";
1024 :
1025 2 : status = smb2_create(tree1, torture, &(io.smb2));
1026 2 : CHECK_STATUS(status, NT_STATUS_OK);
1027 2 : h1 = io.smb2.out.file.handle;
1028 :
1029 2 : torture_comment(torture, "Renaming directory\n");
1030 :
1031 2 : ZERO_STRUCT(sinfo);
1032 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
1033 2 : sinfo.rename_information.in.file.handle = d1;
1034 2 : sinfo.rename_information.in.overwrite = 0;
1035 2 : sinfo.rename_information.in.root_fid = 0;
1036 2 : sinfo.rename_information.in.new_name =
1037 : BASEDIR "-new";
1038 2 : status = smb2_setinfo_file(tree1, &sinfo);
1039 2 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1040 :
1041 2 : torture_comment(torture, "Closing directory\n");
1042 :
1043 2 : ZERO_STRUCT(cl.smb2);
1044 2 : cl.smb2.level = RAW_CLOSE_SMB2;
1045 2 : cl.smb2.in.file.handle = d1;
1046 2 : status = smb2_close(tree1, &(cl.smb2));
1047 2 : CHECK_STATUS(status, NT_STATUS_OK);
1048 2 : ZERO_STRUCT(d1);
1049 :
1050 2 : torture_comment(torture, "Closing test file\n");
1051 :
1052 2 : cl.smb2.in.file.handle = h1;
1053 2 : status = smb2_close(tree1, &(cl.smb2));
1054 2 : CHECK_STATUS(status, NT_STATUS_OK);
1055 2 : ZERO_STRUCT(h1);
1056 :
1057 2 : done:
1058 :
1059 2 : torture_comment(torture, "Cleaning up\n");
1060 :
1061 2 : if (h1.data[0] || h1.data[1]) {
1062 0 : ZERO_STRUCT(cl.smb2);
1063 0 : cl.smb2.level = RAW_CLOSE_SMB2;
1064 0 : cl.smb2.in.file.handle = h1;
1065 0 : status = smb2_close(tree1, &(cl.smb2));
1066 : }
1067 2 : smb2_deltree(tree1, BASEDIR);
1068 2 : return ret;
1069 : }
1070 :
1071 : struct rename_one_dir_cycle_state {
1072 : struct tevent_context *ev;
1073 : struct smb2_tree *tree;
1074 : struct smb2_handle file;
1075 : const char *base_name;
1076 : char *new_name;
1077 : unsigned *rename_counter;
1078 :
1079 : unsigned current;
1080 : unsigned max;
1081 : union smb_setfileinfo sinfo;
1082 : };
1083 :
1084 : static void rename_one_dir_cycle_done(struct smb2_request *subreq);
1085 :
1086 6 : static struct tevent_req *rename_one_dir_cycle_send(TALLOC_CTX *mem_ctx,
1087 : struct tevent_context *ev,
1088 : struct smb2_tree *tree,
1089 : struct smb2_handle file,
1090 : unsigned max_renames,
1091 : const char *base_name,
1092 : unsigned *rename_counter)
1093 : {
1094 0 : struct tevent_req *req;
1095 0 : struct rename_one_dir_cycle_state *state;
1096 0 : struct smb2_request *subreq;
1097 :
1098 6 : req = tevent_req_create(mem_ctx, &state,
1099 : struct rename_one_dir_cycle_state);
1100 6 : if (req == NULL) {
1101 0 : return NULL;
1102 : }
1103 6 : state->ev = ev;
1104 6 : state->tree = tree;
1105 6 : state->file = file;
1106 6 : state->base_name = base_name;
1107 6 : state->rename_counter = rename_counter;
1108 6 : state->current = 0;
1109 6 : state->max = max_renames;
1110 :
1111 6 : ZERO_STRUCT(state->sinfo);
1112 6 : state->sinfo.rename_information.level =
1113 : RAW_SFILEINFO_RENAME_INFORMATION;
1114 6 : state->sinfo.rename_information.in.file.handle = state->file;
1115 6 : state->sinfo.rename_information.in.overwrite = 0;
1116 6 : state->sinfo.rename_information.in.root_fid = 0;
1117 :
1118 12 : state->new_name = talloc_asprintf(
1119 6 : state, "%s-%u", state->base_name, state->current);
1120 6 : if (tevent_req_nomem(state->new_name, req)) {
1121 0 : return tevent_req_post(req, ev);
1122 : }
1123 6 : state->sinfo.rename_information.in.new_name = state->new_name;
1124 :
1125 6 : subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
1126 6 : if (tevent_req_nomem(subreq, req)) {
1127 0 : return tevent_req_post(req, ev);
1128 : }
1129 6 : subreq->async.fn = rename_one_dir_cycle_done;
1130 6 : subreq->async.private_data = req;
1131 6 : return req;
1132 : }
1133 :
1134 60 : static void rename_one_dir_cycle_done(struct smb2_request *subreq)
1135 : {
1136 60 : struct tevent_req *req = talloc_get_type_abort(
1137 : subreq->async.private_data, struct tevent_req);
1138 60 : struct rename_one_dir_cycle_state *state = tevent_req_data(
1139 : req, struct rename_one_dir_cycle_state);
1140 0 : NTSTATUS status;
1141 :
1142 60 : status = smb2_setinfo_recv(subreq);
1143 60 : if (tevent_req_nterror(req, status)) {
1144 6 : return;
1145 : }
1146 60 : TALLOC_FREE(state->new_name);
1147 :
1148 60 : *state->rename_counter += 1;
1149 :
1150 60 : state->current += 1;
1151 60 : if (state->current >= state->max) {
1152 6 : tevent_req_done(req);
1153 6 : return;
1154 : }
1155 :
1156 54 : ZERO_STRUCT(state->sinfo);
1157 54 : state->sinfo.rename_information.level =
1158 : RAW_SFILEINFO_RENAME_INFORMATION;
1159 54 : state->sinfo.rename_information.in.file.handle = state->file;
1160 54 : state->sinfo.rename_information.in.overwrite = 0;
1161 54 : state->sinfo.rename_information.in.root_fid = 0;
1162 :
1163 54 : state->new_name = talloc_asprintf(
1164 : state, "%s-%u", state->base_name, state->current);
1165 54 : if (tevent_req_nomem(state->new_name, req)) {
1166 0 : return;
1167 : }
1168 54 : state->sinfo.rename_information.in.new_name = state->new_name;
1169 :
1170 54 : subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
1171 54 : if (tevent_req_nomem(subreq, req)) {
1172 0 : return;
1173 : }
1174 54 : subreq->async.fn = rename_one_dir_cycle_done;
1175 54 : subreq->async.private_data = req;
1176 : }
1177 :
1178 6 : static NTSTATUS rename_one_dir_cycle_recv(struct tevent_req *req)
1179 : {
1180 6 : return tevent_req_simple_recv_ntstatus(req);
1181 : }
1182 :
1183 : struct rename_dir_bench_state {
1184 : struct tevent_context *ev;
1185 : struct smb2_tree *tree;
1186 : const char *base_name;
1187 : unsigned max_renames;
1188 : unsigned *rename_counter;
1189 :
1190 : struct smb2_create io;
1191 : union smb_setfileinfo sinfo;
1192 : struct smb2_close cl;
1193 :
1194 : struct smb2_handle file;
1195 : };
1196 :
1197 : static void rename_dir_bench_opened(struct smb2_request *subreq);
1198 : static void rename_dir_bench_renamed(struct tevent_req *subreq);
1199 : static void rename_dir_bench_set_doc(struct smb2_request *subreq);
1200 : static void rename_dir_bench_closed(struct smb2_request *subreq);
1201 :
1202 6 : static struct tevent_req *rename_dir_bench_send(TALLOC_CTX *mem_ctx,
1203 : struct tevent_context *ev,
1204 : struct smb2_tree *tree,
1205 : const char *base_name,
1206 : unsigned max_renames,
1207 : unsigned *rename_counter)
1208 : {
1209 0 : struct tevent_req *req;
1210 0 : struct rename_dir_bench_state *state;
1211 0 : struct smb2_request *subreq;
1212 :
1213 6 : req = tevent_req_create(mem_ctx, &state,
1214 : struct rename_dir_bench_state);
1215 6 : if (req == NULL) {
1216 0 : return NULL;
1217 : }
1218 6 : state->ev = ev;
1219 6 : state->tree = tree;
1220 6 : state->base_name = base_name;
1221 6 : state->max_renames = max_renames;
1222 6 : state->rename_counter = rename_counter;
1223 :
1224 6 : ZERO_STRUCT(state->io);
1225 6 : state->io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1226 6 : state->io.in.share_access =
1227 : NTCREATEX_SHARE_ACCESS_READ|
1228 : NTCREATEX_SHARE_ACCESS_WRITE;
1229 6 : state->io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1230 6 : state->io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1231 6 : state->io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1232 6 : state->io.in.fname = state->base_name;
1233 :
1234 6 : subreq = smb2_create_send(state->tree, &state->io);
1235 6 : if (tevent_req_nomem(subreq, req)) {
1236 0 : return tevent_req_post(req, ev);
1237 : }
1238 6 : subreq->async.fn = rename_dir_bench_opened;
1239 6 : subreq->async.private_data = req;
1240 6 : return req;
1241 : }
1242 :
1243 6 : static void rename_dir_bench_opened(struct smb2_request *subreq)
1244 : {
1245 6 : struct tevent_req *req = talloc_get_type_abort(
1246 : subreq->async.private_data, struct tevent_req);
1247 6 : struct rename_dir_bench_state *state = tevent_req_data(
1248 : req, struct rename_dir_bench_state);
1249 0 : struct smb2_create *io;
1250 0 : struct tevent_req *subreq2;
1251 0 : NTSTATUS status;
1252 :
1253 6 : io = talloc(state, struct smb2_create);
1254 6 : if (tevent_req_nomem(io, req)) {
1255 0 : return;
1256 : }
1257 :
1258 6 : status = smb2_create_recv(subreq, io, io);
1259 6 : if (tevent_req_nterror(req, status)) {
1260 0 : return;
1261 : }
1262 6 : state->file = io->out.file.handle;
1263 6 : TALLOC_FREE(io);
1264 :
1265 6 : subreq2 = rename_one_dir_cycle_send(
1266 : state, state->ev, state->tree, state->file,
1267 : state->max_renames, state->base_name,
1268 : state->rename_counter);
1269 6 : if (tevent_req_nomem(subreq2, req)) {
1270 0 : return;
1271 : }
1272 6 : tevent_req_set_callback(subreq2, rename_dir_bench_renamed, req);
1273 : }
1274 :
1275 6 : static void rename_dir_bench_renamed(struct tevent_req *subreq)
1276 : {
1277 6 : struct tevent_req *req = tevent_req_callback_data(
1278 : subreq, struct tevent_req);
1279 6 : struct rename_dir_bench_state *state = tevent_req_data(
1280 : req, struct rename_dir_bench_state);
1281 0 : struct smb2_request *subreq2;
1282 0 : NTSTATUS status;
1283 :
1284 6 : status = rename_one_dir_cycle_recv(subreq);
1285 6 : TALLOC_FREE(subreq);
1286 6 : if (tevent_req_nterror(req, status)) {
1287 0 : return;
1288 : }
1289 :
1290 6 : ZERO_STRUCT(state->sinfo);
1291 6 : state->sinfo.disposition_info.level =
1292 : RAW_SFILEINFO_DISPOSITION_INFORMATION;
1293 6 : state->sinfo.disposition_info.in.file.handle = state->file;
1294 6 : state->sinfo.disposition_info.in.delete_on_close = true;
1295 :
1296 6 : subreq2 = smb2_setinfo_file_send(state->tree, &state->sinfo);
1297 6 : if (tevent_req_nomem(subreq2, req)) {
1298 0 : return;
1299 : }
1300 6 : subreq2->async.fn = rename_dir_bench_set_doc;
1301 6 : subreq2->async.private_data = req;
1302 : }
1303 :
1304 6 : static void rename_dir_bench_set_doc(struct smb2_request *subreq)
1305 : {
1306 6 : struct tevent_req *req = talloc_get_type_abort(
1307 : subreq->async.private_data, struct tevent_req);
1308 6 : struct rename_dir_bench_state *state = tevent_req_data(
1309 : req, struct rename_dir_bench_state);
1310 0 : NTSTATUS status;
1311 :
1312 6 : status = smb2_setinfo_recv(subreq);
1313 6 : if (tevent_req_nterror(req, status)) {
1314 0 : return;
1315 : }
1316 :
1317 6 : ZERO_STRUCT(state->cl);
1318 6 : state->cl.in.file.handle = state->file;
1319 :
1320 6 : subreq = smb2_close_send(state->tree, &state->cl);
1321 6 : if (tevent_req_nomem(subreq, req)) {
1322 0 : return;
1323 : }
1324 6 : subreq->async.fn = rename_dir_bench_closed;
1325 6 : subreq->async.private_data = req;
1326 : }
1327 :
1328 6 : static void rename_dir_bench_closed(struct smb2_request *subreq)
1329 : {
1330 6 : struct tevent_req *req = talloc_get_type_abort(
1331 : subreq->async.private_data, struct tevent_req);
1332 0 : struct smb2_close cl;
1333 0 : NTSTATUS status;
1334 :
1335 6 : status = smb2_close_recv(subreq, &cl);
1336 6 : if (tevent_req_nterror(req, status)) {
1337 0 : return;
1338 : }
1339 6 : tevent_req_done(req);
1340 : }
1341 :
1342 6 : static NTSTATUS rename_dir_bench_recv(struct tevent_req *req)
1343 : {
1344 6 : return tevent_req_simple_recv_ntstatus(req);
1345 : }
1346 :
1347 : struct rename_dirs_bench_state {
1348 : unsigned num_reqs;
1349 : unsigned num_done;
1350 : };
1351 :
1352 : static void rename_dirs_bench_done(struct tevent_req *subreq);
1353 :
1354 2 : static struct tevent_req *rename_dirs_bench_send(TALLOC_CTX *mem_ctx,
1355 : struct tevent_context *ev,
1356 : struct smb2_tree *tree,
1357 : const char *base_name,
1358 : unsigned num_parallel,
1359 : unsigned max_renames,
1360 : unsigned *rename_counter)
1361 : {
1362 0 : struct tevent_req *req;
1363 0 : struct rename_dirs_bench_state *state;
1364 0 : unsigned i;
1365 :
1366 2 : req = tevent_req_create(mem_ctx, &state,
1367 : struct rename_dirs_bench_state);
1368 2 : if (req == NULL) {
1369 0 : return NULL;
1370 : }
1371 2 : state->num_reqs = num_parallel;
1372 2 : state->num_done = 0;
1373 :
1374 8 : for (i=0; i<num_parallel; i++) {
1375 0 : struct tevent_req *subreq;
1376 0 : char *sub_base;
1377 :
1378 6 : sub_base = talloc_asprintf(state, "%s-%u", base_name, i);
1379 6 : if (tevent_req_nomem(sub_base, req)) {
1380 0 : return tevent_req_post(req, ev);
1381 : }
1382 :
1383 6 : subreq = rename_dir_bench_send(state, ev, tree, sub_base,
1384 : max_renames, rename_counter);
1385 6 : if (tevent_req_nomem(subreq, req)) {
1386 0 : return tevent_req_post(req, ev);
1387 : }
1388 6 : tevent_req_set_callback(subreq, rename_dirs_bench_done, req);
1389 : }
1390 2 : return req;
1391 : }
1392 :
1393 6 : static void rename_dirs_bench_done(struct tevent_req *subreq)
1394 : {
1395 6 : struct tevent_req *req = tevent_req_callback_data(
1396 : subreq, struct tevent_req);
1397 6 : struct rename_dirs_bench_state *state = tevent_req_data(
1398 : req, struct rename_dirs_bench_state);
1399 0 : NTSTATUS status;
1400 :
1401 6 : status = rename_dir_bench_recv(subreq);
1402 6 : TALLOC_FREE(subreq);
1403 6 : if (tevent_req_nterror(req, status)) {
1404 0 : return;
1405 : }
1406 :
1407 6 : state->num_done += 1;
1408 6 : if (state->num_done >= state->num_reqs) {
1409 2 : tevent_req_done(req);
1410 : }
1411 : }
1412 :
1413 2 : static NTSTATUS rename_dirs_bench_recv(struct tevent_req *req)
1414 : {
1415 2 : return tevent_req_simple_recv_ntstatus(req);
1416 : }
1417 :
1418 2 : static bool torture_smb2_rename_dir_bench(struct torture_context *tctx,
1419 : struct smb2_tree *tree)
1420 : {
1421 0 : struct tevent_req *req;
1422 0 : NTSTATUS status;
1423 2 : unsigned counter = 0;
1424 0 : bool ret;
1425 :
1426 2 : req = rename_dirs_bench_send(tctx, tctx->ev, tree, "dir", 3, 10,
1427 : &counter);
1428 2 : torture_assert(tctx, req != NULL, "rename_dirs_bench_send failed");
1429 :
1430 2 : ret = tevent_req_poll(req, tctx->ev);
1431 2 : torture_assert(tctx, ret, "tevent_req_poll failed");
1432 :
1433 2 : status = rename_dirs_bench_recv(req);
1434 2 : torture_comment(tctx, "rename_dirs_bench returned %s\n",
1435 : nt_errstr(status));
1436 2 : TALLOC_FREE(req);
1437 2 : torture_assert_ntstatus_ok(tctx, status, "bench failed");
1438 2 : return true;
1439 : }
1440 :
1441 : /*
1442 : * This test basically verifies that modify and change timestamps are preserved
1443 : * after file rename with outstanding open file handles.
1444 : */
1445 :
1446 2 : static bool torture_smb2_rename_simple_modtime(
1447 : struct torture_context *torture,
1448 : struct smb2_tree *tree1)
1449 : {
1450 0 : struct smb2_create c1, c2;
1451 0 : union smb_fileinfo gi;
1452 0 : union smb_setfileinfo si;
1453 2 : struct smb2_handle h1 = {{0}};
1454 2 : struct smb2_handle h2 = {{0}};
1455 0 : NTSTATUS status;
1456 2 : bool ret = true;
1457 :
1458 2 : smb2_deltree(tree1, BASEDIR);
1459 2 : smb2_util_mkdir(tree1, BASEDIR);
1460 :
1461 2 : torture_comment(torture, "Creating test file: file1.txt\n");
1462 :
1463 2 : c1 = (struct smb2_create) {
1464 : .in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE,
1465 : .in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
1466 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
1467 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
1468 : .in.create_disposition = NTCREATEX_DISP_CREATE,
1469 : .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
1470 : .in.fname = BASEDIR "\\file1.txt",
1471 : };
1472 :
1473 2 : status = smb2_create(tree1, torture, &c1);
1474 2 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1475 : "smb2_create failed\n");
1476 2 : h1 = c1.out.file.handle;
1477 :
1478 2 : torture_comment(torture, "Waitig for 5 secs..\n");
1479 2 : sleep(5);
1480 :
1481 2 : torture_comment(torture, "Creating test file: file2.txt\n");
1482 :
1483 2 : c2 = (struct smb2_create) {
1484 : .in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE,
1485 : .in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE,
1486 : .in.file_attributes = FILE_ATTRIBUTE_NORMAL,
1487 : .in.share_access = NTCREATEX_SHARE_ACCESS_MASK,
1488 : .in.create_disposition = NTCREATEX_DISP_CREATE,
1489 : .in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS,
1490 : .in.fname = BASEDIR "\\file2.txt",
1491 : };
1492 :
1493 2 : status = smb2_create(tree1, torture, &c2);
1494 2 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1495 : "smb2_create failed\n");
1496 2 : h2 = c2.out.file.handle;
1497 :
1498 2 : torture_comment(torture, "Renaming file1.txt --> tmp1.txt\n");
1499 :
1500 2 : si = (union smb_setfileinfo) {
1501 : .rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION,
1502 : .rename_information.in.file.handle = h1,
1503 : .rename_information.in.new_name =
1504 : BASEDIR "\\tmp1.txt",
1505 : };
1506 :
1507 2 : status = smb2_setinfo_file(tree1, &si);
1508 2 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1509 : "smb2_setinfo_file failed\n");
1510 :
1511 2 : torture_comment(torture, "GetInfo of tmp1.txt\n");
1512 :
1513 2 : gi = (union smb_fileinfo) {
1514 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
1515 : .generic.in.file.handle = h1,
1516 : };
1517 :
1518 2 : status = smb2_getinfo_file(tree1, torture, &gi);
1519 2 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1520 : "smb2_getinfo_file failed\n");
1521 :
1522 2 : torture_comment(torture, "Check if timestamps are good after rename(file1.txt --> tmp1.txt).\n");
1523 :
1524 2 : torture_assert_nttime_equal(
1525 : torture, c1.out.write_time, gi.all_info.out.write_time,
1526 : "Bad timestamp\n");
1527 2 : torture_assert_nttime_equal(
1528 : torture, c1.out.change_time, gi.all_info.out.change_time,
1529 : "Bad timestamp\n");
1530 :
1531 2 : torture_comment(torture, "Renaming file2.txt --> file1.txt\n");
1532 :
1533 2 : si = (union smb_setfileinfo) {
1534 : .rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION,
1535 : .rename_information.in.file.handle = h2,
1536 : .rename_information.in.new_name =
1537 : BASEDIR "\\file1.txt",
1538 : };
1539 2 : status = smb2_setinfo_file(tree1, &si);
1540 2 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1541 : "smb2_setinfo_file failed\n");
1542 :
1543 2 : torture_comment(torture, "GetInfo of file1.txt\n");
1544 :
1545 2 : gi = (union smb_fileinfo) {
1546 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
1547 : .generic.in.file.handle = h2,
1548 : };
1549 :
1550 2 : status = smb2_getinfo_file(tree1, torture, &gi);
1551 2 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1552 : "smb2_getinfo_file failed\n");
1553 :
1554 2 : torture_comment(torture, "Check if timestamps are good after rename(file2.txt --> file1.txt).\n");
1555 :
1556 2 : torture_assert_nttime_equal(
1557 : torture, c2.out.write_time, gi.all_info.out.write_time,
1558 : "Bad timestamp\n");
1559 2 : torture_assert_nttime_equal(
1560 : torture, c2.out.change_time, gi.all_info.out.change_time,
1561 : "Bad timestamp\n");
1562 :
1563 2 : done:
1564 2 : if (!smb2_util_handle_empty(h1)) {
1565 2 : smb2_util_close(tree1, h1);
1566 : }
1567 2 : if (!smb2_util_handle_empty(h2)) {
1568 2 : smb2_util_close(tree1, h2);
1569 : }
1570 2 : smb2_deltree(tree1, BASEDIR);
1571 2 : return ret;
1572 : }
1573 :
1574 2 : static bool test_smb2_close_full_information(struct torture_context *torture,
1575 : struct smb2_tree *tree1,
1576 : struct smb2_tree *tree2)
1577 : {
1578 0 : union smb_close cl;
1579 2 : struct smb2_create io = {0};
1580 2 : struct smb2_handle h1 = {{0}};
1581 2 : struct smb2_handle h2 = {{0}};
1582 2 : struct smb2_handle h3 = {{0}};
1583 0 : union smb_setfileinfo sinfo;
1584 0 : NTSTATUS status;
1585 2 : const char *fname_src = "request.dat";
1586 2 : const char *fname_dst = "renamed.dat";
1587 2 : bool ret = true;
1588 :
1589 : /* Start with a tidy share. */
1590 2 : smb2_util_unlink(tree1, fname_src);
1591 2 : smb2_util_unlink(tree1, fname_dst);
1592 :
1593 : /* Create the test file, and leave it open. */
1594 2 : io.in.fname = fname_src;
1595 2 : io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE;
1596 2 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1597 2 : io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1598 : NTCREATEX_SHARE_ACCESS_WRITE |
1599 : NTCREATEX_SHARE_ACCESS_DELETE;
1600 2 : status = smb2_create(tree1, tree1, &io);
1601 2 : CHECK_STATUS(status, NT_STATUS_OK);
1602 2 : h1 = io.out.file.handle;
1603 2 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1604 :
1605 : /* Open the test file on the second connection. */
1606 2 : ZERO_STRUCT(io);
1607 2 : io.in.fname = fname_src;
1608 2 : io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE;
1609 2 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1610 2 : io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1611 : NTCREATEX_SHARE_ACCESS_WRITE |
1612 : NTCREATEX_SHARE_ACCESS_DELETE;
1613 2 : status = smb2_create(tree2, tree2, &io);
1614 2 : CHECK_STATUS(status, NT_STATUS_OK);
1615 2 : h2 = io.out.file.handle;
1616 :
1617 : /* Now open for rename on the first connection. */
1618 2 : ZERO_STRUCT(io);
1619 2 : io.in.fname = fname_src;
1620 2 : io.in.desired_access = SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE;
1621 2 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1622 2 : io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1623 : NTCREATEX_SHARE_ACCESS_WRITE |
1624 : NTCREATEX_SHARE_ACCESS_DELETE;
1625 2 : status = smb2_create(tree1, tree1, &io);
1626 2 : CHECK_STATUS(status, NT_STATUS_OK);
1627 2 : h3 = io.out.file.handle;
1628 :
1629 : /* Do the rename. */
1630 2 : ZERO_STRUCT(sinfo);
1631 2 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
1632 2 : sinfo.rename_information.in.file.handle = h3;
1633 2 : sinfo.rename_information.in.new_name = fname_dst;
1634 2 : status = smb2_setinfo_file(tree1, &sinfo);
1635 2 : CHECK_STATUS(status, NT_STATUS_OK);
1636 :
1637 : /* And close h3. */
1638 2 : ZERO_STRUCT(cl.smb2);
1639 2 : cl.smb2.level = RAW_CLOSE_SMB2;
1640 2 : cl.smb2.in.file.handle = h3;
1641 2 : status = smb2_close(tree1, &cl.smb2);
1642 2 : CHECK_STATUS(status, NT_STATUS_OK);
1643 2 : ZERO_STRUCT(h3);
1644 :
1645 : /*
1646 : * Close h1 with SMB2_CLOSE_FLAGS_FULL_INFORMATION.
1647 : * Ensure we get data.
1648 : */
1649 2 : ZERO_STRUCT(cl.smb2);
1650 2 : cl.smb2.level = RAW_CLOSE_SMB2;
1651 2 : cl.smb2.in.file.handle = h1;
1652 2 : cl.smb2.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
1653 2 : status = smb2_close(tree1, &cl.smb2);
1654 2 : CHECK_STATUS(status, NT_STATUS_OK);
1655 2 : ZERO_STRUCT(h1);
1656 2 : CHECK_VAL(cl.smb2.out.file_attr, 0x20);
1657 :
1658 : /*
1659 : * Wait 3 seconds for name change to propagate
1660 : * to the other connection.
1661 : */
1662 2 : sleep(3);
1663 :
1664 : /*
1665 : * Close h2 with SMB2_CLOSE_FLAGS_FULL_INFORMATION.
1666 : * This is on connection2.
1667 : * Ensure we get data.
1668 : */
1669 2 : ZERO_STRUCT(cl.smb2);
1670 2 : cl.smb2.level = RAW_CLOSE_SMB2;
1671 2 : cl.smb2.in.file.handle = h2;
1672 2 : cl.smb2.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
1673 2 : status = smb2_close(tree2, &cl.smb2);
1674 2 : CHECK_STATUS(status, NT_STATUS_OK);
1675 2 : ZERO_STRUCT(h2);
1676 2 : CHECK_VAL(cl.smb2.out.file_attr, 0x20);
1677 :
1678 2 : done:
1679 :
1680 2 : if (h1.data[0] != 0 || h1.data[1] != 0) {
1681 0 : smb2_util_close(tree1, h1);
1682 : }
1683 2 : if (h2.data[0] != 0 || h2.data[1] != 0) {
1684 0 : smb2_util_close(tree2, h2);
1685 : }
1686 2 : if (h3.data[0] != 0 || h3.data[1] != 0) {
1687 0 : smb2_util_close(tree1, h3);
1688 : }
1689 :
1690 2 : smb2_util_unlink(tree1, fname_src);
1691 2 : smb2_util_unlink(tree1, fname_dst);
1692 :
1693 2 : return ret;
1694 : }
1695 :
1696 : /*
1697 : basic testing of SMB2 rename
1698 : */
1699 2354 : struct torture_suite *torture_smb2_rename_init(TALLOC_CTX *ctx)
1700 : {
1701 125 : struct torture_suite *suite =
1702 2354 : torture_suite_create(ctx, "rename");
1703 :
1704 2354 : torture_suite_add_1smb2_test(suite, "simple",
1705 : torture_smb2_rename_simple);
1706 :
1707 2354 : torture_suite_add_1smb2_test(suite, "simple_modtime",
1708 : torture_smb2_rename_simple_modtime);
1709 :
1710 2354 : torture_suite_add_1smb2_test(suite, "simple_nodelete",
1711 : torture_smb2_rename_simple2);
1712 :
1713 2354 : torture_suite_add_1smb2_test(suite, "no_sharing",
1714 : torture_smb2_rename_no_sharemode);
1715 :
1716 2354 : torture_suite_add_1smb2_test(suite,
1717 : "share_delete_and_delete_access",
1718 : torture_smb2_rename_with_delete_access);
1719 :
1720 2354 : torture_suite_add_1smb2_test(suite,
1721 : "no_share_delete_but_delete_access",
1722 : torture_smb2_rename_with_delete_access2);
1723 :
1724 2354 : torture_suite_add_1smb2_test(suite,
1725 : "share_delete_no_delete_access",
1726 : torture_smb2_rename_no_delete_access);
1727 :
1728 2354 : torture_suite_add_1smb2_test(suite,
1729 : "no_share_delete_no_delete_access",
1730 : torture_smb2_rename_no_delete_access2);
1731 :
1732 2354 : torture_suite_add_1smb2_test(suite,
1733 : "msword",
1734 : torture_smb2_rename_msword);
1735 :
1736 2354 : torture_suite_add_1smb2_test(
1737 : suite, "rename_dir_openfile",
1738 : torture_smb2_rename_dir_openfile);
1739 :
1740 2354 : torture_suite_add_1smb2_test(suite,
1741 : "rename_dir_bench",
1742 : torture_smb2_rename_dir_bench);
1743 :
1744 2354 : torture_suite_add_2smb2_test(suite,
1745 : "close-full-information",
1746 : test_smb2_close_full_information);
1747 :
1748 2354 : suite->description = talloc_strdup(suite, "smb2.rename tests");
1749 :
1750 2354 : return suite;
1751 : }
|