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 0 : static bool torture_smb2_rename_simple(struct torture_context *torture,
73 : struct smb2_tree *tree1)
74 : {
75 0 : bool ret = true;
76 : NTSTATUS status;
77 : union smb_open io;
78 : union smb_close cl;
79 : union smb_setfileinfo sinfo;
80 : union smb_fileinfo fi;
81 : struct smb2_handle h1;
82 :
83 0 : ZERO_STRUCT(h1);
84 :
85 0 : smb2_deltree(tree1, BASEDIR);
86 0 : smb2_util_rmdir(tree1, BASEDIR);
87 :
88 0 : torture_comment(torture, "Creating base directory\n");
89 :
90 0 : smb2_util_mkdir(tree1, BASEDIR);
91 :
92 :
93 0 : torture_comment(torture, "Creating test file\n");
94 :
95 0 : ZERO_STRUCT(io.smb2);
96 0 : io.generic.level = RAW_OPEN_SMB2;
97 0 : io.smb2.in.create_flags = 0;
98 0 : io.smb2.in.desired_access = SEC_FILE_ALL|SEC_STD_DELETE;
99 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
100 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
101 0 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
102 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
103 0 : io.smb2.in.alloc_size = 0;
104 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
105 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
106 0 : io.smb2.in.security_flags = 0;
107 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
108 :
109 0 : status = smb2_create(tree1, torture, &(io.smb2));
110 0 : CHECK_STATUS(status, NT_STATUS_OK);
111 0 : h1 = io.smb2.out.file.handle;
112 :
113 0 : torture_comment(torture, "Renaming test file\n");
114 :
115 0 : ZERO_STRUCT(sinfo);
116 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
117 0 : sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
118 0 : sinfo.rename_information.in.overwrite = 0;
119 0 : sinfo.rename_information.in.root_fid = 0;
120 0 : sinfo.rename_information.in.new_name =
121 : BASEDIR "\\newname.txt";
122 0 : status = smb2_setinfo_file(tree1, &sinfo);
123 0 : CHECK_STATUS(status, NT_STATUS_OK);
124 :
125 0 : torture_comment(torture, "Checking for new filename\n");
126 :
127 0 : ZERO_STRUCT(fi);
128 0 : fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
129 0 : fi.generic.in.file.handle = h1;
130 0 : status = smb2_getinfo_file(tree1, torture, &fi);
131 0 : CHECK_STATUS(status, NT_STATUS_OK);
132 :
133 :
134 0 : torture_comment(torture, "Closing test file\n");
135 :
136 0 : ZERO_STRUCT(cl.smb2);
137 0 : cl.smb2.level = RAW_CLOSE_SMB2;
138 0 : cl.smb2.in.file.handle = h1;
139 0 : status = smb2_close(tree1, &(cl.smb2));
140 0 : CHECK_STATUS(status, NT_STATUS_OK);
141 :
142 0 : ZERO_STRUCT(h1);
143 :
144 0 : done:
145 :
146 0 : torture_comment(torture, "Cleaning up\n");
147 :
148 0 : 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 0 : smb2_deltree(tree1, BASEDIR);
155 0 : 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 0 : static bool torture_smb2_rename_simple2(struct torture_context *torture,
164 : struct smb2_tree *tree1)
165 : {
166 0 : bool ret = true;
167 : NTSTATUS status;
168 : union smb_open io;
169 : union smb_close cl;
170 : union smb_setfileinfo sinfo;
171 : struct smb2_handle h1;
172 :
173 0 : ZERO_STRUCT(h1);
174 :
175 0 : smb2_deltree(tree1, BASEDIR);
176 0 : smb2_util_rmdir(tree1, BASEDIR);
177 :
178 0 : torture_comment(torture, "Creating base directory\n");
179 :
180 0 : smb2_util_mkdir(tree1, BASEDIR);
181 :
182 :
183 0 : torture_comment(torture, "Creating test file\n");
184 :
185 0 : ZERO_STRUCT(io.smb2);
186 0 : io.generic.level = RAW_OPEN_SMB2;
187 0 : io.smb2.in.create_flags = 0;
188 0 : io.smb2.in.desired_access = SEC_FILE_ALL;
189 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
190 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
191 0 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
192 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
193 0 : io.smb2.in.alloc_size = 0;
194 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
195 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
196 0 : io.smb2.in.security_flags = 0;
197 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
198 :
199 0 : status = smb2_create(tree1, torture, &(io.smb2));
200 0 : CHECK_STATUS(status, NT_STATUS_OK);
201 0 : h1 = io.smb2.out.file.handle;
202 :
203 0 : torture_comment(torture, "Renaming test file\n");
204 :
205 0 : ZERO_STRUCT(sinfo);
206 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
207 0 : sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
208 0 : sinfo.rename_information.in.overwrite = 0;
209 0 : sinfo.rename_information.in.root_fid = 0;
210 0 : sinfo.rename_information.in.new_name =
211 : BASEDIR "\\newname.txt";
212 0 : status = smb2_setinfo_file(tree1, &sinfo);
213 0 : 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 0 : done:
226 :
227 0 : torture_comment(torture, "Cleaning up\n");
228 :
229 0 : if (h1.data[0] || h1.data[1]) {
230 0 : ZERO_STRUCT(cl.smb2);
231 0 : cl.smb2.level = RAW_CLOSE_SMB2;
232 0 : cl.smb2.in.file.handle = h1;
233 0 : status = smb2_close(tree1, &(cl.smb2));
234 : }
235 0 : smb2_deltree(tree1, BASEDIR);
236 0 : return ret;
237 : }
238 :
239 :
240 : /*
241 : * testing of rename with no sharing allowed on file
242 : * this should work
243 : */
244 :
245 0 : static bool torture_smb2_rename_no_sharemode(struct torture_context *torture,
246 : struct smb2_tree *tree1)
247 : {
248 0 : bool ret = true;
249 : NTSTATUS status;
250 : union smb_open io;
251 : union smb_close cl;
252 : union smb_setfileinfo sinfo;
253 : union smb_fileinfo fi;
254 : struct smb2_handle h1;
255 :
256 0 : ZERO_STRUCT(h1);
257 :
258 0 : smb2_deltree(tree1, BASEDIR);
259 0 : smb2_util_rmdir(tree1, BASEDIR);
260 :
261 0 : torture_comment(torture, "Creating base directory\n");
262 :
263 0 : smb2_util_mkdir(tree1, BASEDIR);
264 :
265 :
266 0 : torture_comment(torture, "Creating test file\n");
267 :
268 0 : ZERO_STRUCT(io.smb2);
269 0 : io.generic.level = RAW_OPEN_SMB2;
270 0 : io.smb2.in.create_flags = 0;
271 0 : io.smb2.in.desired_access = 0x0017019f;
272 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
273 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
274 0 : io.smb2.in.share_access = 0;
275 0 : io.smb2.in.alloc_size = 0;
276 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
277 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
278 0 : io.smb2.in.security_flags = 0;
279 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
280 :
281 0 : status = smb2_create(tree1, torture, &(io.smb2));
282 0 : CHECK_STATUS(status, NT_STATUS_OK);
283 0 : h1 = io.smb2.out.file.handle;
284 :
285 0 : torture_comment(torture, "Renaming test file\n");
286 :
287 0 : ZERO_STRUCT(sinfo);
288 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
289 0 : sinfo.rename_information.in.file.handle = io.smb2.out.file.handle;
290 0 : sinfo.rename_information.in.overwrite = 0;
291 0 : sinfo.rename_information.in.root_fid = 0;
292 0 : sinfo.rename_information.in.new_name =
293 : BASEDIR "\\newname.txt";
294 0 : status = smb2_setinfo_file(tree1, &sinfo);
295 0 : CHECK_STATUS(status, NT_STATUS_OK);
296 :
297 0 : torture_comment(torture, "Checking for new filename\n");
298 :
299 0 : ZERO_STRUCT(fi);
300 0 : fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
301 0 : fi.generic.in.file.handle = h1;
302 0 : status = smb2_getinfo_file(tree1, torture, &fi);
303 0 : CHECK_STATUS(status, NT_STATUS_OK);
304 :
305 :
306 0 : torture_comment(torture, "Closing test file\n");
307 :
308 0 : ZERO_STRUCT(cl.smb2);
309 0 : cl.smb2.level = RAW_CLOSE_SMB2;
310 0 : cl.smb2.in.file.handle = h1;
311 0 : status = smb2_close(tree1, &(cl.smb2));
312 0 : CHECK_STATUS(status, NT_STATUS_OK);
313 :
314 0 : ZERO_STRUCT(h1);
315 :
316 0 : done:
317 :
318 0 : torture_comment(torture, "Cleaning up\n");
319 :
320 0 : 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 0 : smb2_deltree(tree1, BASEDIR);
327 0 : 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 0 : static bool torture_smb2_rename_with_delete_access(struct torture_context *torture,
337 : struct smb2_tree *tree1)
338 : {
339 0 : bool ret = true;
340 : NTSTATUS status;
341 : union smb_open io;
342 : union smb_close cl;
343 : union smb_setfileinfo sinfo;
344 : struct smb2_handle fh, dh;
345 :
346 0 : ZERO_STRUCT(fh);
347 0 : ZERO_STRUCT(dh);
348 :
349 0 : smb2_deltree(tree1, BASEDIR);
350 0 : smb2_util_rmdir(tree1, BASEDIR);
351 :
352 0 : torture_comment(torture, "Creating base directory\n");
353 :
354 0 : smb2_util_mkdir(tree1, BASEDIR);
355 :
356 0 : torture_comment(torture, "Opening parent directory\n");
357 :
358 0 : ZERO_STRUCT(io.smb2);
359 0 : io.generic.level = RAW_OPEN_SMB2;
360 0 : io.smb2.in.create_flags = 0;
361 0 : 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 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
367 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
368 0 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
369 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
370 0 : io.smb2.in.alloc_size = 0;
371 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
372 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
373 0 : io.smb2.in.security_flags = 0;
374 0 : io.smb2.in.fname = BASEDIR;
375 :
376 0 : status = smb2_create(tree1, torture, &(io.smb2));
377 0 : CHECK_STATUS(status, NT_STATUS_OK);
378 0 : dh = io.smb2.out.file.handle;
379 :
380 :
381 0 : torture_comment(torture, "Creating test file\n");
382 :
383 0 : ZERO_STRUCT(io.smb2);
384 0 : io.generic.level = RAW_OPEN_SMB2;
385 0 : io.smb2.in.create_flags = 0;
386 0 : 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 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
391 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
392 0 : io.smb2.in.share_access = 0;
393 0 : io.smb2.in.alloc_size = 0;
394 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
395 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
396 0 : io.smb2.in.security_flags = 0;
397 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
398 :
399 0 : status = smb2_create(tree1, torture, &(io.smb2));
400 0 : CHECK_STATUS(status, NT_STATUS_OK);
401 0 : fh = io.smb2.out.file.handle;
402 :
403 0 : torture_comment(torture, "Renaming test file\n");
404 :
405 0 : ZERO_STRUCT(sinfo);
406 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
407 0 : sinfo.rename_information.in.file.handle = fh;
408 0 : sinfo.rename_information.in.overwrite = 0;
409 0 : sinfo.rename_information.in.root_fid = 0;
410 0 : sinfo.rename_information.in.new_name =
411 : BASEDIR "\\newname.txt";
412 0 : status = smb2_setinfo_file(tree1, &sinfo);
413 0 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
414 :
415 0 : torture_comment(torture, "Closing test file\n");
416 :
417 0 : ZERO_STRUCT(cl.smb2);
418 0 : cl.smb2.level = RAW_CLOSE_SMB2;
419 0 : cl.smb2.in.file.handle = fh;
420 0 : status = smb2_close(tree1, &(cl.smb2));
421 0 : CHECK_STATUS(status, NT_STATUS_OK);
422 :
423 0 : ZERO_STRUCT(fh);
424 :
425 0 : torture_comment(torture, "Closing directory\n");
426 :
427 0 : ZERO_STRUCT(cl.smb2);
428 0 : cl.smb2.level = RAW_CLOSE_SMB2;
429 0 : cl.smb2.in.file.handle = dh;
430 0 : status = smb2_close(tree1, &(cl.smb2));
431 0 : CHECK_STATUS(status, NT_STATUS_OK);
432 :
433 0 : ZERO_STRUCT(dh);
434 :
435 :
436 0 : done:
437 :
438 0 : torture_comment(torture, "Cleaning up\n");
439 :
440 0 : 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 0 : 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 0 : smb2_deltree(tree1, BASEDIR);
454 0 : 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 0 : static bool torture_smb2_rename_with_delete_access2(struct torture_context *torture,
465 : struct smb2_tree *tree1)
466 : {
467 0 : bool ret = true;
468 : NTSTATUS status;
469 : union smb_open io;
470 : union smb_close cl;
471 : union smb_setfileinfo sinfo;
472 : struct smb2_handle fh, dh;
473 :
474 0 : ZERO_STRUCT(fh);
475 0 : ZERO_STRUCT(dh);
476 :
477 0 : smb2_deltree(tree1, BASEDIR);
478 0 : smb2_util_rmdir(tree1, BASEDIR);
479 :
480 0 : torture_comment(torture, "Creating base directory\n");
481 :
482 0 : smb2_util_mkdir(tree1, BASEDIR);
483 :
484 0 : torture_comment(torture, "Opening parent directory\n");
485 :
486 0 : ZERO_STRUCT(io.smb2);
487 0 : io.generic.level = RAW_OPEN_SMB2;
488 0 : io.smb2.in.create_flags = 0;
489 0 : 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 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
495 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
496 0 : io.smb2.in.share_access = 0;
497 0 : io.smb2.in.alloc_size = 0;
498 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
499 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
500 0 : io.smb2.in.security_flags = 0;
501 0 : io.smb2.in.fname = BASEDIR;
502 :
503 0 : status = smb2_create(tree1, torture, &(io.smb2));
504 0 : CHECK_STATUS(status, NT_STATUS_OK);
505 0 : dh = io.smb2.out.file.handle;
506 :
507 :
508 0 : torture_comment(torture, "Creating test file\n");
509 :
510 0 : ZERO_STRUCT(io.smb2);
511 0 : io.generic.level = RAW_OPEN_SMB2;
512 0 : io.smb2.in.create_flags = 0;
513 0 : 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 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
518 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
519 0 : io.smb2.in.share_access = 0;
520 0 : io.smb2.in.alloc_size = 0;
521 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
522 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
523 0 : io.smb2.in.security_flags = 0;
524 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
525 :
526 0 : status = smb2_create(tree1, torture, &(io.smb2));
527 0 : CHECK_STATUS(status, NT_STATUS_OK);
528 0 : fh = io.smb2.out.file.handle;
529 :
530 0 : torture_comment(torture, "Renaming test file\n");
531 :
532 0 : ZERO_STRUCT(sinfo);
533 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
534 0 : sinfo.rename_information.in.file.handle = fh;
535 0 : sinfo.rename_information.in.overwrite = 0;
536 0 : sinfo.rename_information.in.root_fid = 0;
537 0 : sinfo.rename_information.in.new_name =
538 : BASEDIR "\\newname.txt";
539 0 : status = smb2_setinfo_file(tree1, &sinfo);
540 0 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
541 :
542 0 : torture_comment(torture, "Closing test file\n");
543 :
544 0 : ZERO_STRUCT(cl.smb2);
545 0 : cl.smb2.level = RAW_CLOSE_SMB2;
546 0 : cl.smb2.in.file.handle = fh;
547 0 : status = smb2_close(tree1, &(cl.smb2));
548 0 : CHECK_STATUS(status, NT_STATUS_OK);
549 :
550 0 : ZERO_STRUCT(fh);
551 :
552 0 : torture_comment(torture, "Closing directory\n");
553 :
554 0 : ZERO_STRUCT(cl.smb2);
555 0 : cl.smb2.level = RAW_CLOSE_SMB2;
556 0 : cl.smb2.in.file.handle = dh;
557 0 : status = smb2_close(tree1, &(cl.smb2));
558 0 : CHECK_STATUS(status, NT_STATUS_OK);
559 :
560 0 : ZERO_STRUCT(dh);
561 :
562 :
563 0 : done:
564 :
565 0 : torture_comment(torture, "Cleaning up\n");
566 :
567 0 : 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 0 : 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 0 : smb2_deltree(tree1, BASEDIR);
581 0 : 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 0 : static bool torture_smb2_rename_no_delete_access(struct torture_context *torture,
591 : struct smb2_tree *tree1)
592 : {
593 0 : bool ret = true;
594 : NTSTATUS status;
595 : union smb_open io;
596 : union smb_close cl;
597 : union smb_setfileinfo sinfo;
598 : union smb_fileinfo fi;
599 : struct smb2_handle fh, dh;
600 :
601 0 : ZERO_STRUCT(fh);
602 0 : ZERO_STRUCT(dh);
603 :
604 0 : smb2_deltree(tree1, BASEDIR);
605 0 : smb2_util_rmdir(tree1, BASEDIR);
606 :
607 0 : torture_comment(torture, "Creating base directory\n");
608 :
609 0 : smb2_util_mkdir(tree1, BASEDIR);
610 :
611 0 : torture_comment(torture, "Opening parent directory\n");
612 :
613 0 : ZERO_STRUCT(io.smb2);
614 0 : io.generic.level = RAW_OPEN_SMB2;
615 0 : io.smb2.in.create_flags = 0;
616 0 : 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 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
622 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
623 0 : io.smb2.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
624 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
625 0 : io.smb2.in.alloc_size = 0;
626 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
627 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
628 0 : io.smb2.in.security_flags = 0;
629 0 : io.smb2.in.fname = BASEDIR;
630 :
631 0 : status = smb2_create(tree1, torture, &(io.smb2));
632 0 : CHECK_STATUS(status, NT_STATUS_OK);
633 0 : dh = io.smb2.out.file.handle;
634 :
635 :
636 0 : torture_comment(torture, "Creating test file\n");
637 :
638 0 : ZERO_STRUCT(io.smb2);
639 0 : io.generic.level = RAW_OPEN_SMB2;
640 0 : io.smb2.in.create_flags = 0;
641 0 : 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 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
646 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
647 0 : io.smb2.in.share_access = 0;
648 0 : io.smb2.in.alloc_size = 0;
649 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
650 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
651 0 : io.smb2.in.security_flags = 0;
652 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
653 :
654 0 : status = smb2_create(tree1, torture, &(io.smb2));
655 0 : CHECK_STATUS(status, NT_STATUS_OK);
656 0 : fh = io.smb2.out.file.handle;
657 :
658 0 : torture_comment(torture, "Renaming test file\n");
659 :
660 0 : ZERO_STRUCT(sinfo);
661 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
662 0 : sinfo.rename_information.in.file.handle = fh;
663 0 : sinfo.rename_information.in.overwrite = 0;
664 0 : sinfo.rename_information.in.root_fid = 0;
665 0 : sinfo.rename_information.in.new_name =
666 : BASEDIR "\\newname.txt";
667 0 : status = smb2_setinfo_file(tree1, &sinfo);
668 0 : CHECK_STATUS(status, NT_STATUS_OK);
669 :
670 0 : torture_comment(torture, "Checking for new filename\n");
671 :
672 0 : ZERO_STRUCT(fi);
673 0 : fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
674 0 : fi.generic.in.file.handle = fh;
675 0 : status = smb2_getinfo_file(tree1, torture, &fi);
676 0 : CHECK_STATUS(status, NT_STATUS_OK);
677 :
678 :
679 0 : torture_comment(torture, "Closing test file\n");
680 :
681 0 : ZERO_STRUCT(cl.smb2);
682 0 : cl.smb2.level = RAW_CLOSE_SMB2;
683 0 : cl.smb2.in.file.handle = fh;
684 0 : status = smb2_close(tree1, &(cl.smb2));
685 0 : CHECK_STATUS(status, NT_STATUS_OK);
686 :
687 0 : ZERO_STRUCT(fh);
688 :
689 0 : torture_comment(torture, "Closing directory\n");
690 :
691 0 : ZERO_STRUCT(cl.smb2);
692 0 : cl.smb2.level = RAW_CLOSE_SMB2;
693 0 : cl.smb2.in.file.handle = dh;
694 0 : status = smb2_close(tree1, &(cl.smb2));
695 0 : CHECK_STATUS(status, NT_STATUS_OK);
696 :
697 0 : ZERO_STRUCT(dh);
698 :
699 :
700 0 : done:
701 :
702 0 : torture_comment(torture, "Cleaning up\n");
703 :
704 0 : 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 0 : 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 0 : smb2_deltree(tree1, BASEDIR);
718 0 : 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 0 : static bool torture_smb2_rename_no_delete_access2(struct torture_context *torture,
729 : struct smb2_tree *tree1)
730 : {
731 0 : bool ret = true;
732 : NTSTATUS status;
733 : union smb_open io;
734 : union smb_close cl;
735 : union smb_setfileinfo sinfo;
736 : struct smb2_handle fh, dh;
737 :
738 0 : ZERO_STRUCT(fh);
739 0 : ZERO_STRUCT(dh);
740 :
741 0 : smb2_deltree(tree1, BASEDIR);
742 0 : smb2_util_rmdir(tree1, BASEDIR);
743 :
744 0 : torture_comment(torture, "Creating base directory\n");
745 :
746 0 : smb2_util_mkdir(tree1, BASEDIR);
747 :
748 0 : torture_comment(torture, "Opening parent directory\n");
749 :
750 0 : ZERO_STRUCT(io.smb2);
751 0 : io.generic.level = RAW_OPEN_SMB2;
752 0 : io.smb2.in.create_flags = 0;
753 0 : 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 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
759 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
760 0 : io.smb2.in.share_access = 0;
761 0 : io.smb2.in.alloc_size = 0;
762 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
763 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
764 0 : io.smb2.in.security_flags = 0;
765 0 : io.smb2.in.fname = BASEDIR;
766 :
767 0 : status = smb2_create(tree1, torture, &(io.smb2));
768 0 : CHECK_STATUS(status, NT_STATUS_OK);
769 0 : dh = io.smb2.out.file.handle;
770 :
771 :
772 0 : torture_comment(torture, "Creating test file\n");
773 :
774 0 : ZERO_STRUCT(io.smb2);
775 0 : io.generic.level = RAW_OPEN_SMB2;
776 0 : io.smb2.in.create_flags = 0;
777 0 : 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 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
782 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
783 0 : io.smb2.in.share_access = 0;
784 0 : io.smb2.in.alloc_size = 0;
785 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
786 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
787 0 : io.smb2.in.security_flags = 0;
788 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
789 :
790 0 : status = smb2_create(tree1, torture, &(io.smb2));
791 0 : CHECK_STATUS(status, NT_STATUS_OK);
792 0 : fh = io.smb2.out.file.handle;
793 :
794 0 : torture_comment(torture, "Renaming test file\n");
795 :
796 0 : ZERO_STRUCT(sinfo);
797 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
798 0 : sinfo.rename_information.in.file.handle = fh;
799 0 : sinfo.rename_information.in.overwrite = 0;
800 0 : sinfo.rename_information.in.root_fid = 0;
801 0 : sinfo.rename_information.in.new_name =
802 : BASEDIR "\\newname.txt";
803 0 : status = smb2_setinfo_file(tree1, &sinfo);
804 0 : 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 0 : done:
828 :
829 0 : torture_comment(torture, "Cleaning up\n");
830 :
831 0 : if (fh.data[0] || fh.data[1]) {
832 0 : ZERO_STRUCT(cl.smb2);
833 0 : cl.smb2.level = RAW_CLOSE_SMB2;
834 0 : cl.smb2.in.file.handle = fh;
835 0 : status = smb2_close(tree1, &(cl.smb2));
836 : }
837 0 : if (dh.data[0] || dh.data[1]) {
838 0 : ZERO_STRUCT(cl.smb2);
839 0 : cl.smb2.level = RAW_CLOSE_SMB2;
840 0 : cl.smb2.in.file.handle = dh;
841 0 : status = smb2_close(tree1, &(cl.smb2));
842 : }
843 :
844 0 : smb2_deltree(tree1, BASEDIR);
845 0 : return ret;
846 : }
847 :
848 : /*
849 : * this is a replay of how Word 2010 saves a file
850 : * this should pass
851 : */
852 :
853 0 : static bool torture_smb2_rename_msword(struct torture_context *torture,
854 : struct smb2_tree *tree1)
855 : {
856 0 : bool ret = true;
857 : NTSTATUS status;
858 : union smb_open io;
859 : union smb_close cl;
860 : union smb_setfileinfo sinfo;
861 : union smb_fileinfo fi;
862 : struct smb2_handle fh, dh;
863 :
864 0 : ZERO_STRUCT(fh);
865 0 : ZERO_STRUCT(dh);
866 :
867 0 : smb2_deltree(tree1, BASEDIR);
868 0 : smb2_util_rmdir(tree1, BASEDIR);
869 :
870 0 : torture_comment(torture, "Creating base directory\n");
871 :
872 0 : smb2_util_mkdir(tree1, BASEDIR);
873 :
874 0 : torture_comment(torture, "Creating test file\n");
875 :
876 0 : ZERO_STRUCT(io.smb2);
877 0 : io.generic.level = RAW_OPEN_SMB2;
878 0 : io.smb2.in.create_flags = 0;
879 0 : io.smb2.in.desired_access = 0x0017019f;
880 0 : io.smb2.in.create_options = 0x60;
881 0 : io.smb2.in.file_attributes = 0;
882 0 : io.smb2.in.share_access = 0;
883 0 : io.smb2.in.alloc_size = 0;
884 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
885 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
886 0 : io.smb2.in.security_flags = 0;
887 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
888 :
889 0 : status = smb2_create(tree1, torture, &(io.smb2));
890 0 : CHECK_STATUS(status, NT_STATUS_OK);
891 0 : fh = io.smb2.out.file.handle;
892 :
893 0 : torture_comment(torture, "Opening parent directory\n");
894 :
895 0 : ZERO_STRUCT(io.smb2);
896 0 : io.generic.level = RAW_OPEN_SMB2;
897 0 : io.smb2.in.create_flags = 0;
898 0 : io.smb2.in.desired_access = 0x00100080;
899 0 : io.smb2.in.create_options = 0x00800021;
900 0 : io.smb2.in.file_attributes = 0;
901 0 : io.smb2.in.share_access = 0;
902 0 : io.smb2.in.alloc_size = 0;
903 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_OPEN;
904 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
905 0 : io.smb2.in.security_flags = 0;
906 0 : io.smb2.in.fname = BASEDIR;
907 :
908 0 : status = smb2_create(tree1, torture, &(io.smb2));
909 0 : CHECK_STATUS(status, NT_STATUS_OK);
910 0 : dh = io.smb2.out.file.handle;
911 :
912 0 : torture_comment(torture, "Renaming test file\n");
913 :
914 0 : ZERO_STRUCT(sinfo);
915 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
916 0 : sinfo.rename_information.in.file.handle = fh;
917 0 : sinfo.rename_information.in.overwrite = 0;
918 0 : sinfo.rename_information.in.root_fid = 0;
919 0 : sinfo.rename_information.in.new_name =
920 : BASEDIR "\\newname.txt";
921 0 : status = smb2_setinfo_file(tree1, &sinfo);
922 0 : CHECK_STATUS(status, NT_STATUS_OK);
923 :
924 0 : torture_comment(torture, "Checking for new filename\n");
925 :
926 0 : ZERO_STRUCT(fi);
927 0 : fi.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
928 0 : fi.generic.in.file.handle = fh;
929 0 : status = smb2_getinfo_file(tree1, torture, &fi);
930 0 : CHECK_STATUS(status, NT_STATUS_OK);
931 :
932 :
933 0 : torture_comment(torture, "Closing test file\n");
934 :
935 0 : ZERO_STRUCT(cl.smb2);
936 0 : cl.smb2.level = RAW_CLOSE_SMB2;
937 0 : cl.smb2.in.file.handle = fh;
938 0 : status = smb2_close(tree1, &(cl.smb2));
939 0 : CHECK_STATUS(status, NT_STATUS_OK);
940 :
941 0 : ZERO_STRUCT(fh);
942 :
943 0 : torture_comment(torture, "Closing directory\n");
944 :
945 0 : ZERO_STRUCT(cl.smb2);
946 0 : cl.smb2.level = RAW_CLOSE_SMB2;
947 0 : cl.smb2.in.file.handle = dh;
948 0 : status = smb2_close(tree1, &(cl.smb2));
949 0 : CHECK_STATUS(status, NT_STATUS_OK);
950 :
951 0 : ZERO_STRUCT(dh);
952 :
953 :
954 0 : done:
955 :
956 0 : torture_comment(torture, "Cleaning up\n");
957 :
958 0 : 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 0 : 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 0 : smb2_deltree(tree1, BASEDIR);
972 0 : return ret;
973 : }
974 :
975 0 : static bool torture_smb2_rename_dir_openfile(struct torture_context *torture,
976 : struct smb2_tree *tree1)
977 : {
978 0 : bool ret = true;
979 : NTSTATUS status;
980 : union smb_open io;
981 : union smb_close cl;
982 : union smb_setfileinfo sinfo;
983 : struct smb2_handle d1, h1;
984 :
985 0 : ZERO_STRUCT(d1);
986 0 : ZERO_STRUCT(h1);
987 :
988 0 : smb2_deltree(tree1, BASEDIR);
989 0 : smb2_util_rmdir(tree1, BASEDIR);
990 :
991 0 : torture_comment(torture, "Creating base directory\n");
992 :
993 0 : ZERO_STRUCT(io.smb2);
994 0 : io.generic.level = RAW_OPEN_SMB2;
995 0 : io.smb2.in.create_flags = 0;
996 0 : io.smb2.in.desired_access = 0x0017019f;
997 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
998 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
999 0 : io.smb2.in.share_access = 0;
1000 0 : io.smb2.in.alloc_size = 0;
1001 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1002 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1003 0 : io.smb2.in.security_flags = 0;
1004 0 : io.smb2.in.fname = BASEDIR;
1005 :
1006 0 : status = smb2_create(tree1, torture, &(io.smb2));
1007 0 : CHECK_STATUS(status, NT_STATUS_OK);
1008 0 : d1 = io.smb2.out.file.handle;
1009 :
1010 0 : torture_comment(torture, "Creating test file\n");
1011 :
1012 0 : ZERO_STRUCT(io.smb2);
1013 0 : io.generic.level = RAW_OPEN_SMB2;
1014 0 : io.smb2.in.create_flags = 0;
1015 0 : io.smb2.in.desired_access = 0x0017019f;
1016 0 : io.smb2.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1017 0 : io.smb2.in.file_attributes = FILE_ATTRIBUTE_NORMAL;
1018 0 : io.smb2.in.share_access = 0;
1019 0 : io.smb2.in.alloc_size = 0;
1020 0 : io.smb2.in.create_disposition = NTCREATEX_DISP_CREATE;
1021 0 : io.smb2.in.impersonation_level = SMB2_IMPERSONATION_ANONYMOUS;
1022 0 : io.smb2.in.security_flags = 0;
1023 0 : io.smb2.in.fname = BASEDIR "\\file.txt";
1024 :
1025 0 : status = smb2_create(tree1, torture, &(io.smb2));
1026 0 : CHECK_STATUS(status, NT_STATUS_OK);
1027 0 : h1 = io.smb2.out.file.handle;
1028 :
1029 0 : torture_comment(torture, "Renaming directory\n");
1030 :
1031 0 : ZERO_STRUCT(sinfo);
1032 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
1033 0 : sinfo.rename_information.in.file.handle = d1;
1034 0 : sinfo.rename_information.in.overwrite = 0;
1035 0 : sinfo.rename_information.in.root_fid = 0;
1036 0 : sinfo.rename_information.in.new_name =
1037 : BASEDIR "-new";
1038 0 : status = smb2_setinfo_file(tree1, &sinfo);
1039 0 : CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
1040 :
1041 0 : torture_comment(torture, "Closing directory\n");
1042 :
1043 0 : ZERO_STRUCT(cl.smb2);
1044 0 : cl.smb2.level = RAW_CLOSE_SMB2;
1045 0 : cl.smb2.in.file.handle = d1;
1046 0 : status = smb2_close(tree1, &(cl.smb2));
1047 0 : CHECK_STATUS(status, NT_STATUS_OK);
1048 0 : ZERO_STRUCT(d1);
1049 :
1050 0 : torture_comment(torture, "Closing test file\n");
1051 :
1052 0 : cl.smb2.in.file.handle = h1;
1053 0 : status = smb2_close(tree1, &(cl.smb2));
1054 0 : CHECK_STATUS(status, NT_STATUS_OK);
1055 0 : ZERO_STRUCT(h1);
1056 :
1057 0 : done:
1058 :
1059 0 : torture_comment(torture, "Cleaning up\n");
1060 :
1061 0 : 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 0 : smb2_deltree(tree1, BASEDIR);
1068 0 : 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 0 : 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 : struct tevent_req *req;
1095 : struct rename_one_dir_cycle_state *state;
1096 : struct smb2_request *subreq;
1097 :
1098 0 : req = tevent_req_create(mem_ctx, &state,
1099 : struct rename_one_dir_cycle_state);
1100 0 : if (req == NULL) {
1101 0 : return NULL;
1102 : }
1103 0 : state->ev = ev;
1104 0 : state->tree = tree;
1105 0 : state->file = file;
1106 0 : state->base_name = base_name;
1107 0 : state->rename_counter = rename_counter;
1108 0 : state->current = 0;
1109 0 : state->max = max_renames;
1110 :
1111 0 : ZERO_STRUCT(state->sinfo);
1112 0 : state->sinfo.rename_information.level =
1113 : RAW_SFILEINFO_RENAME_INFORMATION;
1114 0 : state->sinfo.rename_information.in.file.handle = state->file;
1115 0 : state->sinfo.rename_information.in.overwrite = 0;
1116 0 : state->sinfo.rename_information.in.root_fid = 0;
1117 :
1118 0 : state->new_name = talloc_asprintf(
1119 0 : state, "%s-%u", state->base_name, state->current);
1120 0 : if (tevent_req_nomem(state->new_name, req)) {
1121 0 : return tevent_req_post(req, ev);
1122 : }
1123 0 : state->sinfo.rename_information.in.new_name = state->new_name;
1124 :
1125 0 : subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
1126 0 : if (tevent_req_nomem(subreq, req)) {
1127 0 : return tevent_req_post(req, ev);
1128 : }
1129 0 : subreq->async.fn = rename_one_dir_cycle_done;
1130 0 : subreq->async.private_data = req;
1131 0 : return req;
1132 : }
1133 :
1134 0 : static void rename_one_dir_cycle_done(struct smb2_request *subreq)
1135 : {
1136 0 : struct tevent_req *req = talloc_get_type_abort(
1137 : subreq->async.private_data, struct tevent_req);
1138 0 : struct rename_one_dir_cycle_state *state = tevent_req_data(
1139 : req, struct rename_one_dir_cycle_state);
1140 : NTSTATUS status;
1141 :
1142 0 : status = smb2_setinfo_recv(subreq);
1143 0 : if (tevent_req_nterror(req, status)) {
1144 0 : return;
1145 : }
1146 0 : TALLOC_FREE(state->new_name);
1147 :
1148 0 : *state->rename_counter += 1;
1149 :
1150 0 : state->current += 1;
1151 0 : if (state->current >= state->max) {
1152 0 : tevent_req_done(req);
1153 0 : return;
1154 : }
1155 :
1156 0 : ZERO_STRUCT(state->sinfo);
1157 0 : state->sinfo.rename_information.level =
1158 : RAW_SFILEINFO_RENAME_INFORMATION;
1159 0 : state->sinfo.rename_information.in.file.handle = state->file;
1160 0 : state->sinfo.rename_information.in.overwrite = 0;
1161 0 : state->sinfo.rename_information.in.root_fid = 0;
1162 :
1163 0 : state->new_name = talloc_asprintf(
1164 : state, "%s-%u", state->base_name, state->current);
1165 0 : if (tevent_req_nomem(state->new_name, req)) {
1166 0 : return;
1167 : }
1168 0 : state->sinfo.rename_information.in.new_name = state->new_name;
1169 :
1170 0 : subreq = smb2_setinfo_file_send(state->tree, &state->sinfo);
1171 0 : if (tevent_req_nomem(subreq, req)) {
1172 0 : return;
1173 : }
1174 0 : subreq->async.fn = rename_one_dir_cycle_done;
1175 0 : subreq->async.private_data = req;
1176 : }
1177 :
1178 0 : static NTSTATUS rename_one_dir_cycle_recv(struct tevent_req *req)
1179 : {
1180 0 : 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 0 : 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 : struct tevent_req *req;
1210 : struct rename_dir_bench_state *state;
1211 : struct smb2_request *subreq;
1212 :
1213 0 : req = tevent_req_create(mem_ctx, &state,
1214 : struct rename_dir_bench_state);
1215 0 : if (req == NULL) {
1216 0 : return NULL;
1217 : }
1218 0 : state->ev = ev;
1219 0 : state->tree = tree;
1220 0 : state->base_name = base_name;
1221 0 : state->max_renames = max_renames;
1222 0 : state->rename_counter = rename_counter;
1223 :
1224 0 : ZERO_STRUCT(state->io);
1225 0 : state->io.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
1226 0 : state->io.in.share_access =
1227 : NTCREATEX_SHARE_ACCESS_READ|
1228 : NTCREATEX_SHARE_ACCESS_WRITE;
1229 0 : state->io.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1230 0 : state->io.in.file_attributes = FILE_ATTRIBUTE_DIRECTORY;
1231 0 : state->io.in.create_disposition = NTCREATEX_DISP_OPEN_IF;
1232 0 : state->io.in.fname = state->base_name;
1233 :
1234 0 : subreq = smb2_create_send(state->tree, &state->io);
1235 0 : if (tevent_req_nomem(subreq, req)) {
1236 0 : return tevent_req_post(req, ev);
1237 : }
1238 0 : subreq->async.fn = rename_dir_bench_opened;
1239 0 : subreq->async.private_data = req;
1240 0 : return req;
1241 : }
1242 :
1243 0 : static void rename_dir_bench_opened(struct smb2_request *subreq)
1244 : {
1245 0 : struct tevent_req *req = talloc_get_type_abort(
1246 : subreq->async.private_data, struct tevent_req);
1247 0 : struct rename_dir_bench_state *state = tevent_req_data(
1248 : req, struct rename_dir_bench_state);
1249 : struct smb2_create *io;
1250 : struct tevent_req *subreq2;
1251 : NTSTATUS status;
1252 :
1253 0 : io = talloc(state, struct smb2_create);
1254 0 : if (tevent_req_nomem(io, req)) {
1255 0 : return;
1256 : }
1257 :
1258 0 : status = smb2_create_recv(subreq, io, io);
1259 0 : if (tevent_req_nterror(req, status)) {
1260 0 : return;
1261 : }
1262 0 : state->file = io->out.file.handle;
1263 0 : TALLOC_FREE(io);
1264 :
1265 0 : 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 0 : if (tevent_req_nomem(subreq2, req)) {
1270 0 : return;
1271 : }
1272 0 : tevent_req_set_callback(subreq2, rename_dir_bench_renamed, req);
1273 : }
1274 :
1275 0 : static void rename_dir_bench_renamed(struct tevent_req *subreq)
1276 : {
1277 0 : struct tevent_req *req = tevent_req_callback_data(
1278 : subreq, struct tevent_req);
1279 0 : struct rename_dir_bench_state *state = tevent_req_data(
1280 : req, struct rename_dir_bench_state);
1281 : struct smb2_request *subreq2;
1282 : NTSTATUS status;
1283 :
1284 0 : status = rename_one_dir_cycle_recv(subreq);
1285 0 : TALLOC_FREE(subreq);
1286 0 : if (tevent_req_nterror(req, status)) {
1287 0 : return;
1288 : }
1289 :
1290 0 : ZERO_STRUCT(state->sinfo);
1291 0 : state->sinfo.disposition_info.level =
1292 : RAW_SFILEINFO_DISPOSITION_INFORMATION;
1293 0 : state->sinfo.disposition_info.in.file.handle = state->file;
1294 0 : state->sinfo.disposition_info.in.delete_on_close = true;
1295 :
1296 0 : subreq2 = smb2_setinfo_file_send(state->tree, &state->sinfo);
1297 0 : if (tevent_req_nomem(subreq2, req)) {
1298 0 : return;
1299 : }
1300 0 : subreq2->async.fn = rename_dir_bench_set_doc;
1301 0 : subreq2->async.private_data = req;
1302 : }
1303 :
1304 0 : static void rename_dir_bench_set_doc(struct smb2_request *subreq)
1305 : {
1306 0 : struct tevent_req *req = talloc_get_type_abort(
1307 : subreq->async.private_data, struct tevent_req);
1308 0 : struct rename_dir_bench_state *state = tevent_req_data(
1309 : req, struct rename_dir_bench_state);
1310 : NTSTATUS status;
1311 :
1312 0 : status = smb2_setinfo_recv(subreq);
1313 0 : if (tevent_req_nterror(req, status)) {
1314 0 : return;
1315 : }
1316 :
1317 0 : ZERO_STRUCT(state->cl);
1318 0 : state->cl.in.file.handle = state->file;
1319 :
1320 0 : subreq = smb2_close_send(state->tree, &state->cl);
1321 0 : if (tevent_req_nomem(subreq, req)) {
1322 0 : return;
1323 : }
1324 0 : subreq->async.fn = rename_dir_bench_closed;
1325 0 : subreq->async.private_data = req;
1326 : }
1327 :
1328 0 : static void rename_dir_bench_closed(struct smb2_request *subreq)
1329 : {
1330 0 : struct tevent_req *req = talloc_get_type_abort(
1331 : subreq->async.private_data, struct tevent_req);
1332 : struct smb2_close cl;
1333 : NTSTATUS status;
1334 :
1335 0 : status = smb2_close_recv(subreq, &cl);
1336 0 : if (tevent_req_nterror(req, status)) {
1337 0 : return;
1338 : }
1339 0 : tevent_req_done(req);
1340 : }
1341 :
1342 0 : static NTSTATUS rename_dir_bench_recv(struct tevent_req *req)
1343 : {
1344 0 : 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 0 : 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 : struct tevent_req *req;
1363 : struct rename_dirs_bench_state *state;
1364 : unsigned i;
1365 :
1366 0 : req = tevent_req_create(mem_ctx, &state,
1367 : struct rename_dirs_bench_state);
1368 0 : if (req == NULL) {
1369 0 : return NULL;
1370 : }
1371 0 : state->num_reqs = num_parallel;
1372 0 : state->num_done = 0;
1373 :
1374 0 : for (i=0; i<num_parallel; i++) {
1375 : struct tevent_req *subreq;
1376 : char *sub_base;
1377 :
1378 0 : sub_base = talloc_asprintf(state, "%s-%u", base_name, i);
1379 0 : if (tevent_req_nomem(sub_base, req)) {
1380 0 : return tevent_req_post(req, ev);
1381 : }
1382 :
1383 0 : subreq = rename_dir_bench_send(state, ev, tree, sub_base,
1384 : max_renames, rename_counter);
1385 0 : if (tevent_req_nomem(subreq, req)) {
1386 0 : return tevent_req_post(req, ev);
1387 : }
1388 0 : tevent_req_set_callback(subreq, rename_dirs_bench_done, req);
1389 : }
1390 0 : return req;
1391 : }
1392 :
1393 0 : static void rename_dirs_bench_done(struct tevent_req *subreq)
1394 : {
1395 0 : struct tevent_req *req = tevent_req_callback_data(
1396 : subreq, struct tevent_req);
1397 0 : struct rename_dirs_bench_state *state = tevent_req_data(
1398 : req, struct rename_dirs_bench_state);
1399 : NTSTATUS status;
1400 :
1401 0 : status = rename_dir_bench_recv(subreq);
1402 0 : TALLOC_FREE(subreq);
1403 0 : if (tevent_req_nterror(req, status)) {
1404 0 : return;
1405 : }
1406 :
1407 0 : state->num_done += 1;
1408 0 : if (state->num_done >= state->num_reqs) {
1409 0 : tevent_req_done(req);
1410 : }
1411 : }
1412 :
1413 0 : static NTSTATUS rename_dirs_bench_recv(struct tevent_req *req)
1414 : {
1415 0 : return tevent_req_simple_recv_ntstatus(req);
1416 : }
1417 :
1418 0 : static bool torture_smb2_rename_dir_bench(struct torture_context *tctx,
1419 : struct smb2_tree *tree)
1420 : {
1421 : struct tevent_req *req;
1422 : NTSTATUS status;
1423 0 : unsigned counter = 0;
1424 : bool ret;
1425 :
1426 0 : req = rename_dirs_bench_send(tctx, tctx->ev, tree, "dir", 3, 10,
1427 : &counter);
1428 0 : torture_assert(tctx, req != NULL, "rename_dirs_bench_send failed");
1429 :
1430 0 : ret = tevent_req_poll(req, tctx->ev);
1431 0 : torture_assert(tctx, ret, "tevent_req_poll failed");
1432 :
1433 0 : status = rename_dirs_bench_recv(req);
1434 0 : torture_comment(tctx, "rename_dirs_bench returned %s\n",
1435 : nt_errstr(status));
1436 0 : TALLOC_FREE(req);
1437 0 : torture_assert_ntstatus_ok(tctx, status, "bench failed");
1438 0 : 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 0 : static bool torture_smb2_rename_simple_modtime(
1447 : struct torture_context *torture,
1448 : struct smb2_tree *tree1)
1449 : {
1450 : struct smb2_create c1, c2;
1451 : union smb_fileinfo gi;
1452 : union smb_setfileinfo si;
1453 0 : struct smb2_handle h1 = {{0}};
1454 0 : struct smb2_handle h2 = {{0}};
1455 : NTSTATUS status;
1456 0 : bool ret = true;
1457 :
1458 0 : smb2_deltree(tree1, BASEDIR);
1459 0 : smb2_util_mkdir(tree1, BASEDIR);
1460 :
1461 0 : torture_comment(torture, "Creating test file: file1.txt\n");
1462 :
1463 0 : 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 0 : status = smb2_create(tree1, torture, &c1);
1474 0 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1475 : "smb2_create failed\n");
1476 0 : h1 = c1.out.file.handle;
1477 :
1478 0 : torture_comment(torture, "Waitig for 5 secs..\n");
1479 0 : sleep(5);
1480 :
1481 0 : torture_comment(torture, "Creating test file: file2.txt\n");
1482 :
1483 0 : 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 0 : status = smb2_create(tree1, torture, &c2);
1494 0 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1495 : "smb2_create failed\n");
1496 0 : h2 = c2.out.file.handle;
1497 :
1498 0 : torture_comment(torture, "Renaming file1.txt --> tmp1.txt\n");
1499 :
1500 0 : 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 0 : status = smb2_setinfo_file(tree1, &si);
1508 0 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1509 : "smb2_setinfo_file failed\n");
1510 :
1511 0 : torture_comment(torture, "GetInfo of tmp1.txt\n");
1512 :
1513 0 : gi = (union smb_fileinfo) {
1514 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
1515 : .generic.in.file.handle = h1,
1516 : };
1517 :
1518 0 : status = smb2_getinfo_file(tree1, torture, &gi);
1519 0 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1520 : "smb2_getinfo_file failed\n");
1521 :
1522 0 : torture_comment(torture, "Check if timestamps are good after rename(file1.txt --> tmp1.txt).\n");
1523 :
1524 0 : torture_assert_nttime_equal(
1525 : torture, c1.out.write_time, gi.all_info.out.write_time,
1526 : "Bad timestamp\n");
1527 0 : torture_assert_nttime_equal(
1528 : torture, c1.out.change_time, gi.all_info.out.change_time,
1529 : "Bad timestamp\n");
1530 :
1531 0 : torture_comment(torture, "Renaming file2.txt --> file1.txt\n");
1532 :
1533 0 : 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 0 : status = smb2_setinfo_file(tree1, &si);
1540 0 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1541 : "smb2_setinfo_file failed\n");
1542 :
1543 0 : torture_comment(torture, "GetInfo of file1.txt\n");
1544 :
1545 0 : gi = (union smb_fileinfo) {
1546 : .generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION,
1547 : .generic.in.file.handle = h2,
1548 : };
1549 :
1550 0 : status = smb2_getinfo_file(tree1, torture, &gi);
1551 0 : torture_assert_ntstatus_ok_goto(torture, status, ret, done,
1552 : "smb2_getinfo_file failed\n");
1553 :
1554 0 : torture_comment(torture, "Check if timestamps are good after rename(file2.txt --> file1.txt).\n");
1555 :
1556 0 : torture_assert_nttime_equal(
1557 : torture, c2.out.write_time, gi.all_info.out.write_time,
1558 : "Bad timestamp\n");
1559 0 : torture_assert_nttime_equal(
1560 : torture, c2.out.change_time, gi.all_info.out.change_time,
1561 : "Bad timestamp\n");
1562 :
1563 0 : done:
1564 0 : if (!smb2_util_handle_empty(h1)) {
1565 0 : smb2_util_close(tree1, h1);
1566 : }
1567 0 : if (!smb2_util_handle_empty(h2)) {
1568 0 : smb2_util_close(tree1, h2);
1569 : }
1570 0 : smb2_deltree(tree1, BASEDIR);
1571 0 : return ret;
1572 : }
1573 :
1574 0 : static bool test_smb2_close_full_information(struct torture_context *torture,
1575 : struct smb2_tree *tree1,
1576 : struct smb2_tree *tree2)
1577 : {
1578 : union smb_close cl;
1579 0 : struct smb2_create io = {0};
1580 0 : struct smb2_handle h1 = {{0}};
1581 0 : struct smb2_handle h2 = {{0}};
1582 0 : struct smb2_handle h3 = {{0}};
1583 : union smb_setfileinfo sinfo;
1584 : NTSTATUS status;
1585 0 : const char *fname_src = "request.dat";
1586 0 : const char *fname_dst = "renamed.dat";
1587 0 : bool ret = true;
1588 :
1589 : /* Start with a tidy share. */
1590 0 : smb2_util_unlink(tree1, fname_src);
1591 0 : smb2_util_unlink(tree1, fname_dst);
1592 :
1593 : /* Create the test file, and leave it open. */
1594 0 : io.in.fname = fname_src;
1595 0 : io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE;
1596 0 : io.in.create_disposition = NTCREATEX_DISP_CREATE;
1597 0 : io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1598 : NTCREATEX_SHARE_ACCESS_WRITE |
1599 : NTCREATEX_SHARE_ACCESS_DELETE;
1600 0 : status = smb2_create(tree1, tree1, &io);
1601 0 : CHECK_STATUS(status, NT_STATUS_OK);
1602 0 : h1 = io.out.file.handle;
1603 0 : CHECK_CREATED(&io, CREATED, FILE_ATTRIBUTE_ARCHIVE);
1604 :
1605 : /* Open the test file on the second connection. */
1606 0 : ZERO_STRUCT(io);
1607 0 : io.in.fname = fname_src;
1608 0 : io.in.desired_access = SEC_FILE_READ_DATA | SEC_FILE_READ_ATTRIBUTE;
1609 0 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1610 0 : io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1611 : NTCREATEX_SHARE_ACCESS_WRITE |
1612 : NTCREATEX_SHARE_ACCESS_DELETE;
1613 0 : status = smb2_create(tree2, tree2, &io);
1614 0 : CHECK_STATUS(status, NT_STATUS_OK);
1615 0 : h2 = io.out.file.handle;
1616 :
1617 : /* Now open for rename on the first connection. */
1618 0 : ZERO_STRUCT(io);
1619 0 : io.in.fname = fname_src;
1620 0 : io.in.desired_access = SEC_STD_DELETE | SEC_FILE_READ_ATTRIBUTE;
1621 0 : io.in.create_disposition = NTCREATEX_DISP_OPEN;
1622 0 : io.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1623 : NTCREATEX_SHARE_ACCESS_WRITE |
1624 : NTCREATEX_SHARE_ACCESS_DELETE;
1625 0 : status = smb2_create(tree1, tree1, &io);
1626 0 : CHECK_STATUS(status, NT_STATUS_OK);
1627 0 : h3 = io.out.file.handle;
1628 :
1629 : /* Do the rename. */
1630 0 : ZERO_STRUCT(sinfo);
1631 0 : sinfo.rename_information.level = RAW_SFILEINFO_RENAME_INFORMATION;
1632 0 : sinfo.rename_information.in.file.handle = h3;
1633 0 : sinfo.rename_information.in.new_name = fname_dst;
1634 0 : status = smb2_setinfo_file(tree1, &sinfo);
1635 0 : CHECK_STATUS(status, NT_STATUS_OK);
1636 :
1637 : /* And close h3. */
1638 0 : ZERO_STRUCT(cl.smb2);
1639 0 : cl.smb2.level = RAW_CLOSE_SMB2;
1640 0 : cl.smb2.in.file.handle = h3;
1641 0 : status = smb2_close(tree1, &cl.smb2);
1642 0 : CHECK_STATUS(status, NT_STATUS_OK);
1643 0 : ZERO_STRUCT(h3);
1644 :
1645 : /*
1646 : * Close h1 with SMB2_CLOSE_FLAGS_FULL_INFORMATION.
1647 : * Ensure we get data.
1648 : */
1649 0 : ZERO_STRUCT(cl.smb2);
1650 0 : cl.smb2.level = RAW_CLOSE_SMB2;
1651 0 : cl.smb2.in.file.handle = h1;
1652 0 : cl.smb2.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
1653 0 : status = smb2_close(tree1, &cl.smb2);
1654 0 : CHECK_STATUS(status, NT_STATUS_OK);
1655 0 : ZERO_STRUCT(h1);
1656 0 : 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 0 : 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 0 : ZERO_STRUCT(cl.smb2);
1670 0 : cl.smb2.level = RAW_CLOSE_SMB2;
1671 0 : cl.smb2.in.file.handle = h2;
1672 0 : cl.smb2.in.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION;
1673 0 : status = smb2_close(tree2, &cl.smb2);
1674 0 : CHECK_STATUS(status, NT_STATUS_OK);
1675 0 : ZERO_STRUCT(h2);
1676 0 : CHECK_VAL(cl.smb2.out.file_attr, 0x20);
1677 :
1678 0 : done:
1679 :
1680 0 : if (h1.data[0] != 0 || h1.data[1] != 0) {
1681 0 : smb2_util_close(tree1, h1);
1682 : }
1683 0 : if (h2.data[0] != 0 || h2.data[1] != 0) {
1684 0 : smb2_util_close(tree2, h2);
1685 : }
1686 0 : if (h3.data[0] != 0 || h3.data[1] != 0) {
1687 0 : smb2_util_close(tree1, h3);
1688 : }
1689 :
1690 0 : smb2_util_unlink(tree1, fname_src);
1691 0 : smb2_util_unlink(tree1, fname_dst);
1692 :
1693 0 : return ret;
1694 : }
1695 :
1696 : /*
1697 : basic testing of SMB2 rename
1698 : */
1699 966 : struct torture_suite *torture_smb2_rename_init(TALLOC_CTX *ctx)
1700 : {
1701 : struct torture_suite *suite =
1702 966 : torture_suite_create(ctx, "rename");
1703 :
1704 966 : torture_suite_add_1smb2_test(suite, "simple",
1705 : torture_smb2_rename_simple);
1706 :
1707 966 : torture_suite_add_1smb2_test(suite, "simple_modtime",
1708 : torture_smb2_rename_simple_modtime);
1709 :
1710 966 : torture_suite_add_1smb2_test(suite, "simple_nodelete",
1711 : torture_smb2_rename_simple2);
1712 :
1713 966 : torture_suite_add_1smb2_test(suite, "no_sharing",
1714 : torture_smb2_rename_no_sharemode);
1715 :
1716 966 : torture_suite_add_1smb2_test(suite,
1717 : "share_delete_and_delete_access",
1718 : torture_smb2_rename_with_delete_access);
1719 :
1720 966 : torture_suite_add_1smb2_test(suite,
1721 : "no_share_delete_but_delete_access",
1722 : torture_smb2_rename_with_delete_access2);
1723 :
1724 966 : torture_suite_add_1smb2_test(suite,
1725 : "share_delete_no_delete_access",
1726 : torture_smb2_rename_no_delete_access);
1727 :
1728 966 : torture_suite_add_1smb2_test(suite,
1729 : "no_share_delete_no_delete_access",
1730 : torture_smb2_rename_no_delete_access2);
1731 :
1732 966 : torture_suite_add_1smb2_test(suite,
1733 : "msword",
1734 : torture_smb2_rename_msword);
1735 :
1736 966 : torture_suite_add_1smb2_test(
1737 : suite, "rename_dir_openfile",
1738 : torture_smb2_rename_dir_openfile);
1739 :
1740 966 : torture_suite_add_1smb2_test(suite,
1741 : "rename_dir_bench",
1742 : torture_smb2_rename_dir_bench);
1743 :
1744 966 : torture_suite_add_2smb2_test(suite,
1745 : "close-full-information",
1746 : test_smb2_close_full_information);
1747 :
1748 966 : suite->description = talloc_strdup(suite, "smb2.rename tests");
1749 :
1750 966 : return suite;
1751 : }
|