1 /*
2 Unix SMB/CIFS implementation.
3 rename test suite
4 Copyright (C) Andrew Tridgell 2003
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "libcli/libcli.h"
25 #include "torture/util.h"
26
27 #define CHECK_STATUS(status, correct) do { \
28 if (!NT_STATUS_EQUAL(status, correct)) { \
29 printf("(%s) Incorrect status %s - should be %s\n", \
30 __location__, nt_errstr(status), nt_errstr(correct)); \
31 ret = False; \
32 goto done; \
33 }} while (0)
34
35 #define CHECK_VALUE(v, correct) do { \
36 if ((v) != (correct)) { \
37 printf("(%s) Incorrect %s %d - should be %d\n", \
38 __location__, #v, (int)v, (int)correct); \
39 ret = False; \
40 }} while (0)
41
42 #define BASEDIR "\\testrename"
43
44 /*
45 test SMBmv ops
46 */
test_mv(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)47 static BOOL test_mv(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
48 {
49 union smb_rename io;
50 NTSTATUS status;
51 BOOL ret = True;
52 int fnum = -1;
53 const char *fname1 = BASEDIR "\\test1.txt";
54 const char *fname2 = BASEDIR "\\test2.txt";
55 union smb_open op;
56
57 printf("Testing SMBmv\n");
58
59 if (!torture_setup_dir(cli, BASEDIR)) {
60 return False;
61 }
62
63 printf("Trying simple rename\n");
64
65 op.generic.level = RAW_OPEN_NTCREATEX;
66 op.ntcreatex.in.root_fid = 0;
67 op.ntcreatex.in.flags = 0;
68 op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
69 op.ntcreatex.in.create_options = 0;
70 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
71 op.ntcreatex.in.share_access =
72 NTCREATEX_SHARE_ACCESS_READ |
73 NTCREATEX_SHARE_ACCESS_WRITE;
74 op.ntcreatex.in.alloc_size = 0;
75 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
76 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
77 op.ntcreatex.in.security_flags = 0;
78 op.ntcreatex.in.fname = fname1;
79
80 status = smb_raw_open(cli->tree, mem_ctx, &op);
81 CHECK_STATUS(status, NT_STATUS_OK);
82 fnum = op.ntcreatex.out.file.fnum;
83
84 io.generic.level = RAW_RENAME_RENAME;
85 io.rename.in.pattern1 = fname1;
86 io.rename.in.pattern2 = fname2;
87 io.rename.in.attrib = 0;
88
89 printf("trying rename while first file open\n");
90 status = smb_raw_rename(cli->tree, &io);
91 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
92
93 smbcli_close(cli->tree, fnum);
94
95 op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
96 op.ntcreatex.in.share_access =
97 NTCREATEX_SHARE_ACCESS_DELETE |
98 NTCREATEX_SHARE_ACCESS_READ |
99 NTCREATEX_SHARE_ACCESS_WRITE;
100 status = smb_raw_open(cli->tree, mem_ctx, &op);
101 CHECK_STATUS(status, NT_STATUS_OK);
102 fnum = op.ntcreatex.out.file.fnum;
103
104 printf("trying rename while first file open with SHARE_ACCESS_DELETE\n");
105 status = smb_raw_rename(cli->tree, &io);
106 CHECK_STATUS(status, NT_STATUS_OK);
107
108 io.rename.in.pattern1 = fname2;
109 io.rename.in.pattern2 = fname1;
110 status = smb_raw_rename(cli->tree, &io);
111 CHECK_STATUS(status, NT_STATUS_OK);
112
113 io.rename.in.pattern1 = fname1;
114 io.rename.in.pattern2 = fname2;
115
116 printf("trying rename while not open\n");
117 smb_raw_exit(cli->session);
118 status = smb_raw_rename(cli->tree, &io);
119 CHECK_STATUS(status, NT_STATUS_OK);
120
121 printf("Trying self rename\n");
122 io.rename.in.pattern1 = fname2;
123 io.rename.in.pattern2 = fname2;
124 status = smb_raw_rename(cli->tree, &io);
125 CHECK_STATUS(status, NT_STATUS_OK);
126
127 io.rename.in.pattern1 = fname1;
128 io.rename.in.pattern2 = fname1;
129 status = smb_raw_rename(cli->tree, &io);
130 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
131
132
133 printf("trying wildcard rename\n");
134 io.rename.in.pattern1 = BASEDIR "\\*.txt";
135 io.rename.in.pattern2 = fname1;
136
137 status = smb_raw_rename(cli->tree, &io);
138 CHECK_STATUS(status, NT_STATUS_OK);
139
140 printf("and again\n");
141 status = smb_raw_rename(cli->tree, &io);
142 CHECK_STATUS(status, NT_STATUS_OK);
143
144 printf("Trying extension change\n");
145 io.rename.in.pattern1 = BASEDIR "\\*.txt";
146 io.rename.in.pattern2 = BASEDIR "\\*.bak";
147 status = smb_raw_rename(cli->tree, &io);
148 CHECK_STATUS(status, NT_STATUS_OK);
149
150 status = smb_raw_rename(cli->tree, &io);
151 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
152
153 printf("Checking attrib handling\n");
154 torture_set_file_attribute(cli->tree, BASEDIR "\\test1.bak", FILE_ATTRIBUTE_HIDDEN);
155 io.rename.in.pattern1 = BASEDIR "\\test1.bak";
156 io.rename.in.pattern2 = BASEDIR "\\*.txt";
157 io.rename.in.attrib = 0;
158 status = smb_raw_rename(cli->tree, &io);
159 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
160
161 io.rename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
162 status = smb_raw_rename(cli->tree, &io);
163 CHECK_STATUS(status, NT_STATUS_OK);
164
165 done:
166 smbcli_close(cli->tree, fnum);
167 smb_raw_exit(cli->session);
168 smbcli_deltree(cli->tree, BASEDIR);
169 return ret;
170 }
171
172
173
174 /*
175 test SMBntrename ops
176 */
test_ntrename(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)177 static BOOL test_ntrename(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
178 {
179 union smb_rename io;
180 NTSTATUS status;
181 BOOL ret = True;
182 int fnum, i;
183 const char *fname1 = BASEDIR "\\test1.txt";
184 const char *fname2 = BASEDIR "\\test2.txt";
185 union smb_fileinfo finfo;
186
187 printf("Testing SMBntrename\n");
188
189 if (!torture_setup_dir(cli, BASEDIR)) {
190 return False;
191 }
192
193 printf("Trying simple rename\n");
194
195 fnum = create_complex_file(cli, mem_ctx, fname1);
196
197 io.generic.level = RAW_RENAME_NTRENAME;
198 io.ntrename.in.old_name = fname1;
199 io.ntrename.in.new_name = fname2;
200 io.ntrename.in.attrib = 0;
201 io.ntrename.in.cluster_size = 0;
202 io.ntrename.in.flags = RENAME_FLAG_RENAME;
203
204 status = smb_raw_rename(cli->tree, &io);
205 CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
206
207 smb_raw_exit(cli->session);
208 status = smb_raw_rename(cli->tree, &io);
209 CHECK_STATUS(status, NT_STATUS_OK);
210
211 printf("Trying self rename\n");
212 io.ntrename.in.old_name = fname2;
213 io.ntrename.in.new_name = fname2;
214 status = smb_raw_rename(cli->tree, &io);
215 CHECK_STATUS(status, NT_STATUS_OK);
216
217 io.ntrename.in.old_name = fname1;
218 io.ntrename.in.new_name = fname1;
219 status = smb_raw_rename(cli->tree, &io);
220 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
221
222 printf("trying wildcard rename\n");
223 io.ntrename.in.old_name = BASEDIR "\\*.txt";
224 io.ntrename.in.new_name = fname1;
225
226 status = smb_raw_rename(cli->tree, &io);
227 CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
228
229 printf("Checking attrib handling\n");
230 torture_set_file_attribute(cli->tree, fname2, FILE_ATTRIBUTE_HIDDEN);
231 io.ntrename.in.old_name = fname2;
232 io.ntrename.in.new_name = fname1;
233 io.ntrename.in.attrib = 0;
234 status = smb_raw_rename(cli->tree, &io);
235 CHECK_STATUS(status, NT_STATUS_NO_SUCH_FILE);
236
237 io.ntrename.in.attrib = FILE_ATTRIBUTE_HIDDEN;
238 status = smb_raw_rename(cli->tree, &io);
239 CHECK_STATUS(status, NT_STATUS_OK);
240
241 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
242
243 printf("Checking hard link\n");
244 io.ntrename.in.old_name = fname1;
245 io.ntrename.in.new_name = fname2;
246 io.ntrename.in.attrib = 0;
247 io.ntrename.in.flags = RENAME_FLAG_HARD_LINK;
248 status = smb_raw_rename(cli->tree, &io);
249 CHECK_STATUS(status, NT_STATUS_OK);
250
251 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
252
253 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
254 finfo.generic.in.file.path = fname2;
255 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
256 CHECK_STATUS(status, NT_STATUS_OK);
257 CHECK_VALUE(finfo.all_info.out.nlink, 2);
258 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
259
260 finfo.generic.in.file.path = fname1;
261 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
262 CHECK_STATUS(status, NT_STATUS_OK);
263 CHECK_VALUE(finfo.all_info.out.nlink, 2);
264 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
265
266 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
267
268 smbcli_unlink(cli->tree, fname2);
269
270 finfo.generic.in.file.path = fname1;
271 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
272 CHECK_STATUS(status, NT_STATUS_OK);
273 CHECK_VALUE(finfo.all_info.out.nlink, 1);
274 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
275
276 printf("Checking copy\n");
277 io.ntrename.in.old_name = fname1;
278 io.ntrename.in.new_name = fname2;
279 io.ntrename.in.attrib = 0;
280 io.ntrename.in.flags = RENAME_FLAG_COPY;
281 status = smb_raw_rename(cli->tree, &io);
282 CHECK_STATUS(status, NT_STATUS_OK);
283
284 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
285 finfo.generic.in.file.path = fname1;
286 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
287 CHECK_STATUS(status, NT_STATUS_OK);
288 CHECK_VALUE(finfo.all_info.out.nlink, 1);
289 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
290
291 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
292 finfo.generic.in.file.path = fname2;
293 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
294 CHECK_STATUS(status, NT_STATUS_OK);
295 CHECK_VALUE(finfo.all_info.out.nlink, 1);
296 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
297
298 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_SYSTEM);
299
300 finfo.generic.level = RAW_FILEINFO_ALL_INFO;
301 finfo.generic.in.file.path = fname2;
302 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
303 CHECK_STATUS(status, NT_STATUS_OK);
304 CHECK_VALUE(finfo.all_info.out.nlink, 1);
305 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
306
307 finfo.generic.in.file.path = fname1;
308 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
309 CHECK_STATUS(status, NT_STATUS_OK);
310 CHECK_VALUE(finfo.all_info.out.nlink, 1);
311 CHECK_VALUE(finfo.all_info.out.attrib, FILE_ATTRIBUTE_SYSTEM);
312
313 torture_set_file_attribute(cli->tree, fname1, FILE_ATTRIBUTE_NORMAL);
314
315 smbcli_unlink(cli->tree, fname2);
316
317 finfo.generic.in.file.path = fname1;
318 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
319 CHECK_STATUS(status, NT_STATUS_OK);
320 CHECK_VALUE(finfo.all_info.out.nlink, 1);
321
322 printf("Checking invalid flags\n");
323 io.ntrename.in.old_name = fname1;
324 io.ntrename.in.new_name = fname2;
325 io.ntrename.in.attrib = 0;
326 io.ntrename.in.flags = 0;
327 status = smb_raw_rename(cli->tree, &io);
328 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
329
330 io.ntrename.in.flags = 300;
331 status = smb_raw_rename(cli->tree, &io);
332 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
333
334 io.ntrename.in.flags = 0x106;
335 status = smb_raw_rename(cli->tree, &io);
336 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
337
338 printf("Checking unknown field\n");
339 io.ntrename.in.old_name = fname1;
340 io.ntrename.in.new_name = fname2;
341 io.ntrename.in.attrib = 0;
342 io.ntrename.in.flags = RENAME_FLAG_RENAME;
343 io.ntrename.in.cluster_size = 0xff;
344 status = smb_raw_rename(cli->tree, &io);
345 CHECK_STATUS(status, NT_STATUS_OK);
346
347 printf("Trying RENAME_FLAG_MOVE_CLUSTER_INFORMATION\n");
348
349 io.ntrename.in.old_name = fname2;
350 io.ntrename.in.new_name = fname1;
351 io.ntrename.in.attrib = 0;
352 io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
353 io.ntrename.in.cluster_size = 1;
354 status = smb_raw_rename(cli->tree, &io);
355 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
356
357 io.ntrename.in.flags = RENAME_FLAG_COPY;
358 status = smb_raw_rename(cli->tree, &io);
359 CHECK_STATUS(status, NT_STATUS_OK);
360
361 #if 0
362 {
363 char buf[16384];
364 fnum = smbcli_open(cli->tree, fname1, O_RDWR, DENY_NONE);
365 memset(buf, 1, sizeof(buf));
366 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
367 smbcli_close(cli->tree, fnum);
368
369 fnum = smbcli_open(cli->tree, fname2, O_RDWR, DENY_NONE);
370 memset(buf, 1, sizeof(buf));
371 smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf)-1);
372 smbcli_close(cli->tree, fnum);
373
374 torture_all_info(cli->tree, fname1);
375 torture_all_info(cli->tree, fname2);
376 }
377
378
379 io.ntrename.in.flags = RENAME_FLAG_MOVE_CLUSTER_INFORMATION;
380 status = smb_raw_rename(cli->tree, &io);
381 CHECK_STATUS(status, NT_STATUS_INVALID_PARAMETER);
382
383 for (i=0;i<20000;i++) {
384 io.ntrename.in.cluster_size = i;
385 status = smb_raw_rename(cli->tree, &io);
386 if (!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
387 printf("i=%d status=%s\n", i, nt_errstr(status));
388 }
389 }
390 #endif
391
392 printf("Checking other flags\n");
393
394 for (i=0;i<0xFFF;i++) {
395 if (i == RENAME_FLAG_RENAME ||
396 i == RENAME_FLAG_HARD_LINK ||
397 i == RENAME_FLAG_COPY) {
398 continue;
399 }
400
401 io.ntrename.in.old_name = fname2;
402 io.ntrename.in.new_name = fname1;
403 io.ntrename.in.flags = i;
404 io.ntrename.in.attrib = 0;
405 io.ntrename.in.cluster_size = 0;
406 status = smb_raw_rename(cli->tree, &io);
407 if (!NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
408 printf("flags=0x%x status=%s\n", i, nt_errstr(status));
409 }
410 }
411
412 done:
413 smb_raw_exit(cli->session);
414 smbcli_deltree(cli->tree, BASEDIR);
415 return ret;
416 }
417
418
419 /*
420 basic testing of rename calls
421 */
torture_raw_rename(struct torture_context * torture)422 BOOL torture_raw_rename(struct torture_context *torture)
423 {
424 struct smbcli_state *cli;
425 BOOL ret = True;
426 TALLOC_CTX *mem_ctx;
427
428 if (!torture_open_connection(&cli, 0)) {
429 return False;
430 }
431
432 mem_ctx = talloc_init("torture_raw_rename");
433
434 if (!test_mv(cli, mem_ctx)) {
435 ret = False;
436 }
437
438 if (!test_ntrename(cli, mem_ctx)) {
439 ret = False;
440 }
441
442 torture_close_connection(cli);
443 talloc_free(mem_ctx);
444 return ret;
445 }
446