Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : RAW_SFILEINFO_* individual 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 3 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, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "system/time.h"
22 : #include "libcli/raw/libcliraw.h"
23 : #include "libcli/libcli.h"
24 : #include "torture/util.h"
25 : #include "torture/raw/proto.h"
26 :
27 : #define BASEDIR "\\testsfileinfo"
28 :
29 : /* basic testing of all RAW_SFILEINFO_* calls
30 : for each call we test that it succeeds, and where possible test
31 : for consistency between the calls.
32 : */
33 : static bool
34 1 : torture_raw_sfileinfo_base(struct torture_context *torture, struct smbcli_state *cli)
35 : {
36 1 : bool ret = true;
37 1 : int fnum = -1;
38 0 : char *fnum_fname;
39 0 : char *path_fname;
40 0 : char *path_fname_new;
41 0 : union smb_fileinfo finfo1, finfo2;
42 0 : union smb_setfileinfo sfinfo;
43 0 : NTSTATUS status, status2;
44 0 : const char *call_name;
45 1 : time_t basetime = (time(NULL) - 86400) & ~1;
46 0 : bool check_fnum;
47 1 : int n = time(NULL) % 100;
48 :
49 1 : path_fname = talloc_asprintf(torture, BASEDIR "\\fname_test_%d.txt", n);
50 1 : path_fname_new = talloc_asprintf(torture, BASEDIR "\\fname_test_new_%d.txt", n);
51 1 : fnum_fname = talloc_asprintf(torture, BASEDIR "\\fnum_test_%d.txt", n);
52 :
53 1 : torture_assert(torture, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
54 :
55 : #define RECREATE_FILE(fname) do { \
56 : if (fnum != -1) smbcli_close(cli->tree, fnum); \
57 : fnum = create_complex_file(cli, torture, fname); \
58 : if (fnum == -1) { \
59 : printf("(%s) ERROR: open of %s failed (%s)\n", \
60 : __location__, fname, smbcli_errstr(cli->tree)); \
61 : ret = false; \
62 : goto done; \
63 : }} while (0)
64 :
65 : #define RECREATE_BOTH do { \
66 : RECREATE_FILE(path_fname); \
67 : smbcli_close(cli->tree, fnum); \
68 : RECREATE_FILE(fnum_fname); \
69 : } while (0)
70 :
71 1 : RECREATE_BOTH;
72 :
73 : #define CHECK_CALL_FNUM(call, rightstatus) do { \
74 : check_fnum = true; \
75 : call_name = #call; \
76 : sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
77 : sfinfo.generic.in.file.fnum = fnum; \
78 : status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
79 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
80 : torture_warning(torture, \
81 : "(%s) %s - %s", __location__, #call, \
82 : nt_errstr(status)); \
83 : } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
84 : printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
85 : nt_errstr(status), nt_errstr(rightstatus)); \
86 : ret = false; \
87 : } \
88 : finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
89 : finfo1.generic.in.file.fnum = fnum; \
90 : status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \
91 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
92 : torture_warning(torture, \
93 : "(%s) %s - %s", __location__, #call, \
94 : nt_errstr(status)); \
95 : } else if (!NT_STATUS_IS_OK(status2)) { \
96 : printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
97 : ret = false; \
98 : }} while (0)
99 :
100 : #define CHECK_CALL_PATH(call, rightstatus) do { \
101 : check_fnum = false; \
102 : call_name = #call; \
103 : sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
104 : sfinfo.generic.in.file.path = path_fname; \
105 : status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
106 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
107 : sfinfo.generic.in.file.path = path_fname_new; \
108 : status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
109 : } \
110 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
111 : torture_warning(torture, \
112 : "(%s) %s - %s", __location__, #call, \
113 : nt_errstr(status)); \
114 : } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
115 : printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
116 : nt_errstr(status), nt_errstr(rightstatus)); \
117 : ret = false; \
118 : } \
119 : finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
120 : finfo1.generic.in.file.path = path_fname; \
121 : status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
122 : if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
123 : finfo1.generic.in.file.path = path_fname_new; \
124 : status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
125 : } \
126 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
127 : torture_warning(torture, \
128 : "(%s) %s - %s", __location__, #call, \
129 : nt_errstr(status)); \
130 : } else if (!NT_STATUS_IS_OK(status2)) { \
131 : printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status2)); \
132 : ret = false; \
133 : }} while (0)
134 :
135 : #define CHECK1(call) \
136 : do { if (NT_STATUS_IS_OK(status)) { \
137 : finfo2.generic.level = RAW_FILEINFO_ ## call; \
138 : if (check_fnum) { \
139 : finfo2.generic.in.file.fnum = fnum; \
140 : status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \
141 : } else { \
142 : finfo2.generic.in.file.path = path_fname; \
143 : status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
144 : if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
145 : finfo2.generic.in.file.path = path_fname_new; \
146 : status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
147 : } \
148 : } \
149 : if (!NT_STATUS_IS_OK(status2)) { \
150 : printf("%s - %s\n", #call, nt_errstr(status2)); \
151 : ret = false; \
152 : } \
153 : }} while (0)
154 :
155 : #define CHECK_VALUE(call, stype, field, value) do { \
156 : CHECK1(call); \
157 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
158 : printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
159 : call_name, #stype, #field, \
160 : (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
161 : dump_all_info(torture, &finfo1); \
162 : ret = false; \
163 : }} while (0)
164 :
165 : #define CHECK_TIME(call, stype, field, value) do { \
166 : CHECK1(call); \
167 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
168 : printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
169 : call_name, #stype, #field, \
170 : (unsigned int)value, \
171 : (unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \
172 : printf("\t%s", timestring(torture, value)); \
173 : printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
174 : dump_all_info(torture, &finfo1); \
175 : ret = false; \
176 : }} while (0)
177 :
178 : #define CHECK_STR(call, stype, field, value) do { \
179 : CHECK1(call); \
180 : if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \
181 : printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \
182 : call_name, #stype, #field, \
183 : value, \
184 : finfo2.stype.out.field); \
185 : dump_all_info(torture, &finfo1); \
186 : ret = false; \
187 : }} while (0)
188 :
189 : #define CHECK_STATUS(status, correct) do { \
190 : if (!NT_STATUS_EQUAL(status, correct)) { \
191 : printf("(%s) Incorrect status %s - should be %s\n", \
192 : __location__, nt_errstr(status), nt_errstr(correct)); \
193 : ret = false; \
194 : goto done; \
195 : }} while (0)
196 :
197 :
198 1 : printf("Test setattr\n");
199 1 : sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_READONLY;
200 1 : sfinfo.setattr.in.write_time = basetime;
201 2 : CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
202 2 : CHECK_VALUE (ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY);
203 2 : CHECK_TIME (ALL_INFO, all_info, write_time, basetime);
204 :
205 1 : printf("setting to NORMAL doesn't do anything\n");
206 1 : sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_NORMAL;
207 1 : sfinfo.setattr.in.write_time = 0;
208 2 : CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
209 2 : CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY);
210 2 : CHECK_TIME (ALL_INFO, all_info, write_time, basetime);
211 :
212 1 : printf("a zero write_time means don't change\n");
213 1 : sfinfo.setattr.in.attrib = 0;
214 1 : sfinfo.setattr.in.write_time = 0;
215 2 : CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
216 2 : CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
217 2 : CHECK_TIME (ALL_INFO, all_info, write_time, basetime);
218 :
219 1 : printf("Test setattre\n");
220 1 : sfinfo.setattre.in.create_time = basetime + 20;
221 1 : sfinfo.setattre.in.access_time = basetime + 30;
222 1 : sfinfo.setattre.in.write_time = basetime + 40;
223 2 : CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK);
224 1 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20);
225 1 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30);
226 1 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 40);
227 :
228 1 : sfinfo.setattre.in.create_time = 0;
229 1 : sfinfo.setattre.in.access_time = 0;
230 1 : sfinfo.setattre.in.write_time = 0;
231 2 : CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK);
232 1 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20);
233 1 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30);
234 1 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 40);
235 :
236 1 : printf("Test standard level\n");
237 1 : sfinfo.standard.in.create_time = basetime + 100;
238 1 : sfinfo.standard.in.access_time = basetime + 200;
239 1 : sfinfo.standard.in.write_time = basetime + 300;
240 2 : CHECK_CALL_FNUM(STANDARD, NT_STATUS_OK);
241 1 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
242 1 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
243 1 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
244 :
245 1 : printf("Test basic_info level\n");
246 1 : basetime += 86400;
247 1 : unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
248 1 : unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
249 1 : unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime + 300);
250 1 : unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
251 1 : sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
252 2 : CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK);
253 1 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
254 1 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
255 1 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
256 1 : CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
257 1 : CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY);
258 :
259 1 : printf("a zero time means don't change\n");
260 1 : unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
261 1 : unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
262 1 : unix_to_nt_time(&sfinfo.basic_info.in.write_time, 0);
263 1 : unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
264 1 : sfinfo.basic_info.in.attrib = 0;
265 2 : CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK);
266 1 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
267 1 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
268 1 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
269 1 : CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
270 1 : CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_READONLY);
271 :
272 1 : printf("Test basic_information level\n");
273 1 : basetime += 86400;
274 1 : unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
275 1 : unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
276 1 : unix_to_nt_time(&sfinfo.basic_info.in.write_time, basetime + 300);
277 1 : unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
278 1 : sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
279 2 : CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK);
280 1 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
281 1 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
282 1 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
283 1 : CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
284 1 : CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
285 :
286 2 : CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK);
287 2 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
288 2 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
289 2 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
290 2 : CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
291 2 : CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
292 :
293 1 : torture_comment(torture, "try to change a file to a directory\n");
294 1 : sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
295 2 : CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_INVALID_PARAMETER);
296 :
297 1 : printf("a zero time means don't change\n");
298 1 : unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
299 1 : unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
300 1 : unix_to_nt_time(&sfinfo.basic_info.in.write_time, 0);
301 1 : unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
302 1 : sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
303 2 : CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK);
304 1 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
305 1 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
306 1 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
307 1 : CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
308 1 : CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
309 :
310 2 : CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK);
311 2 : CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
312 2 : CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
313 2 : CHECK_TIME(ALL_INFO, all_info, write_time, basetime + 300);
314 :
315 : /* interesting - w2k3 leaves change_time as current time for 0 change time
316 : in setpathinfo
317 : CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
318 : */
319 2 : CHECK_VALUE(ALL_INFO, all_info, attrib, FILE_ATTRIBUTE_NORMAL);
320 :
321 1 : printf("Test disposition_info level\n");
322 1 : sfinfo.disposition_info.in.delete_on_close = 1;
323 2 : CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
324 1 : CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
325 1 : CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
326 :
327 1 : sfinfo.disposition_info.in.delete_on_close = 0;
328 2 : CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
329 1 : CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
330 1 : CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
331 :
332 1 : printf("Test disposition_information level\n");
333 1 : sfinfo.disposition_info.in.delete_on_close = 1;
334 2 : CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK);
335 1 : CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
336 1 : CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
337 :
338 : /* this would delete the file! */
339 : /*
340 : CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
341 : CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
342 : CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
343 : */
344 :
345 1 : sfinfo.disposition_info.in.delete_on_close = 0;
346 2 : CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK);
347 1 : CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
348 1 : CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
349 :
350 2 : CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
351 2 : CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
352 2 : CHECK_VALUE(ALL_INFO, all_info, nlink, 1);
353 :
354 1 : printf("Test allocation_info level\n");
355 1 : sfinfo.allocation_info.in.alloc_size = 0;
356 2 : CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK);
357 1 : CHECK_VALUE(ALL_INFO, all_info, size, 0);
358 1 : CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
359 :
360 1 : sfinfo.allocation_info.in.alloc_size = 4096;
361 2 : CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK);
362 1 : CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096);
363 1 : CHECK_VALUE(ALL_INFO, all_info, size, 0);
364 :
365 1 : RECREATE_BOTH;
366 1 : sfinfo.allocation_info.in.alloc_size = 0;
367 2 : CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK);
368 1 : CHECK_VALUE(ALL_INFO, all_info, size, 0);
369 1 : CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
370 :
371 2 : CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK);
372 2 : CHECK_VALUE(ALL_INFO, all_info, size, 0);
373 2 : CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
374 :
375 1 : sfinfo.allocation_info.in.alloc_size = 4096;
376 2 : CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK);
377 1 : CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096);
378 1 : CHECK_VALUE(ALL_INFO, all_info, size, 0);
379 :
380 : /* setting the allocation size up via setpathinfo seems
381 : to be broken in w2k3 */
382 2 : CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK);
383 2 : CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
384 2 : CHECK_VALUE(ALL_INFO, all_info, size, 0);
385 :
386 1 : printf("Test end_of_file_info level\n");
387 1 : sfinfo.end_of_file_info.in.size = 37;
388 2 : CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK);
389 1 : CHECK_VALUE(ALL_INFO, all_info, size, 37);
390 :
391 1 : sfinfo.end_of_file_info.in.size = 7;
392 2 : CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK);
393 1 : CHECK_VALUE(ALL_INFO, all_info, size, 7);
394 :
395 1 : sfinfo.end_of_file_info.in.size = 37;
396 2 : CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK);
397 1 : CHECK_VALUE(ALL_INFO, all_info, size, 37);
398 :
399 2 : CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
400 2 : CHECK_VALUE(ALL_INFO, all_info, size, 37);
401 :
402 1 : sfinfo.end_of_file_info.in.size = 7;
403 2 : CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK);
404 1 : CHECK_VALUE(ALL_INFO, all_info, size, 7);
405 :
406 2 : CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
407 2 : CHECK_VALUE(ALL_INFO, all_info, size, 7);
408 :
409 1 : printf("Test position_information level\n");
410 1 : sfinfo.position_information.in.position = 123456;
411 2 : CHECK_CALL_FNUM(POSITION_INFORMATION, NT_STATUS_OK);
412 1 : CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);
413 :
414 2 : CHECK_CALL_PATH(POSITION_INFORMATION, NT_STATUS_OK);
415 2 : CHECK_VALUE(POSITION_INFORMATION, position_information, position, 0);
416 :
417 1 : printf("Test mode_information level\n");
418 1 : sfinfo.mode_information.in.mode = 2;
419 2 : CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK);
420 1 : CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);
421 :
422 2 : CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
423 2 : CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
424 :
425 1 : sfinfo.mode_information.in.mode = 1;
426 2 : CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
427 2 : CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
428 :
429 1 : sfinfo.mode_information.in.mode = 0;
430 2 : CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK);
431 1 : CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
432 :
433 2 : CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
434 2 : CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);
435 :
436 : #if 0
437 : printf("Test unix_basic level\n");
438 : CHECK_CALL_FNUM(UNIX_BASIC, NT_STATUS_OK);
439 : CHECK_CALL_PATH(UNIX_BASIC, NT_STATUS_OK);
440 :
441 : printf("Test unix_link level\n");
442 : CHECK_CALL_FNUM(UNIX_LINK, NT_STATUS_OK);
443 : CHECK_CALL_PATH(UNIX_LINK, NT_STATUS_OK);
444 : #endif
445 :
446 1 : done:
447 1 : smb_raw_exit(cli->session);
448 1 : smbcli_close(cli->tree, fnum);
449 1 : if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fnum_fname))) {
450 0 : printf("Failed to delete %s - %s\n", fnum_fname, smbcli_errstr(cli->tree));
451 : }
452 1 : if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) {
453 0 : printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree));
454 : }
455 :
456 1 : return ret;
457 : }
458 :
459 : /*
460 : * basic testing of all RAW_SFILEINFO_RENAME call
461 : */
462 : static bool
463 5 : torture_raw_sfileinfo_rename(struct torture_context *torture,
464 : struct smbcli_state *cli)
465 : {
466 5 : bool ret = true;
467 5 : int fnum_saved, d_fnum, fnum2, fnum = -1;
468 0 : char *fnum_fname;
469 0 : char *fnum_fname_new;
470 0 : char *path_fname;
471 0 : char *path_fname_new;
472 0 : char *path_dname;
473 0 : char *path_dname_new;
474 0 : char *saved_name;
475 0 : char *saved_name_new;
476 0 : union smb_fileinfo finfo1, finfo2;
477 0 : union smb_setfileinfo sfinfo;
478 0 : NTSTATUS status, status2;
479 0 : const char *call_name;
480 0 : bool check_fnum;
481 5 : int n = time(NULL) % 100;
482 :
483 5 : path_fname = talloc_asprintf(torture, BASEDIR "\\fname_test_%d.txt", n);
484 5 : path_fname_new = talloc_asprintf(torture, BASEDIR "\\fname_test_new_%d.txt", n);
485 5 : fnum_fname = talloc_asprintf(torture, BASEDIR "\\fnum_test_%d.txt", n);
486 5 : fnum_fname_new = talloc_asprintf(torture, BASEDIR "\\fnum_test_new_%d.txt", n);
487 5 : path_dname = talloc_asprintf(torture, BASEDIR "\\dname_test_%d", n);
488 5 : path_dname_new = talloc_asprintf(torture, BASEDIR "\\dname_test_new_%d", n);
489 :
490 5 : torture_assert(torture, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
491 :
492 5 : RECREATE_BOTH;
493 :
494 5 : ZERO_STRUCT(sfinfo);
495 :
496 5 : smbcli_close(cli->tree, create_complex_file(cli, torture, fnum_fname_new));
497 5 : smbcli_close(cli->tree, create_complex_file(cli, torture, path_fname_new));
498 :
499 5 : sfinfo.rename_information.in.overwrite = 0;
500 5 : sfinfo.rename_information.in.root_fid = 0;
501 5 : sfinfo.rename_information.in.new_name = fnum_fname_new+strlen(BASEDIR)+1;
502 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OBJECT_NAME_COLLISION);
503 :
504 5 : sfinfo.rename_information.in.new_name = path_fname_new+strlen(BASEDIR)+1;
505 10 : CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OBJECT_NAME_COLLISION);
506 :
507 5 : sfinfo.rename_information.in.new_name = fnum_fname_new;
508 5 : sfinfo.rename_information.in.overwrite = 1;
509 5 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_NOT_SUPPORTED);
510 :
511 5 : sfinfo.rename_information.in.new_name = fnum_fname_new+strlen(BASEDIR)+1;
512 5 : sfinfo.rename_information.in.overwrite = 1;
513 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
514 5 : CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname_new);
515 :
516 5 : printf("Trying rename with dest file open\n");
517 5 : fnum2 = create_complex_file(cli, torture, fnum_fname);
518 5 : sfinfo.rename_information.in.new_name = fnum_fname+strlen(BASEDIR)+1;
519 5 : sfinfo.rename_information.in.overwrite = 1;
520 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_ACCESS_DENIED);
521 5 : CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname_new);
522 :
523 5 : fnum_saved = fnum;
524 5 : fnum = fnum2;
525 5 : sfinfo.disposition_info.in.delete_on_close = 1;
526 10 : CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
527 5 : fnum = fnum_saved;
528 :
529 5 : printf("Trying rename with dest file open and delete_on_close\n");
530 5 : sfinfo.rename_information.in.new_name = fnum_fname+strlen(BASEDIR)+1;
531 5 : sfinfo.rename_information.in.overwrite = 1;
532 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_ACCESS_DENIED);
533 :
534 5 : smbcli_close(cli->tree, fnum2);
535 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
536 5 : CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
537 :
538 5 : printf("Trying rename with source file open twice\n");
539 5 : sfinfo.rename_information.in.new_name = fnum_fname+strlen(BASEDIR)+1;
540 5 : sfinfo.rename_information.in.overwrite = 1;
541 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
542 5 : CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
543 :
544 5 : fnum2 = create_complex_file(cli, torture, fnum_fname);
545 5 : sfinfo.rename_information.in.new_name = fnum_fname_new+strlen(BASEDIR)+1;
546 5 : sfinfo.rename_information.in.overwrite = 0;
547 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
548 5 : CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname_new);
549 5 : smbcli_close(cli->tree, fnum2);
550 :
551 5 : sfinfo.rename_information.in.new_name = fnum_fname+strlen(BASEDIR)+1;
552 5 : sfinfo.rename_information.in.overwrite = 0;
553 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
554 5 : CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
555 :
556 5 : sfinfo.rename_information.in.new_name = path_fname_new+strlen(BASEDIR)+1;
557 5 : sfinfo.rename_information.in.overwrite = 1;
558 10 : CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
559 10 : CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
560 :
561 5 : sfinfo.rename_information.in.new_name = fnum_fname+strlen(BASEDIR)+1;
562 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
563 5 : CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
564 :
565 5 : sfinfo.rename_information.in.new_name = path_fname+strlen(BASEDIR)+1;
566 10 : CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
567 10 : CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
568 :
569 5 : printf("Trying rename with a root fid\n");
570 5 : status = create_directory_handle(cli->tree, BASEDIR, &d_fnum);
571 5 : CHECK_STATUS(status, NT_STATUS_OK);
572 5 : sfinfo.rename_information.in.new_name = fnum_fname_new+strlen(BASEDIR)+1;
573 5 : sfinfo.rename_information.in.root_fid = d_fnum;
574 10 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_INVALID_PARAMETER);
575 5 : CHECK_STR(NAME_INFO, name_info, fname.s, fnum_fname);
576 5 : smbcli_close(cli->tree, d_fnum);
577 :
578 5 : printf("Trying rename directory\n");
579 5 : if (!torture_setup_dir(cli, path_dname)) {
580 0 : ret = false;
581 0 : goto done;
582 : }
583 5 : saved_name = path_fname;
584 5 : saved_name_new = path_fname_new;
585 5 : path_fname = path_dname;
586 5 : path_fname_new = path_dname_new;
587 5 : sfinfo.rename_information.in.new_name = path_dname_new+strlen(BASEDIR)+1;
588 5 : sfinfo.rename_information.in.overwrite = 0;
589 5 : sfinfo.rename_information.in.root_fid = 0;
590 10 : CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
591 10 : CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
592 5 : path_fname = saved_name;
593 5 : path_fname_new = saved_name_new;
594 :
595 5 : if (torture_setting_bool(torture, "samba3", false)) {
596 4 : printf("SKIP: Trying rename directory with a handle\n");
597 4 : printf("SKIP: Trying rename by path while a handle is open\n");
598 4 : printf("SKIP: Trying rename directory by path while a handle is open\n");
599 4 : goto done;
600 : }
601 :
602 1 : printf("Trying rename directory with a handle\n");
603 1 : status = create_directory_handle(cli->tree, path_dname_new, &d_fnum);
604 1 : fnum_saved = fnum;
605 1 : fnum = d_fnum;
606 1 : saved_name = fnum_fname;
607 1 : saved_name_new = fnum_fname_new;
608 1 : fnum_fname = path_dname;
609 1 : fnum_fname_new = path_dname_new;
610 1 : sfinfo.rename_information.in.new_name = path_dname+strlen(BASEDIR)+1;
611 1 : sfinfo.rename_information.in.overwrite = 0;
612 1 : sfinfo.rename_information.in.root_fid = 0;
613 2 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
614 1 : CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
615 1 : smbcli_close(cli->tree, d_fnum);
616 1 : fnum = fnum_saved;
617 1 : fnum_fname = saved_name;
618 1 : fnum_fname_new = saved_name_new;
619 :
620 1 : printf("Trying rename by path while a handle is open\n");
621 1 : fnum_saved = fnum;
622 1 : fnum = create_complex_file(cli, torture, path_fname);
623 1 : sfinfo.rename_information.in.new_name = path_fname_new+strlen(BASEDIR)+1;
624 1 : sfinfo.rename_information.in.overwrite = 0;
625 1 : sfinfo.rename_information.in.root_fid = 0;
626 2 : CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
627 2 : CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
628 : /* check that the handle returns the same name */
629 1 : check_fnum = true;
630 1 : CHECK_STR(NAME_INFO, name_info, fname.s, path_fname_new);
631 : /* rename it back on the handle */
632 1 : sfinfo.rename_information.in.new_name = path_fname+strlen(BASEDIR)+1;
633 2 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
634 1 : CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
635 1 : check_fnum = false;
636 2 : CHECK_STR(NAME_INFO, name_info, fname.s, path_fname);
637 1 : smbcli_close(cli->tree, fnum);
638 1 : fnum = fnum_saved;
639 :
640 1 : printf("Trying rename directory by path while a handle is open\n");
641 1 : status = create_directory_handle(cli->tree, path_dname, &d_fnum);
642 1 : fnum_saved = fnum;
643 1 : fnum = d_fnum;
644 1 : saved_name = path_fname;
645 1 : saved_name_new = path_fname_new;
646 1 : path_fname = path_dname;
647 1 : path_fname_new = path_dname_new;
648 1 : sfinfo.rename_information.in.new_name = path_dname_new+strlen(BASEDIR)+1;
649 1 : sfinfo.rename_information.in.overwrite = 0;
650 1 : sfinfo.rename_information.in.root_fid = 0;
651 2 : CHECK_CALL_PATH(RENAME_INFORMATION, NT_STATUS_OK);
652 2 : CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
653 1 : path_fname = saved_name;
654 1 : path_fname_new = saved_name_new;
655 1 : saved_name = fnum_fname;
656 1 : saved_name_new = fnum_fname_new;
657 1 : fnum_fname = path_dname;
658 1 : fnum_fname_new = path_dname_new;
659 : /* check that the handle returns the same name */
660 1 : check_fnum = true;
661 1 : CHECK_STR(NAME_INFO, name_info, fname.s, path_dname_new);
662 : /* rename it back on the handle */
663 1 : sfinfo.rename_information.in.new_name = path_dname+strlen(BASEDIR)+1;
664 2 : CHECK_CALL_FNUM(RENAME_INFORMATION, NT_STATUS_OK);
665 1 : CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
666 1 : fnum_fname = saved_name;
667 1 : fnum_fname_new = saved_name_new;
668 1 : saved_name = path_fname;
669 1 : saved_name_new = path_fname_new;
670 1 : path_fname = path_dname;
671 1 : path_fname_new = path_dname_new;
672 1 : check_fnum = false;
673 2 : CHECK_STR(NAME_INFO, name_info, fname.s, path_dname);
674 1 : smbcli_close(cli->tree, d_fnum);
675 1 : fnum = fnum_saved;
676 1 : path_fname = saved_name;
677 1 : path_fname_new = saved_name_new;
678 :
679 5 : done:
680 5 : smb_raw_exit(cli->session);
681 5 : smbcli_deltree(cli->tree, BASEDIR);
682 5 : return ret;
683 : }
684 :
685 : /*
686 : look for the w2k3 setpathinfo STANDARD bug
687 : */
688 5 : static bool torture_raw_sfileinfo_bug(struct torture_context *torture,
689 : struct smbcli_state *cli)
690 : {
691 5 : const char *fname = "\\bug3.txt";
692 0 : union smb_setfileinfo sfinfo;
693 0 : NTSTATUS status;
694 0 : int fnum;
695 :
696 5 : if (!torture_setting_bool(torture, "dangerous", false))
697 5 : torture_skip(torture,
698 : "torture_raw_sfileinfo_bug disabled - enable dangerous tests to use\n");
699 :
700 0 : fnum = create_complex_file(cli, torture, fname);
701 0 : smbcli_close(cli->tree, fnum);
702 :
703 0 : sfinfo.generic.level = RAW_SFILEINFO_STANDARD;
704 0 : sfinfo.generic.in.file.path = fname;
705 :
706 0 : sfinfo.standard.in.create_time = 0;
707 0 : sfinfo.standard.in.access_time = 0;
708 0 : sfinfo.standard.in.write_time = 0;
709 :
710 0 : status = smb_raw_setpathinfo(cli->tree, &sfinfo);
711 0 : printf("%s - %s\n", fname, nt_errstr(status));
712 :
713 0 : printf("now try and delete %s\n", fname);
714 :
715 0 : return true;
716 : }
717 :
718 : /**
719 : * Test both the snia cifs RAW_SFILEINFO_END_OF_FILE_INFO and the undocumented
720 : * pass-through RAW_SFILEINFO_END_OF_FILE_INFORMATION in the context of
721 : * trans2setpathinfo.
722 : */
723 : static bool
724 5 : torture_raw_sfileinfo_eof(struct torture_context *tctx,
725 : struct smbcli_state *cli1, struct smbcli_state *cli2)
726 : {
727 5 : const char *fname = BASEDIR "\\test_sfileinfo_end_of_file.dat";
728 0 : NTSTATUS status;
729 5 : bool ret = true;
730 0 : union smb_open io;
731 0 : union smb_setfileinfo sfi;
732 0 : union smb_fileinfo qfi;
733 5 : uint16_t fnum = 0;
734 :
735 5 : if (!torture_setup_dir(cli1, BASEDIR)) {
736 0 : return false;
737 : }
738 :
739 : /* cleanup */
740 5 : smbcli_unlink(cli1->tree, fname);
741 :
742 5 : io.generic.level = RAW_OPEN_NTCREATEX;
743 5 : io.ntcreatex.in.root_fid.fnum = 0;
744 5 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
745 5 : io.ntcreatex.in.alloc_size = 0;
746 5 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
747 5 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
748 5 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
749 5 : io.ntcreatex.in.create_options = 0;
750 5 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
751 5 : io.ntcreatex.in.security_flags = 0;
752 5 : io.ntcreatex.in.fname = fname;
753 5 : io.ntcreatex.in.flags = 0;
754 :
755 : /* Open the file sharing none. */
756 5 : status = smb_raw_open(cli1->tree, tctx, &io);
757 5 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
758 : done, "Status should be OK");
759 5 : fnum = io.ntcreatex.out.file.fnum;
760 :
761 : /* Try to sfileinfo to extend the file. */
762 5 : ZERO_STRUCT(sfi);
763 5 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
764 5 : sfi.generic.in.file.path = fname;
765 5 : sfi.end_of_file_info.in.size = 100;
766 5 : status = smb_raw_setpathinfo(cli2->tree, &sfi);
767 :
768 : /* There should be share mode contention in this case. */
769 5 : torture_assert_ntstatus_equal_goto(tctx, status,
770 : NT_STATUS_SHARING_VIOLATION, ret, done, "Status should be "
771 : "SHARING_VIOLATION");
772 :
773 : /* Make sure the size is still 0. */
774 5 : ZERO_STRUCT(qfi);
775 5 : qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
776 5 : qfi.generic.in.file.path = fname;
777 5 : status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
778 5 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
779 : done, "Status should be OK");
780 :
781 5 : torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 0,
782 : "alloc_size should be 0 since the setpathinfo failed.");
783 :
784 : /* Try again with the pass through instead of documented version. */
785 5 : ZERO_STRUCT(sfi);
786 5 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
787 5 : sfi.generic.in.file.path = fname;
788 5 : sfi.end_of_file_info.in.size = 100;
789 5 : status = smb_raw_setpathinfo(cli2->tree, &sfi);
790 :
791 : /*
792 : * Looks like a windows bug:
793 : * http://lists.samba.org/archive/cifs-protocol/2009-November/001130.html
794 : */
795 5 : if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
796 : /* It succeeds! This is just weird! */
797 0 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
798 : ret, done, "Status should be OK");
799 :
800 : /* Verify that the file was actually extended to 100. */
801 0 : ZERO_STRUCT(qfi);
802 0 : qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
803 0 : qfi.generic.in.file.path = fname;
804 0 : status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
805 0 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
806 : ret, done, "Status should be OK");
807 :
808 0 : torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 100,
809 : "alloc_size should be 100 since the setpathinfo "
810 : "succeeded.");
811 : } else {
812 5 : torture_assert_ntstatus_equal_goto(tctx, status,
813 : NT_STATUS_SHARING_VIOLATION, ret, done, "Status should be "
814 : "SHARING_VIOLATION");
815 : }
816 :
817 : /* close the first file. */
818 5 : smbcli_close(cli1->tree, fnum);
819 5 : fnum = 0;
820 :
821 : /* Try to sfileinfo to extend the file again (non-pass-through). */
822 5 : ZERO_STRUCT(sfi);
823 5 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
824 5 : sfi.generic.in.file.path = fname;
825 5 : sfi.end_of_file_info.in.size = 200;
826 5 : status = smb_raw_setpathinfo(cli2->tree, &sfi);
827 :
828 : /* This should cause the client to return invalid level. */
829 5 : if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
830 : /*
831 : * Windows sends back an invalid packet that smbclient sees
832 : * and returns INTERNAL_ERROR.
833 : */
834 0 : torture_assert_ntstatus_equal_goto(tctx, status,
835 : NT_STATUS_INTERNAL_ERROR, ret, done, "Status should be "
836 : "INTERNAL_ERROR");
837 : } else {
838 5 : torture_assert_ntstatus_equal_goto(tctx, status,
839 : NT_STATUS_INVALID_LEVEL, ret, done, "Status should be "
840 : "INVALID_LEVEL");
841 : }
842 :
843 : /* Try to extend the file now with the passthrough level. */
844 4 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
845 4 : status = smb_raw_setpathinfo(cli2->tree, &sfi);
846 4 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
847 : done, "Status should be OK");
848 :
849 : /* Verify that the file was actually extended to 200. */
850 4 : ZERO_STRUCT(qfi);
851 4 : qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
852 4 : qfi.generic.in.file.path = fname;
853 4 : status = smb_raw_pathinfo(cli2->tree, tctx, &qfi);
854 :
855 4 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
856 : done, "Status should be OK");
857 4 : torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 200,
858 : "alloc_size should be 200 since the setpathinfo succeeded.");
859 :
860 : /* Open the file so end of file can be set by handle. */
861 4 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_WRITE;
862 4 : status = smb_raw_open(cli1->tree, tctx, &io);
863 4 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
864 : done, "Status should be OK");
865 4 : fnum = io.ntcreatex.out.file.fnum;
866 :
867 : /* Try sfileinfo to extend the file by handle (non-pass-through). */
868 4 : ZERO_STRUCT(sfi);
869 4 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
870 4 : sfi.generic.in.file.fnum = fnum;
871 4 : sfi.end_of_file_info.in.size = 300;
872 4 : status = smb_raw_setfileinfo(cli1->tree, &sfi);
873 4 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
874 : done, "Status should be OK");
875 :
876 : /* Verify that the file was actually extended to 300. */
877 4 : ZERO_STRUCT(qfi);
878 4 : qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
879 4 : qfi.generic.in.file.path = fname;
880 4 : status = smb_raw_pathinfo(cli1->tree, tctx, &qfi);
881 4 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
882 : done, "Status should be OK");
883 4 : torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 300,
884 : "alloc_size should be 300 since the setpathinfo succeeded.");
885 :
886 : /* Try sfileinfo to extend the file by handle (pass-through). */
887 4 : ZERO_STRUCT(sfi);
888 4 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
889 4 : sfi.generic.in.file.fnum = fnum;
890 4 : sfi.end_of_file_info.in.size = 400;
891 4 : status = smb_raw_setfileinfo(cli1->tree, &sfi);
892 4 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
893 : done, "Status should be OK");
894 :
895 : /* Verify that the file was actually extended to 300. */
896 4 : ZERO_STRUCT(qfi);
897 4 : qfi.generic.level = RAW_FILEINFO_STANDARD_INFO;
898 4 : qfi.generic.in.file.path = fname;
899 4 : status = smb_raw_pathinfo(cli1->tree, tctx, &qfi);
900 4 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK, ret,
901 : done, "Status should be OK");
902 4 : torture_assert_u64_equal(tctx, qfi.standard_info.out.size, 400,
903 : "alloc_size should be 400 since the setpathinfo succeeded.");
904 4 : done:
905 5 : if (fnum > 0) {
906 4 : smbcli_close(cli1->tree, fnum);
907 4 : fnum = 0;
908 : }
909 :
910 5 : smb_raw_exit(cli1->session);
911 5 : smb_raw_exit(cli2->session);
912 5 : smbcli_deltree(cli1->tree, BASEDIR);
913 5 : return ret;
914 : }
915 :
916 : static bool
917 1 : torture_raw_sfileinfo_eof_access(struct torture_context *tctx,
918 : struct smbcli_state *cli1, struct smbcli_state *cli2)
919 : {
920 1 : const char *fname = BASEDIR "\\test_exclusive3.dat";
921 0 : NTSTATUS status, expected_status;
922 1 : bool ret = true;
923 0 : union smb_open io;
924 0 : union smb_setfileinfo sfi;
925 1 : uint16_t fnum=0;
926 1 : uint32_t access_mask = 0;
927 :
928 1 : if (!torture_setup_dir(cli1, BASEDIR)) {
929 0 : return false;
930 : }
931 :
932 : /* cleanup */
933 1 : smbcli_unlink(cli1->tree, fname);
934 :
935 : /*
936 : * base ntcreatex parms
937 : */
938 1 : io.generic.level = RAW_OPEN_NTCREATEX;
939 1 : io.ntcreatex.in.root_fid.fnum = 0;
940 1 : io.ntcreatex.in.alloc_size = 0;
941 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
942 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
943 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
944 1 : io.ntcreatex.in.create_options = 0;
945 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
946 1 : io.ntcreatex.in.security_flags = 0;
947 1 : io.ntcreatex.in.fname = fname;
948 1 : io.ntcreatex.in.flags = 0;
949 :
950 :
951 512 : for (access_mask = 1; access_mask <= 0x00001FF; access_mask++) {
952 511 : io.ntcreatex.in.access_mask = access_mask;
953 :
954 511 : status = smb_raw_open(cli1->tree, tctx, &io);
955 511 : if (!NT_STATUS_IS_OK(status)) {
956 0 : continue;
957 : }
958 :
959 511 : fnum = io.ntcreatex.out.file.fnum;
960 :
961 511 : ZERO_STRUCT(sfi);
962 511 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
963 511 : sfi.generic.in.file.fnum = fnum;
964 511 : sfi.end_of_file_info.in.size = 100;
965 :
966 511 : status = smb_raw_setfileinfo(cli1->tree, &sfi);
967 :
968 511 : expected_status = (access_mask & SEC_FILE_WRITE_DATA) ?
969 0 : NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
970 :
971 511 : if (!NT_STATUS_EQUAL(expected_status, status)) {
972 0 : torture_comment(tctx, "0x%x wrong\n", access_mask);
973 : }
974 :
975 511 : torture_assert_ntstatus_equal_goto(tctx, status,
976 : expected_status, ret, done, "Status Wrong");
977 :
978 511 : smbcli_close(cli1->tree, fnum);
979 : }
980 :
981 1 : done:
982 1 : smb_raw_exit(cli1->session);
983 1 : smb_raw_exit(cli2->session);
984 1 : smbcli_deltree(cli1->tree, BASEDIR);
985 1 : return ret;
986 : }
987 :
988 : static bool
989 1 : torture_raw_sfileinfo_archive(struct torture_context *tctx,
990 : struct smbcli_state *cli)
991 : {
992 1 : const char *fname = BASEDIR "\\test_archive.dat";
993 0 : NTSTATUS status;
994 1 : bool ret = true;
995 0 : union smb_open io;
996 0 : union smb_setfileinfo sfinfo;
997 0 : union smb_fileinfo finfo;
998 1 : uint16_t fnum=0;
999 :
1000 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1001 :
1002 : /* cleanup */
1003 1 : smbcli_unlink(cli->tree, fname);
1004 :
1005 : /*
1006 : * create a normal file, verify archive bit
1007 : */
1008 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1009 1 : io.ntcreatex.in.root_fid.fnum = 0;
1010 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1011 1 : io.ntcreatex.in.alloc_size = 0;
1012 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1013 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1014 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1015 1 : io.ntcreatex.in.create_options = 0;
1016 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1017 1 : io.ntcreatex.in.security_flags = 0;
1018 1 : io.ntcreatex.in.fname = fname;
1019 1 : io.ntcreatex.in.flags = 0;
1020 1 : status = smb_raw_open(cli->tree, tctx, &io);
1021 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1022 : ret, done, "open failed");
1023 1 : fnum = io.ntcreatex.out.file.fnum;
1024 :
1025 1 : torture_assert_int_equal(tctx,
1026 : io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1027 : FILE_ATTRIBUTE_ARCHIVE,
1028 : "archive bit not set");
1029 :
1030 : /*
1031 : * try to turn off archive bit
1032 : */
1033 1 : ZERO_STRUCT(sfinfo);
1034 1 : sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1035 1 : sfinfo.generic.in.file.fnum = fnum;
1036 1 : sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
1037 1 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1038 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1039 : ret, done, "setfileinfo failed");
1040 :
1041 1 : finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1042 1 : finfo.generic.in.file.fnum = fnum;
1043 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1044 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1045 : ret, done, "fileinfo failed");
1046 :
1047 1 : torture_assert_int_equal(tctx,
1048 : finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1049 : FILE_ATTRIBUTE_NORMAL,
1050 : "archive bit set");
1051 :
1052 1 : status = smbcli_close(cli->tree, fnum);
1053 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1054 : ret, done, "close failed");
1055 :
1056 1 : status = smbcli_unlink(cli->tree, fname);
1057 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1058 : ret, done, "unlink failed");
1059 :
1060 : /*
1061 : * create a directory, verify no archive bit
1062 : */
1063 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1064 1 : io.ntcreatex.in.root_fid.fnum = 0;
1065 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_DIR_ALL;
1066 1 : io.ntcreatex.in.alloc_size = 0;
1067 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1068 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1069 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1070 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1071 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1072 1 : io.ntcreatex.in.security_flags = 0;
1073 1 : io.ntcreatex.in.fname = fname;
1074 1 : io.ntcreatex.in.flags = 0;
1075 1 : status = smb_raw_open(cli->tree, tctx, &io);
1076 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1077 : ret, done, "directory open failed");
1078 1 : fnum = io.ntcreatex.out.file.fnum;
1079 :
1080 1 : torture_assert_int_equal(tctx,
1081 : io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1082 : FILE_ATTRIBUTE_DIRECTORY,
1083 : "archive bit set");
1084 :
1085 : /*
1086 : * verify you can turn on archive bit
1087 : */
1088 1 : sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1089 1 : sfinfo.generic.in.file.fnum = fnum;
1090 1 : sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE;
1091 1 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1092 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1093 : ret, done, "setfileinfo failed");
1094 :
1095 1 : finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1096 1 : finfo.generic.in.file.fnum = fnum;
1097 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1098 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1099 : ret, done, "fileinfo failed");
1100 :
1101 1 : torture_assert_int_equal(tctx,
1102 : finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1103 : FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE,
1104 : "archive bit not set");
1105 :
1106 : /*
1107 : * and try to turn it back off
1108 : */
1109 1 : sfinfo.generic.level = RAW_SFILEINFO_BASIC_INFO;
1110 1 : sfinfo.generic.in.file.fnum = fnum;
1111 1 : sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
1112 1 : status = smb_raw_setfileinfo(cli->tree, &sfinfo);
1113 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1114 : ret, done, "setfileinfo failed");
1115 :
1116 1 : finfo.generic.level = RAW_FILEINFO_ALL_INFO;
1117 1 : finfo.generic.in.file.fnum = fnum;
1118 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1119 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1120 : ret, done, "fileinfo failed");
1121 :
1122 1 : torture_assert_int_equal(tctx,
1123 : finfo.all_info.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1124 : FILE_ATTRIBUTE_DIRECTORY,
1125 : "archive bit set");
1126 :
1127 1 : status = smbcli_close(cli->tree, fnum);
1128 1 : torture_assert_ntstatus_equal_goto(tctx, status, NT_STATUS_OK,
1129 : ret, done, "close failed");
1130 :
1131 1 : done:
1132 1 : smbcli_close(cli->tree, fnum);
1133 1 : smbcli_deltree(cli->tree, BASEDIR);
1134 1 : return ret;
1135 : }
1136 :
1137 2354 : struct torture_suite *torture_raw_sfileinfo(TALLOC_CTX *mem_ctx)
1138 : {
1139 2354 : struct torture_suite *suite = torture_suite_create(mem_ctx, "sfileinfo");
1140 :
1141 2354 : torture_suite_add_1smb_test(suite, "base", torture_raw_sfileinfo_base);
1142 2354 : torture_suite_add_1smb_test(suite, "rename", torture_raw_sfileinfo_rename);
1143 2354 : torture_suite_add_1smb_test(suite, "bug", torture_raw_sfileinfo_bug);
1144 2354 : torture_suite_add_2smb_test(suite, "end-of-file",
1145 : torture_raw_sfileinfo_eof);
1146 2354 : torture_suite_add_2smb_test(suite, "end-of-file-access",
1147 : torture_raw_sfileinfo_eof_access);
1148 2354 : torture_suite_add_1smb_test(suite, "archive",
1149 : torture_raw_sfileinfo_archive);
1150 :
1151 2354 : return suite;
1152 : }
|