Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : RAW_OPEN_* 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 "libcli/raw/libcliraw.h"
22 : #include "system/time.h"
23 : #include "system/filesys.h"
24 : #include "lib/events/events.h"
25 : #include "libcli/libcli.h"
26 : #include "torture/util.h"
27 : #include "torture/raw/proto.h"
28 :
29 : /* enum for whether reads/writes are possible on a file */
30 : enum rdwr_mode {RDWR_NONE, RDWR_RDONLY, RDWR_WRONLY, RDWR_RDWR};
31 :
32 : #define BASEDIR "\\rawopen"
33 :
34 : /*
35 : check if a open file can be read/written
36 : */
37 8 : static enum rdwr_mode check_rdwr(struct smbcli_tree *tree, int fnum)
38 : {
39 8 : uint8_t c = 1;
40 8 : bool can_read = (smbcli_read(tree, fnum, &c, 0, 1) == 1);
41 8 : bool can_write = (smbcli_write(tree, fnum, 0, &c, 0, 1) == 1);
42 8 : if ( can_read && can_write) return RDWR_RDWR;
43 4 : if ( can_read && !can_write) return RDWR_RDONLY;
44 1 : if (!can_read && can_write) return RDWR_WRONLY;
45 0 : return RDWR_NONE;
46 : }
47 :
48 : /*
49 : describe a RDWR mode as a string
50 : */
51 0 : static const char *rdwr_string(enum rdwr_mode m)
52 : {
53 0 : switch (m) {
54 0 : case RDWR_NONE: return "NONE";
55 0 : case RDWR_RDONLY: return "RDONLY";
56 0 : case RDWR_WRONLY: return "WRONLY";
57 0 : case RDWR_RDWR: return "RDWR";
58 : }
59 0 : return "-";
60 : }
61 :
62 : #define CHECK_STATUS(status, correct) do { \
63 : if (!NT_STATUS_EQUAL(status, correct)) { \
64 : torture_result(tctx, TORTURE_FAIL, \
65 : "(%s) Incorrect status %s - should be %s\n", \
66 : __location__, nt_errstr(status), nt_errstr(correct)); \
67 : ret = false; \
68 : goto done; \
69 : }} while (0)
70 :
71 : #define CREATE_FILE do { \
72 : fnum = create_complex_file(cli, tctx, fname); \
73 : if (fnum == -1) { \
74 : torture_result(tctx, TORTURE_FAIL, \
75 : "(%s) Failed to create %s - %s\n", \
76 : __location__, fname, smbcli_errstr(cli->tree)); \
77 : ret = false; \
78 : goto done; \
79 : }} while (0)
80 :
81 : #define CHECK_RDWR(fnum, correct) do { \
82 : enum rdwr_mode m = check_rdwr(cli->tree, fnum); \
83 : if (m != correct) { \
84 : torture_result(tctx, TORTURE_FAIL, \
85 : "(%s) Incorrect readwrite mode %s - expected %s\n", \
86 : __location__, rdwr_string(m), rdwr_string(correct)); \
87 : ret = false; \
88 : }} while (0)
89 :
90 : #define CHECK_TIME(t, field) do { \
91 : time_t t1, t2; \
92 : finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
93 : finfo.all_info.in.file.path = fname; \
94 : status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
95 : CHECK_STATUS(status, NT_STATUS_OK); \
96 : t1 = t & ~1; \
97 : t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
98 : if (labs(t1-t2) > 2) { \
99 : torture_result(tctx, TORTURE_FAIL, \
100 : "(%s) wrong time for field %s %s - %s\n", \
101 : __location__, #field, \
102 : timestring(tctx, t1), \
103 : timestring(tctx, t2)); \
104 : dump_all_info(tctx, &finfo); \
105 : ret = false; \
106 : }} while (0)
107 :
108 : #define CHECK_NTTIME(t, field) do { \
109 : NTTIME t2; \
110 : finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
111 : finfo.all_info.in.file.path = fname; \
112 : status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
113 : CHECK_STATUS(status, NT_STATUS_OK); \
114 : t2 = finfo.all_info.out.field; \
115 : if (llabs((int64_t)(t-t2)) > 20000) { \
116 : torture_result(tctx, TORTURE_FAIL, \
117 : "(%s) wrong time for field %s %s - %s\n", \
118 : __location__, #field, \
119 : nt_time_string(tctx, t), \
120 : nt_time_string(tctx, t2)); \
121 : dump_all_info(tctx, &finfo); \
122 : ret = false; \
123 : }} while (0)
124 :
125 : #define CHECK_ALL_INFO(v, field) do { \
126 : finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
127 : finfo.all_info.in.file.path = fname; \
128 : status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
129 : CHECK_STATUS(status, NT_STATUS_OK); \
130 : if ((v) != (finfo.all_info.out.field)) { \
131 : torture_result(tctx, TORTURE_FAIL, \
132 : "(%s) wrong value for field %s 0x%x - 0x%x\n", \
133 : __location__, #field, (unsigned int)(v), (unsigned int)(finfo.all_info.out.field)); \
134 : dump_all_info(tctx, &finfo); \
135 : ret = false; \
136 : }} while (0)
137 :
138 : #define CHECK_VAL(v, correct) do { \
139 : if ((v) != (correct)) { \
140 : torture_result(tctx, TORTURE_FAIL, \
141 : "(%s) wrong value for %s 0x%x - should be 0x%x\n", \
142 : __location__, #v, (unsigned int)(v), (unsigned int)(correct)); \
143 : ret = false; \
144 : }} while (0)
145 :
146 : #define SET_ATTRIB(sattrib) do { \
147 : union smb_setfileinfo sfinfo; \
148 : ZERO_STRUCT(sfinfo.basic_info.in); \
149 : sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
150 : sfinfo.basic_info.in.file.path = fname; \
151 : sfinfo.basic_info.in.attrib = sattrib; \
152 : status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
153 : if (!NT_STATUS_IS_OK(status)) { \
154 : torture_warning(tctx, "(%s) Failed to set attrib 0x%x on %s\n", \
155 : __location__, (unsigned int)(sattrib), fname); \
156 : }} while (0)
157 :
158 : /*
159 : test RAW_OPEN_OPEN
160 : */
161 1 : static bool test_open(struct torture_context *tctx, struct smbcli_state *cli)
162 : {
163 : union smb_open io;
164 : union smb_fileinfo finfo;
165 1 : const char *fname = BASEDIR "\\torture_open.txt";
166 : NTSTATUS status;
167 1 : int fnum = -1, fnum2;
168 1 : bool ret = true;
169 :
170 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
171 :
172 1 : io.openold.level = RAW_OPEN_OPEN;
173 1 : io.openold.in.fname = fname;
174 1 : io.openold.in.open_mode = OPEN_FLAGS_FCB;
175 1 : io.openold.in.search_attrs = 0;
176 1 : status = smb_raw_open(cli->tree, tctx, &io);
177 1 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
178 1 : fnum = io.openold.out.file.fnum;
179 :
180 1 : smbcli_unlink(cli->tree, fname);
181 1 : CREATE_FILE;
182 1 : smbcli_close(cli->tree, fnum);
183 :
184 1 : status = smb_raw_open(cli->tree, tctx, &io);
185 1 : CHECK_STATUS(status, NT_STATUS_OK);
186 1 : fnum = io.openold.out.file.fnum;
187 1 : CHECK_RDWR(fnum, RDWR_RDWR);
188 :
189 1 : status = smb_raw_open(cli->tree, tctx, &io);
190 1 : CHECK_STATUS(status, NT_STATUS_OK);
191 1 : fnum2 = io.openold.out.file.fnum;
192 1 : CHECK_RDWR(fnum2, RDWR_RDWR);
193 1 : smbcli_close(cli->tree, fnum2);
194 1 : smbcli_close(cli->tree, fnum);
195 :
196 : /* check the read/write modes */
197 1 : io.openold.level = RAW_OPEN_OPEN;
198 1 : io.openold.in.fname = fname;
199 1 : io.openold.in.search_attrs = 0;
200 :
201 1 : io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
202 1 : status = smb_raw_open(cli->tree, tctx, &io);
203 1 : CHECK_STATUS(status, NT_STATUS_OK);
204 1 : fnum = io.openold.out.file.fnum;
205 1 : CHECK_RDWR(fnum, RDWR_RDONLY);
206 1 : smbcli_close(cli->tree, fnum);
207 :
208 1 : io.openold.in.open_mode = OPEN_FLAGS_OPEN_WRITE;
209 1 : status = smb_raw_open(cli->tree, tctx, &io);
210 1 : CHECK_STATUS(status, NT_STATUS_OK);
211 1 : fnum = io.openold.out.file.fnum;
212 1 : CHECK_RDWR(fnum, RDWR_WRONLY);
213 1 : smbcli_close(cli->tree, fnum);
214 :
215 1 : io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR;
216 1 : status = smb_raw_open(cli->tree, tctx, &io);
217 1 : CHECK_STATUS(status, NT_STATUS_OK);
218 1 : fnum = io.openold.out.file.fnum;
219 1 : CHECK_RDWR(fnum, RDWR_RDWR);
220 1 : smbcli_close(cli->tree, fnum);
221 :
222 : /* check the share modes roughly - not a complete matrix */
223 1 : io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE;
224 1 : status = smb_raw_open(cli->tree, tctx, &io);
225 1 : CHECK_STATUS(status, NT_STATUS_OK);
226 1 : fnum = io.openold.out.file.fnum;
227 1 : CHECK_RDWR(fnum, RDWR_RDWR);
228 :
229 1 : if (io.openold.in.open_mode != io.openold.out.rmode) {
230 0 : torture_warning(tctx, "(%s) rmode should equal open_mode - 0x%x 0x%x\n",
231 0 : __location__, io.openold.out.rmode, io.openold.in.open_mode);
232 : }
233 :
234 1 : io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE;
235 1 : status = smb_raw_open(cli->tree, tctx, &io);
236 1 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
237 :
238 1 : io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE;
239 1 : status = smb_raw_open(cli->tree, tctx, &io);
240 1 : CHECK_STATUS(status, NT_STATUS_OK);
241 1 : fnum2 = io.openold.out.file.fnum;
242 1 : CHECK_RDWR(fnum2, RDWR_RDONLY);
243 1 : smbcli_close(cli->tree, fnum);
244 1 : smbcli_close(cli->tree, fnum2);
245 :
246 :
247 : /* check the returned write time */
248 1 : io.openold.level = RAW_OPEN_OPEN;
249 1 : io.openold.in.fname = fname;
250 1 : io.openold.in.search_attrs = 0;
251 1 : io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
252 1 : status = smb_raw_open(cli->tree, tctx, &io);
253 1 : CHECK_STATUS(status, NT_STATUS_OK);
254 1 : fnum = io.openold.out.file.fnum;
255 :
256 : /* check other reply fields */
257 1 : CHECK_TIME(io.openold.out.write_time, write_time);
258 1 : CHECK_ALL_INFO(io.openold.out.size, size);
259 1 : CHECK_ALL_INFO(io.openold.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
260 :
261 2 : done:
262 1 : smbcli_close(cli->tree, fnum);
263 1 : smbcli_deltree(cli->tree, BASEDIR);
264 :
265 1 : return ret;
266 : }
267 :
268 :
269 : /*
270 : test RAW_OPEN_OPENX
271 : */
272 1 : static bool test_openx(struct torture_context *tctx, struct smbcli_state *cli)
273 : {
274 : union smb_open io;
275 : union smb_fileinfo finfo;
276 1 : const char *fname = BASEDIR "\\torture_openx.txt";
277 1 : const char *fname_exe = BASEDIR "\\torture_openx.exe";
278 : NTSTATUS status;
279 1 : int fnum = -1, fnum2;
280 1 : bool ret = true;
281 : int i;
282 : struct timeval tv;
283 : struct {
284 : uint16_t open_func;
285 : bool with_file;
286 : NTSTATUS correct_status;
287 1 : } open_funcs[] = {
288 : { OPENX_OPEN_FUNC_OPEN, true, NT_STATUS_OK },
289 : { OPENX_OPEN_FUNC_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
290 : { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OK },
291 : { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
292 : { OPENX_OPEN_FUNC_FAIL, true, NT_STATUS_DOS(ERRDOS, ERRbadaccess) },
293 : { OPENX_OPEN_FUNC_FAIL, false, NT_STATUS_DOS(ERRDOS, ERRbadaccess) },
294 : { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
295 : { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
296 : { OPENX_OPEN_FUNC_TRUNC, true, NT_STATUS_OK },
297 : { OPENX_OPEN_FUNC_TRUNC, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
298 : { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OK },
299 : { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
300 : };
301 :
302 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
303 :
304 1 : io.openx.level = RAW_OPEN_OPENX;
305 1 : io.openx.in.fname = fname;
306 1 : io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
307 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
308 1 : io.openx.in.search_attrs = 0;
309 1 : io.openx.in.file_attrs = 0;
310 1 : io.openx.in.write_time = 0;
311 1 : io.openx.in.size = 1024*1024;
312 1 : io.openx.in.timeout = 0;
313 :
314 : /* check all combinations of open_func */
315 13 : for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
316 12 : if (open_funcs[i].with_file) {
317 6 : fnum = create_complex_file(cli, tctx, fname);
318 6 : if (fnum == -1) {
319 0 : torture_result(tctx, TORTURE_FAIL,
320 : "Failed to create file %s - %s\n",
321 : fname, smbcli_errstr(cli->tree));
322 0 : ret = false;
323 0 : goto done;
324 : }
325 6 : smbcli_close(cli->tree, fnum);
326 : }
327 12 : io.openx.in.open_func = open_funcs[i].open_func;
328 12 : status = smb_raw_open(cli->tree, tctx, &io);
329 12 : if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
330 0 : torture_result(tctx, TORTURE_FAIL,
331 : "(%s) incorrect status %s should be %s "
332 : "(i=%d with_file=%d open_func=0x%x)\n",
333 : __location__, nt_errstr(status),
334 : nt_errstr(open_funcs[i].correct_status),
335 0 : i, (int)open_funcs[i].with_file,
336 0 : open_funcs[i].open_func);
337 0 : ret = false;
338 : }
339 12 : if (NT_STATUS_IS_OK(status)) {
340 7 : smbcli_close(cli->tree, io.openx.out.file.fnum);
341 : }
342 12 : if (open_funcs[i].with_file) {
343 6 : smbcli_unlink(cli->tree, fname);
344 : }
345 : }
346 :
347 1 : smbcli_unlink(cli->tree, fname);
348 :
349 : /* check the basic return fields */
350 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
351 1 : status = smb_raw_open(cli->tree, tctx, &io);
352 1 : CHECK_STATUS(status, NT_STATUS_OK);
353 1 : fnum = io.openx.out.file.fnum;
354 :
355 1 : CHECK_ALL_INFO(io.openx.out.size, size);
356 1 : CHECK_TIME(io.openx.out.write_time, write_time);
357 1 : CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
358 1 : CHECK_VAL(io.openx.out.access, OPENX_MODE_ACCESS_RDWR);
359 1 : CHECK_VAL(io.openx.out.ftype, 0);
360 1 : CHECK_VAL(io.openx.out.devstate, 0);
361 1 : CHECK_VAL(io.openx.out.action, OPENX_ACTION_CREATED);
362 1 : CHECK_VAL(io.openx.out.size, 1024*1024);
363 1 : CHECK_ALL_INFO(io.openx.in.size, size);
364 1 : smbcli_close(cli->tree, fnum);
365 1 : smbcli_unlink(cli->tree, fname);
366 :
367 : /* check the fields when the file already existed */
368 1 : fnum2 = create_complex_file(cli, tctx, fname);
369 1 : if (fnum2 == -1) {
370 0 : ret = false;
371 0 : goto done;
372 : }
373 1 : smbcli_close(cli->tree, fnum2);
374 :
375 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
376 1 : status = smb_raw_open(cli->tree, tctx, &io);
377 1 : CHECK_STATUS(status, NT_STATUS_OK);
378 1 : fnum = io.openx.out.file.fnum;
379 :
380 1 : CHECK_ALL_INFO(io.openx.out.size, size);
381 1 : CHECK_TIME(io.openx.out.write_time, write_time);
382 1 : CHECK_VAL(io.openx.out.action, OPENX_ACTION_EXISTED);
383 1 : CHECK_VAL(io.openx.out.unknown, 0);
384 1 : CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
385 1 : smbcli_close(cli->tree, fnum);
386 :
387 : /* now check the search attrib for hidden files - win2003 ignores this? */
388 1 : SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
389 1 : CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
390 :
391 1 : io.openx.in.search_attrs = FILE_ATTRIBUTE_HIDDEN;
392 1 : status = smb_raw_open(cli->tree, tctx, &io);
393 1 : CHECK_STATUS(status, NT_STATUS_OK);
394 1 : smbcli_close(cli->tree, io.openx.out.file.fnum);
395 :
396 1 : io.openx.in.search_attrs = 0;
397 1 : status = smb_raw_open(cli->tree, tctx, &io);
398 1 : CHECK_STATUS(status, NT_STATUS_OK);
399 1 : smbcli_close(cli->tree, io.openx.out.file.fnum);
400 :
401 1 : SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
402 1 : smbcli_unlink(cli->tree, fname);
403 :
404 : /* and check attrib on create */
405 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
406 1 : io.openx.in.search_attrs = 0;
407 1 : io.openx.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
408 1 : status = smb_raw_open(cli->tree, tctx, &io);
409 1 : CHECK_STATUS(status, NT_STATUS_OK);
410 1 : if (torture_setting_bool(tctx, "samba3", false)) {
411 0 : CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE,
412 : attrib & ~(FILE_ATTRIBUTE_NONINDEXED|
413 : FILE_ATTRIBUTE_SPARSE));
414 : }
415 : else {
416 1 : CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE,
417 : attrib & ~(FILE_ATTRIBUTE_NONINDEXED));
418 : }
419 1 : smbcli_close(cli->tree, io.openx.out.file.fnum);
420 1 : smbcli_unlink(cli->tree, fname);
421 :
422 : /* check timeout on create - win2003 ignores the timeout! */
423 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
424 1 : io.openx.in.file_attrs = 0;
425 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
426 1 : status = smb_raw_open(cli->tree, tctx, &io);
427 1 : CHECK_STATUS(status, NT_STATUS_OK);
428 1 : fnum = io.openx.out.file.fnum;
429 :
430 1 : io.openx.in.timeout = 20000;
431 1 : tv = timeval_current();
432 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_NONE;
433 1 : status = smb_raw_open(cli->tree, tctx, &io);
434 1 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
435 1 : if (timeval_elapsed(&tv) > 3.0) {
436 0 : torture_result(tctx, TORTURE_FAIL,
437 : "(%s) Incorrect timing in openx with timeout "
438 : "- waited %.2f seconds\n",
439 : __location__, timeval_elapsed(&tv));
440 0 : ret = false;
441 : }
442 1 : smbcli_close(cli->tree, fnum);
443 1 : smbcli_unlink(cli->tree, fname);
444 :
445 : /* now this is a really weird one - open for execute implies create?! */
446 1 : io.openx.in.fname = fname;
447 1 : io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
448 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
449 1 : io.openx.in.search_attrs = 0;
450 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL;
451 1 : io.openx.in.file_attrs = 0;
452 1 : io.openx.in.write_time = 0;
453 1 : io.openx.in.size = 0;
454 1 : io.openx.in.timeout = 0;
455 1 : status = smb_raw_open(cli->tree, tctx, &io);
456 1 : CHECK_STATUS(status, NT_STATUS_OK);
457 1 : smbcli_close(cli->tree, io.openx.out.file.fnum);
458 :
459 : /* check the extended return flag */
460 1 : io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO | OPENX_FLAGS_EXTENDED_RETURN;
461 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
462 1 : status = smb_raw_open(cli->tree, tctx, &io);
463 1 : CHECK_STATUS(status, NT_STATUS_OK);
464 1 : CHECK_VAL(io.openx.out.access_mask, SEC_STD_ALL);
465 1 : smbcli_close(cli->tree, io.openx.out.file.fnum);
466 :
467 1 : io.openx.in.fname = "\\A.+,;=[].B";
468 1 : status = smb_raw_open(cli->tree, tctx, &io);
469 1 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
470 :
471 : /* Check the mapping for open exec. */
472 :
473 : /* First create an .exe file. */
474 1 : smbcli_unlink(cli->tree, fname_exe);
475 1 : fnum = create_complex_file(cli, tctx, fname_exe);
476 1 : smbcli_close(cli->tree, fnum);
477 :
478 1 : io.openx.level = RAW_OPEN_OPENX;
479 1 : io.openx.in.fname = fname_exe;
480 1 : io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
481 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
482 1 : io.openx.in.search_attrs = 0;
483 1 : io.openx.in.file_attrs = 0;
484 1 : io.openx.in.write_time = 0;
485 1 : io.openx.in.size = 0;
486 1 : io.openx.in.timeout = 0;
487 1 : status = smb_raw_open(cli->tree, tctx, &io);
488 1 : CHECK_STATUS(status, NT_STATUS_OK);
489 :
490 : /* Can we read and write ? */
491 1 : CHECK_RDWR(io.openx.out.file.fnum, RDWR_RDONLY);
492 1 : smbcli_close(cli->tree, io.openx.out.file.fnum);
493 1 : smbcli_unlink(cli->tree, fname);
494 :
495 1 : done:
496 1 : smbcli_close(cli->tree, fnum);
497 1 : smbcli_deltree(cli->tree, BASEDIR);
498 :
499 1 : return ret;
500 : }
501 :
502 :
503 : /*
504 : test RAW_OPEN_T2OPEN
505 :
506 : many thanks to kukks for a sniff showing how this works with os2->w2k
507 : */
508 1 : static bool test_t2open(struct torture_context *tctx, struct smbcli_state *cli)
509 : {
510 : union smb_open io;
511 : union smb_fileinfo finfo;
512 1 : const char *fname1 = BASEDIR "\\torture_t2open_yes.txt";
513 1 : const char *fname2 = BASEDIR "\\torture_t2open_no.txt";
514 1 : const char *fname = BASEDIR "\\torture_t2open_3.txt";
515 : NTSTATUS status;
516 : int fnum;
517 1 : bool ret = true;
518 : int i;
519 : struct {
520 : uint16_t open_func;
521 : bool with_file;
522 : NTSTATUS correct_status;
523 1 : } open_funcs[] = {
524 : { OPENX_OPEN_FUNC_OPEN, true, NT_STATUS_OK },
525 : { OPENX_OPEN_FUNC_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
526 : { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OK },
527 : { OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
528 : { OPENX_OPEN_FUNC_FAIL, true, NT_STATUS_OBJECT_NAME_COLLISION },
529 : { OPENX_OPEN_FUNC_FAIL, false, NT_STATUS_OBJECT_NAME_COLLISION },
530 : { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
531 : { OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OBJECT_NAME_COLLISION },
532 : { OPENX_OPEN_FUNC_TRUNC, true, NT_STATUS_OK },
533 : { OPENX_OPEN_FUNC_TRUNC, false, NT_STATUS_OK },
534 : { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, true, NT_STATUS_OK },
535 : { OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, false, NT_STATUS_OK },
536 : };
537 :
538 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
539 :
540 1 : fnum = create_complex_file(cli, tctx, fname1);
541 1 : if (fnum == -1) {
542 0 : torture_result(tctx, TORTURE_FAIL,
543 : "(%s): Failed to create file %s - %s\n",
544 : __location__, fname1, smbcli_errstr(cli->tree));
545 0 : ret = false;
546 0 : goto done;
547 : }
548 1 : smbcli_close(cli->tree, fnum);
549 :
550 1 : io.t2open.level = RAW_OPEN_T2OPEN;
551 1 : io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
552 1 : io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR;
553 1 : io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
554 1 : io.t2open.in.search_attrs = 0;
555 1 : io.t2open.in.file_attrs = 0;
556 1 : io.t2open.in.write_time = 0;
557 1 : io.t2open.in.size = 0;
558 1 : io.t2open.in.timeout = 0;
559 :
560 1 : io.t2open.in.num_eas = 3;
561 1 : io.t2open.in.eas = talloc_array(tctx, struct ea_struct, io.t2open.in.num_eas);
562 1 : io.t2open.in.eas[0].flags = 0;
563 1 : io.t2open.in.eas[0].name.s = ".CLASSINFO";
564 1 : io.t2open.in.eas[0].value = data_blob_talloc(tctx, "first value", 11);
565 1 : io.t2open.in.eas[1].flags = 0;
566 1 : io.t2open.in.eas[1].name.s = "EA TWO";
567 1 : io.t2open.in.eas[1].value = data_blob_talloc(tctx, "foo", 3);
568 1 : io.t2open.in.eas[2].flags = 0;
569 1 : io.t2open.in.eas[2].name.s = "X THIRD";
570 1 : io.t2open.in.eas[2].value = data_blob_talloc(tctx, "xy", 2);
571 :
572 : /* check all combinations of open_func */
573 13 : for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
574 12 : again:
575 12 : if (open_funcs[i].with_file) {
576 6 : io.t2open.in.fname = fname1;
577 : } else {
578 6 : io.t2open.in.fname = fname2;
579 : }
580 12 : io.t2open.in.open_func = open_funcs[i].open_func;
581 12 : status = smb_raw_open(cli->tree, tctx, &io);
582 12 : if ((io.t2open.in.num_eas != 0)
583 12 : && NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
584 0 : && torture_setting_bool(tctx, "samba3", false)) {
585 0 : torture_warning(tctx, "(%s) EAs not supported, not "
586 : "treating as fatal in Samba3 test\n",
587 : __location__);
588 0 : io.t2open.in.num_eas = 0;
589 0 : goto again;
590 : }
591 :
592 12 : if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
593 0 : torture_result(tctx, TORTURE_FAIL,
594 : "(%s) incorrect status %s should be %s "
595 : "(i=%d with_file=%d open_func=0x%x)\n",
596 : __location__, nt_errstr(status),
597 : nt_errstr(open_funcs[i].correct_status),
598 0 : i, (int)open_funcs[i].with_file,
599 0 : open_funcs[i].open_func);
600 0 : ret = false;
601 : }
602 12 : if (NT_STATUS_IS_OK(status)) {
603 7 : smbcli_close(cli->tree, io.t2open.out.file.fnum);
604 : }
605 : }
606 :
607 1 : smbcli_unlink(cli->tree, fname1);
608 1 : smbcli_unlink(cli->tree, fname2);
609 :
610 : /* check the basic return fields */
611 1 : io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
612 1 : io.t2open.in.write_time = 0;
613 1 : io.t2open.in.fname = fname;
614 1 : status = smb_raw_open(cli->tree, tctx, &io);
615 1 : CHECK_STATUS(status, NT_STATUS_OK);
616 1 : fnum = io.t2open.out.file.fnum;
617 :
618 1 : CHECK_ALL_INFO(io.t2open.out.size, size);
619 : #if 0
620 : /* windows appears to leak uninitialised memory here */
621 : CHECK_VAL(io.t2open.out.write_time, 0);
622 : #endif
623 1 : CHECK_ALL_INFO(io.t2open.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
624 1 : CHECK_VAL(io.t2open.out.access, OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR);
625 1 : CHECK_VAL(io.t2open.out.ftype, 0);
626 1 : CHECK_VAL(io.t2open.out.devstate, 0);
627 1 : CHECK_VAL(io.t2open.out.action, OPENX_ACTION_CREATED);
628 1 : smbcli_close(cli->tree, fnum);
629 :
630 1 : status = torture_check_ea(cli, fname, ".CLASSINFO", "first value");
631 1 : CHECK_STATUS(status, io.t2open.in.num_eas
632 : ? NT_STATUS_OK : NT_STATUS_EAS_NOT_SUPPORTED);
633 1 : status = torture_check_ea(cli, fname, "EA TWO", "foo");
634 1 : CHECK_STATUS(status, io.t2open.in.num_eas
635 : ? NT_STATUS_OK : NT_STATUS_EAS_NOT_SUPPORTED);
636 1 : status = torture_check_ea(cli, fname, "X THIRD", "xy");
637 1 : CHECK_STATUS(status, io.t2open.in.num_eas
638 : ? NT_STATUS_OK : NT_STATUS_EAS_NOT_SUPPORTED);
639 :
640 : /* now check the search attrib for hidden files - win2003 ignores this? */
641 1 : SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
642 1 : CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
643 :
644 1 : status = smb_raw_open(cli->tree, tctx, &io);
645 1 : CHECK_STATUS(status, NT_STATUS_OK);
646 1 : smbcli_close(cli->tree, io.t2open.out.file.fnum);
647 :
648 1 : status = smb_raw_open(cli->tree, tctx, &io);
649 1 : CHECK_STATUS(status, NT_STATUS_OK);
650 1 : smbcli_close(cli->tree, io.t2open.out.file.fnum);
651 :
652 1 : SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
653 1 : smbcli_unlink(cli->tree, fname);
654 :
655 : /* and check attrib on create */
656 1 : io.t2open.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
657 1 : io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
658 1 : status = smb_raw_open(cli->tree, tctx, &io);
659 1 : CHECK_STATUS(status, NT_STATUS_OK);
660 :
661 : /* check timeout on create - win2003 ignores the timeout! */
662 1 : io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
663 1 : io.t2open.in.file_attrs = 0;
664 1 : io.t2open.in.timeout = 20000;
665 1 : io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
666 1 : status = smb_raw_open(cli->tree, tctx, &io);
667 1 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
668 :
669 2 : done:
670 1 : smbcli_close(cli->tree, fnum);
671 1 : smbcli_deltree(cli->tree, BASEDIR);
672 :
673 1 : return ret;
674 : }
675 :
676 :
677 : /*
678 : test RAW_OPEN_NTCREATEX
679 : */
680 1 : static bool test_ntcreatex(struct torture_context *tctx, struct smbcli_state *cli)
681 : {
682 : union smb_open io;
683 : union smb_fileinfo finfo;
684 1 : const char *fname = BASEDIR "\\torture_ntcreatex.txt";
685 1 : const char *dname = BASEDIR "\\torture_ntcreatex.dir";
686 : NTSTATUS status;
687 1 : int fnum = -1;
688 1 : bool ret = true;
689 : int i;
690 : struct {
691 : uint32_t open_disp;
692 : bool with_file;
693 : NTSTATUS correct_status;
694 1 : } open_funcs[] = {
695 : { NTCREATEX_DISP_SUPERSEDE, true, NT_STATUS_OK },
696 : { NTCREATEX_DISP_SUPERSEDE, false, NT_STATUS_OK },
697 : { NTCREATEX_DISP_OPEN, true, NT_STATUS_OK },
698 : { NTCREATEX_DISP_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
699 : { NTCREATEX_DISP_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
700 : { NTCREATEX_DISP_CREATE, false, NT_STATUS_OK },
701 : { NTCREATEX_DISP_OPEN_IF, true, NT_STATUS_OK },
702 : { NTCREATEX_DISP_OPEN_IF, false, NT_STATUS_OK },
703 : { NTCREATEX_DISP_OVERWRITE, true, NT_STATUS_OK },
704 : { NTCREATEX_DISP_OVERWRITE, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
705 : { NTCREATEX_DISP_OVERWRITE_IF, true, NT_STATUS_OK },
706 : { NTCREATEX_DISP_OVERWRITE_IF, false, NT_STATUS_OK },
707 : { 6, true, NT_STATUS_INVALID_PARAMETER },
708 : { 6, false, NT_STATUS_INVALID_PARAMETER },
709 : };
710 :
711 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
712 :
713 : /* reasonable default parameters */
714 1 : io.generic.level = RAW_OPEN_NTCREATEX;
715 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
716 1 : io.ntcreatex.in.root_fid.fnum = 0;
717 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
718 1 : io.ntcreatex.in.alloc_size = 1024*1024;
719 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
720 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
721 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
722 1 : io.ntcreatex.in.create_options = 0;
723 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
724 1 : io.ntcreatex.in.security_flags = 0;
725 1 : io.ntcreatex.in.fname = fname;
726 :
727 : /* test the open disposition */
728 15 : for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
729 14 : if (open_funcs[i].with_file) {
730 7 : fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
731 7 : if (fnum == -1) {
732 0 : torture_result(tctx, TORTURE_FAIL,
733 : "Failed to create file %s - %s\n",
734 : fname, smbcli_errstr(cli->tree));
735 0 : ret = false;
736 0 : goto done;
737 : }
738 7 : smbcli_close(cli->tree, fnum);
739 : }
740 14 : io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
741 14 : status = smb_raw_open(cli->tree, tctx, &io);
742 14 : if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
743 0 : torture_result(tctx, TORTURE_FAIL,
744 : "(%s) incorrect status %s should be %s "
745 : "(i=%d with_file=%d open_disp=%d)\n",
746 : __location__, nt_errstr(status),
747 : nt_errstr(open_funcs[i].correct_status),
748 0 : i, (int)open_funcs[i].with_file,
749 0 : (int)open_funcs[i].open_disp);
750 0 : ret = false;
751 : }
752 14 : if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
753 11 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
754 11 : smbcli_unlink(cli->tree, fname);
755 : }
756 : }
757 :
758 : /* basic field testing */
759 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
760 :
761 1 : status = smb_raw_open(cli->tree, tctx, &io);
762 1 : CHECK_STATUS(status, NT_STATUS_OK);
763 1 : fnum = io.ntcreatex.out.file.fnum;
764 :
765 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
766 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
767 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
768 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
769 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
770 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
771 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
772 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
773 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
774 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
775 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
776 :
777 : /* check fields when the file already existed */
778 1 : smbcli_close(cli->tree, fnum);
779 1 : smbcli_unlink(cli->tree, fname);
780 1 : fnum = create_complex_file(cli, tctx, fname);
781 1 : if (fnum == -1) {
782 0 : ret = false;
783 0 : goto done;
784 : }
785 1 : smbcli_close(cli->tree, fnum);
786 :
787 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
788 1 : status = smb_raw_open(cli->tree, tctx, &io);
789 1 : CHECK_STATUS(status, NT_STATUS_OK);
790 1 : fnum = io.ntcreatex.out.file.fnum;
791 :
792 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
793 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
794 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
795 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
796 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
797 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
798 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
799 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
800 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
801 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
802 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
803 1 : smbcli_close(cli->tree, fnum);
804 1 : smbcli_unlink(cli->tree, fname);
805 :
806 :
807 : /* create a directory */
808 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
809 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
810 1 : io.ntcreatex.in.alloc_size = 0;
811 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
812 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
813 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
814 1 : io.ntcreatex.in.create_options = 0;
815 1 : io.ntcreatex.in.fname = dname;
816 1 : fname = dname;
817 :
818 1 : smbcli_rmdir(cli->tree, fname);
819 1 : smbcli_unlink(cli->tree, fname);
820 :
821 1 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
822 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
823 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
824 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
825 1 : status = smb_raw_open(cli->tree, tctx, &io);
826 1 : CHECK_STATUS(status, NT_STATUS_OK);
827 1 : fnum = io.ntcreatex.out.file.fnum;
828 :
829 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
830 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
831 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
832 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
833 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
834 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
835 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
836 1 : CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
837 : FILE_ATTRIBUTE_DIRECTORY);
838 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
839 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
840 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
841 1 : CHECK_VAL(io.ntcreatex.out.is_directory, 1);
842 1 : CHECK_VAL(io.ntcreatex.out.size, 0);
843 1 : CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
844 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
845 1 : smbcli_unlink(cli->tree, fname);
846 :
847 :
848 1 : done:
849 1 : smbcli_close(cli->tree, fnum);
850 1 : smbcli_deltree(cli->tree, BASEDIR);
851 :
852 1 : return ret;
853 : }
854 :
855 :
856 : /*
857 : test RAW_OPEN_NTTRANS_CREATE
858 : */
859 1 : static bool test_nttrans_create(struct torture_context *tctx, struct smbcli_state *cli)
860 : {
861 : union smb_open io;
862 : union smb_fileinfo finfo;
863 1 : const char *fname = BASEDIR "\\torture_ntcreatex.txt";
864 1 : const char *dname = BASEDIR "\\torture_ntcreatex.dir";
865 : NTSTATUS status;
866 1 : int fnum = -1;
867 1 : bool ret = true;
868 : int i;
869 : uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
870 : uint32_t not_a_directory_mask, unexpected_mask;
871 : struct {
872 : uint32_t open_disp;
873 : bool with_file;
874 : NTSTATUS correct_status;
875 1 : } open_funcs[] = {
876 : { NTCREATEX_DISP_SUPERSEDE, true, NT_STATUS_OK },
877 : { NTCREATEX_DISP_SUPERSEDE, false, NT_STATUS_OK },
878 : { NTCREATEX_DISP_OPEN, true, NT_STATUS_OK },
879 : { NTCREATEX_DISP_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
880 : { NTCREATEX_DISP_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
881 : { NTCREATEX_DISP_CREATE, false, NT_STATUS_OK },
882 : { NTCREATEX_DISP_OPEN_IF, true, NT_STATUS_OK },
883 : { NTCREATEX_DISP_OPEN_IF, false, NT_STATUS_OK },
884 : { NTCREATEX_DISP_OVERWRITE, true, NT_STATUS_OK },
885 : { NTCREATEX_DISP_OVERWRITE, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
886 : { NTCREATEX_DISP_OVERWRITE_IF, true, NT_STATUS_OK },
887 : { NTCREATEX_DISP_OVERWRITE_IF, false, NT_STATUS_OK },
888 : { 6, true, NT_STATUS_INVALID_PARAMETER },
889 : { 6, false, NT_STATUS_INVALID_PARAMETER },
890 : };
891 :
892 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
893 :
894 : /* reasonable default parameters */
895 1 : io.generic.level = RAW_OPEN_NTTRANS_CREATE;
896 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
897 1 : io.ntcreatex.in.root_fid.fnum = 0;
898 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
899 1 : io.ntcreatex.in.alloc_size = 1024*1024;
900 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
901 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
902 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
903 1 : io.ntcreatex.in.create_options = 0;
904 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
905 1 : io.ntcreatex.in.security_flags = 0;
906 1 : io.ntcreatex.in.fname = fname;
907 1 : io.ntcreatex.in.sec_desc = NULL;
908 1 : io.ntcreatex.in.ea_list = NULL;
909 :
910 : /* test the open disposition */
911 15 : for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
912 14 : if (open_funcs[i].with_file) {
913 7 : fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
914 7 : if (fnum == -1) {
915 0 : torture_result(tctx, TORTURE_FAIL,
916 : "Failed to create file %s - %s\n",
917 : fname, smbcli_errstr(cli->tree));
918 0 : ret = false;
919 0 : goto done;
920 : }
921 7 : smbcli_close(cli->tree, fnum);
922 : }
923 14 : io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
924 14 : status = smb_raw_open(cli->tree, tctx, &io);
925 14 : if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
926 0 : torture_result(tctx, TORTURE_FAIL,
927 : "(%s) incorrect status %s should be %s "
928 : "(i=%d with_file=%d open_disp=%d)\n",
929 : __location__, nt_errstr(status),
930 : nt_errstr(open_funcs[i].correct_status),
931 0 : i, (int)open_funcs[i].with_file,
932 0 : (int)open_funcs[i].open_disp);
933 0 : ret = false;
934 : }
935 14 : if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
936 11 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
937 11 : smbcli_unlink(cli->tree, fname);
938 : }
939 : }
940 :
941 : /* basic field testing */
942 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
943 :
944 1 : status = smb_raw_open(cli->tree, tctx, &io);
945 1 : CHECK_STATUS(status, NT_STATUS_OK);
946 1 : fnum = io.ntcreatex.out.file.fnum;
947 :
948 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
949 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
950 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
951 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
952 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
953 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
954 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
955 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
956 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
957 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
958 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
959 :
960 : /* check fields when the file already existed */
961 1 : smbcli_close(cli->tree, fnum);
962 1 : smbcli_unlink(cli->tree, fname);
963 1 : fnum = create_complex_file(cli, tctx, fname);
964 1 : if (fnum == -1) {
965 0 : ret = false;
966 0 : goto done;
967 : }
968 1 : smbcli_close(cli->tree, fnum);
969 :
970 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
971 1 : status = smb_raw_open(cli->tree, tctx, &io);
972 1 : CHECK_STATUS(status, NT_STATUS_OK);
973 1 : fnum = io.ntcreatex.out.file.fnum;
974 :
975 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
976 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
977 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
978 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
979 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
980 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
981 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
982 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
983 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
984 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
985 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
986 1 : smbcli_close(cli->tree, fnum);
987 :
988 : /* check no-recall - don't pull a file from tape on a HSM */
989 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NO_RECALL;
990 1 : status = smb_raw_open(cli->tree, tctx, &io);
991 1 : CHECK_STATUS(status, NT_STATUS_OK);
992 1 : fnum = io.ntcreatex.out.file.fnum;
993 :
994 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
995 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
996 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
997 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
998 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
999 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
1000 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1001 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1002 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1003 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1004 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1005 1 : smbcli_close(cli->tree, fnum);
1006 :
1007 : /* Check some create options (these all should be ignored) */
1008 33 : for (i=0; i < 32; i++) {
1009 32 : uint32_t create_option =
1010 32 : ((uint32_t)1 << i) & NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
1011 32 : if (create_option == 0) {
1012 25 : continue;
1013 : }
1014 7 : io.ntcreatex.in.create_options = create_option;
1015 7 : status = smb_raw_open(cli->tree, tctx, &io);
1016 7 : if (!NT_STATUS_IS_OK(status)) {
1017 0 : torture_warning(tctx, "ntcreatex create option 0x%08x "
1018 : "gave %s - should give NT_STATUS_OK\n",
1019 : create_option, nt_errstr(status));
1020 : }
1021 7 : CHECK_STATUS(status, NT_STATUS_OK);
1022 7 : fnum = io.ntcreatex.out.file.fnum;
1023 :
1024 7 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1025 7 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
1026 7 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
1027 7 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
1028 7 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
1029 7 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
1030 7 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1031 7 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1032 7 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1033 7 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1034 7 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1035 7 : smbcli_close(cli->tree, fnum);
1036 : }
1037 :
1038 1 : io.ntcreatex.in.file_attr = 0;
1039 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1040 1 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1041 :
1042 : /* Check for options that should return NOT_SUPPORTED, OK or INVALID_PARAMETER */
1043 1 : ok_mask = 0;
1044 1 : not_supported_mask = 0;
1045 1 : invalid_parameter_mask = 0;
1046 1 : not_a_directory_mask = 0;
1047 1 : unexpected_mask = 0;
1048 33 : for (i=0; i < 32; i++) {
1049 32 : uint32_t create_option = (uint32_t)1<<i;
1050 32 : if (create_option & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
1051 1 : continue;
1052 : }
1053 31 : io.ntcreatex.in.create_options = create_option;
1054 31 : status = smb_raw_open(cli->tree, tctx, &io);
1055 31 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1056 1 : not_supported_mask |= create_option;
1057 30 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1058 18 : ok_mask |= create_option;
1059 18 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1060 12 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1061 11 : invalid_parameter_mask |= create_option;
1062 1 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1063 1 : not_a_directory_mask |= 1<<i;
1064 : } else {
1065 0 : unexpected_mask |= 1<<i;
1066 0 : torture_comment(tctx, "create option 0x%08x returned %s\n",
1067 : create_option, nt_errstr(status));
1068 : }
1069 : }
1070 :
1071 1 : CHECK_VAL(ok_mask, 0x00efcfce);
1072 1 : CHECK_VAL(not_a_directory_mask, 0x00000001);
1073 1 : CHECK_VAL(not_supported_mask, 0x00002000);
1074 1 : CHECK_VAL(invalid_parameter_mask, 0xff100030);
1075 1 : CHECK_VAL(unexpected_mask, 0x00000000);
1076 :
1077 1 : smbcli_unlink(cli->tree, fname);
1078 :
1079 :
1080 : /* create a directory */
1081 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1082 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1083 1 : io.ntcreatex.in.alloc_size = 0;
1084 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1085 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1086 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1087 1 : io.ntcreatex.in.create_options = 0;
1088 1 : io.ntcreatex.in.fname = dname;
1089 1 : fname = dname;
1090 :
1091 1 : smbcli_rmdir(cli->tree, fname);
1092 1 : smbcli_unlink(cli->tree, fname);
1093 :
1094 1 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1095 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1096 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1097 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1098 1 : status = smb_raw_open(cli->tree, tctx, &io);
1099 1 : CHECK_STATUS(status, NT_STATUS_OK);
1100 1 : fnum = io.ntcreatex.out.file.fnum;
1101 :
1102 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1103 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
1104 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
1105 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
1106 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
1107 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
1108 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1109 1 : CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1110 : FILE_ATTRIBUTE_DIRECTORY);
1111 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1112 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1113 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1114 1 : CHECK_VAL(io.ntcreatex.out.is_directory, 1);
1115 1 : CHECK_VAL(io.ntcreatex.out.size, 0);
1116 1 : CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
1117 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1118 1 : smbcli_unlink(cli->tree, fname);
1119 :
1120 :
1121 1 : done:
1122 1 : smbcli_close(cli->tree, fnum);
1123 1 : smbcli_deltree(cli->tree, BASEDIR);
1124 :
1125 1 : return ret;
1126 : }
1127 :
1128 : /*
1129 : test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
1130 :
1131 : I've got an application that does a similar sequence of ntcreate&x,
1132 : locking&x and another ntcreate&x with
1133 : open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
1134 : second open.
1135 : */
1136 1 : static bool test_ntcreatex_brlocked(struct torture_context *tctx, struct smbcli_state *cli)
1137 : {
1138 : union smb_open io, io1;
1139 : union smb_lock io2;
1140 : struct smb_lock_entry lock[1];
1141 1 : const char *fname = BASEDIR "\\torture_ntcreatex.txt";
1142 : NTSTATUS status;
1143 1 : bool ret = true;
1144 :
1145 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1146 :
1147 1 : torture_comment(tctx, "Testing ntcreatex with a byte range locked file\n");
1148 :
1149 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1150 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1151 1 : io.ntcreatex.in.root_fid.fnum = 0;
1152 1 : io.ntcreatex.in.access_mask = 0x2019f;
1153 1 : io.ntcreatex.in.alloc_size = 0;
1154 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1155 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1156 : NTCREATEX_SHARE_ACCESS_WRITE;
1157 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1158 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1159 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1160 1 : io.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1161 : NTCREATEX_SECURITY_ALL;
1162 1 : io.ntcreatex.in.fname = fname;
1163 :
1164 1 : status = smb_raw_open(cli->tree, tctx, &io);
1165 1 : CHECK_STATUS(status, NT_STATUS_OK);
1166 :
1167 1 : io2.lockx.level = RAW_LOCK_LOCKX;
1168 1 : io2.lockx.in.file.fnum = io.ntcreatex.out.file.fnum;
1169 1 : io2.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1170 1 : io2.lockx.in.timeout = 0;
1171 1 : io2.lockx.in.ulock_cnt = 0;
1172 1 : io2.lockx.in.lock_cnt = 1;
1173 1 : lock[0].pid = cli->session->pid;
1174 1 : lock[0].offset = 0;
1175 1 : lock[0].count = 0x1;
1176 1 : io2.lockx.in.locks = &lock[0];
1177 1 : status = smb_raw_lock(cli->tree, &io2);
1178 1 : CHECK_STATUS(status, NT_STATUS_OK);
1179 :
1180 1 : io1.generic.level = RAW_OPEN_NTCREATEX;
1181 1 : io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1182 1 : io1.ntcreatex.in.root_fid.fnum = 0;
1183 1 : io1.ntcreatex.in.access_mask = 0x20196;
1184 1 : io1.ntcreatex.in.alloc_size = 0;
1185 1 : io1.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1186 1 : io1.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1187 : NTCREATEX_SHARE_ACCESS_WRITE;
1188 1 : io1.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1189 1 : io1.ntcreatex.in.create_options = 0;
1190 1 : io1.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1191 1 : io1.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1192 : NTCREATEX_SECURITY_ALL;
1193 1 : io1.ntcreatex.in.fname = fname;
1194 :
1195 1 : status = smb_raw_open(cli->tree, tctx, &io1);
1196 1 : CHECK_STATUS(status, NT_STATUS_OK);
1197 :
1198 2 : done:
1199 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1200 1 : smbcli_close(cli->tree, io1.ntcreatex.out.file.fnum);
1201 1 : smbcli_deltree(cli->tree, BASEDIR);
1202 1 : return ret;
1203 : }
1204 :
1205 : /*
1206 : test RAW_OPEN_MKNEW
1207 : */
1208 1 : static bool test_mknew(struct torture_context *tctx, struct smbcli_state *cli)
1209 : {
1210 : union smb_open io;
1211 1 : const char *fname = BASEDIR "\\torture_mknew.txt";
1212 : NTSTATUS status;
1213 1 : int fnum = -1;
1214 1 : bool ret = true;
1215 1 : time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1216 : union smb_fileinfo finfo;
1217 :
1218 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1219 :
1220 1 : io.mknew.level = RAW_OPEN_MKNEW;
1221 1 : io.mknew.in.attrib = 0;
1222 1 : io.mknew.in.write_time = 0;
1223 1 : io.mknew.in.fname = fname;
1224 1 : status = smb_raw_open(cli->tree, tctx, &io);
1225 1 : CHECK_STATUS(status, NT_STATUS_OK);
1226 1 : fnum = io.mknew.out.file.fnum;
1227 :
1228 1 : status = smb_raw_open(cli->tree, tctx, &io);
1229 1 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
1230 :
1231 1 : smbcli_close(cli->tree, fnum);
1232 1 : smbcli_unlink(cli->tree, fname);
1233 :
1234 : /* make sure write_time works */
1235 1 : io.mknew.in.write_time = basetime;
1236 1 : status = smb_raw_open(cli->tree, tctx, &io);
1237 1 : CHECK_STATUS(status, NT_STATUS_OK);
1238 1 : fnum = io.mknew.out.file.fnum;
1239 1 : CHECK_TIME(basetime, write_time);
1240 :
1241 1 : smbcli_close(cli->tree, fnum);
1242 1 : smbcli_unlink(cli->tree, fname);
1243 :
1244 : /* make sure file_attrs works */
1245 1 : io.mknew.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1246 1 : status = smb_raw_open(cli->tree, tctx, &io);
1247 1 : CHECK_STATUS(status, NT_STATUS_OK);
1248 1 : fnum = io.mknew.out.file.fnum;
1249 1 : CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE,
1250 : attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1251 :
1252 2 : done:
1253 1 : smbcli_close(cli->tree, fnum);
1254 1 : smbcli_deltree(cli->tree, BASEDIR);
1255 :
1256 1 : return ret;
1257 : }
1258 :
1259 :
1260 : /*
1261 : test RAW_OPEN_CREATE
1262 : */
1263 1 : static bool test_create(struct torture_context *tctx, struct smbcli_state *cli)
1264 : {
1265 : union smb_open io;
1266 1 : const char *fname = BASEDIR "\\torture_create.txt";
1267 : NTSTATUS status;
1268 1 : int fnum = -1;
1269 1 : bool ret = true;
1270 1 : time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1271 : union smb_fileinfo finfo;
1272 :
1273 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1274 :
1275 1 : io.create.level = RAW_OPEN_CREATE;
1276 1 : io.create.in.attrib = 0;
1277 1 : io.create.in.write_time = 0;
1278 1 : io.create.in.fname = fname;
1279 1 : status = smb_raw_open(cli->tree, tctx, &io);
1280 1 : CHECK_STATUS(status, NT_STATUS_OK);
1281 1 : fnum = io.create.out.file.fnum;
1282 :
1283 1 : status = smb_raw_open(cli->tree, tctx, &io);
1284 1 : CHECK_STATUS(status, NT_STATUS_OK);
1285 :
1286 1 : smbcli_close(cli->tree, io.create.out.file.fnum);
1287 1 : smbcli_close(cli->tree, fnum);
1288 1 : smbcli_unlink(cli->tree, fname);
1289 :
1290 : /* make sure write_time works */
1291 1 : io.create.in.write_time = basetime;
1292 1 : status = smb_raw_open(cli->tree, tctx, &io);
1293 1 : CHECK_STATUS(status, NT_STATUS_OK);
1294 1 : fnum = io.create.out.file.fnum;
1295 1 : CHECK_TIME(basetime, write_time);
1296 :
1297 1 : smbcli_close(cli->tree, fnum);
1298 1 : smbcli_unlink(cli->tree, fname);
1299 :
1300 : /* make sure file_attrs works */
1301 1 : io.create.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1302 1 : status = smb_raw_open(cli->tree, tctx, &io);
1303 1 : CHECK_STATUS(status, NT_STATUS_OK);
1304 1 : fnum = io.create.out.file.fnum;
1305 1 : CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE,
1306 : attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1307 :
1308 2 : done:
1309 1 : smbcli_close(cli->tree, fnum);
1310 1 : smbcli_deltree(cli->tree, BASEDIR);
1311 :
1312 1 : return ret;
1313 : }
1314 :
1315 :
1316 : /*
1317 : test RAW_OPEN_CTEMP
1318 : */
1319 1 : static bool test_ctemp(struct torture_context *tctx, struct smbcli_state *cli)
1320 : {
1321 : union smb_open io;
1322 : NTSTATUS status;
1323 1 : int fnum = -1;
1324 1 : bool ret = true;
1325 1 : time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1326 : union smb_fileinfo finfo;
1327 1 : const char *name, *fname = NULL;
1328 :
1329 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1330 :
1331 1 : io.ctemp.level = RAW_OPEN_CTEMP;
1332 1 : io.ctemp.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1333 1 : io.ctemp.in.write_time = basetime;
1334 1 : io.ctemp.in.directory = BASEDIR;
1335 1 : status = smb_raw_open(cli->tree, tctx, &io);
1336 1 : CHECK_STATUS(status, NT_STATUS_OK);
1337 1 : fnum = io.ctemp.out.file.fnum;
1338 :
1339 1 : name = io.ctemp.out.name;
1340 :
1341 1 : finfo.generic.level = RAW_FILEINFO_NAME_INFO;
1342 1 : finfo.generic.in.file.fnum = fnum;
1343 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1344 1 : CHECK_STATUS(status, NT_STATUS_OK);
1345 :
1346 1 : fname = finfo.name_info.out.fname.s;
1347 1 : torture_comment(tctx, "ctemp name=%s real name=%s\n", name, fname);
1348 :
1349 1 : done:
1350 1 : smbcli_close(cli->tree, fnum);
1351 1 : smbcli_deltree(cli->tree, BASEDIR);
1352 :
1353 1 : return ret;
1354 : }
1355 :
1356 :
1357 : /*
1358 : test chained RAW_OPEN_OPENX_READX
1359 : */
1360 1 : static bool test_chained(struct torture_context *tctx, struct smbcli_state *cli)
1361 : {
1362 : union smb_open io;
1363 1 : const char *fname = BASEDIR "\\torture_chained.txt";
1364 : NTSTATUS status;
1365 1 : int fnum = -1;
1366 1 : bool ret = true;
1367 1 : const char buf[] = "test";
1368 : char buf2[4];
1369 :
1370 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1371 :
1372 1 : fnum = create_complex_file(cli, tctx, fname);
1373 :
1374 1 : smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1375 :
1376 1 : smbcli_close(cli->tree, fnum);
1377 :
1378 1 : io.openxreadx.level = RAW_OPEN_OPENX_READX;
1379 1 : io.openxreadx.in.fname = fname;
1380 1 : io.openxreadx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1381 1 : io.openxreadx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1382 1 : io.openxreadx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1383 1 : io.openxreadx.in.search_attrs = 0;
1384 1 : io.openxreadx.in.file_attrs = 0;
1385 1 : io.openxreadx.in.write_time = 0;
1386 1 : io.openxreadx.in.size = 1024*1024;
1387 1 : io.openxreadx.in.timeout = 0;
1388 :
1389 1 : io.openxreadx.in.offset = 0;
1390 1 : io.openxreadx.in.mincnt = sizeof(buf2);
1391 1 : io.openxreadx.in.maxcnt = sizeof(buf2);
1392 1 : io.openxreadx.in.remaining = 0;
1393 1 : io.openxreadx.out.data = (uint8_t *)buf2;
1394 :
1395 1 : status = smb_raw_open(cli->tree, tctx, &io);
1396 1 : CHECK_STATUS(status, NT_STATUS_OK);
1397 1 : fnum = io.openxreadx.out.file.fnum;
1398 :
1399 1 : if (memcmp(buf, buf2, MIN(sizeof(buf), sizeof(buf2))) != 0) {
1400 0 : torture_result(tctx, TORTURE_FAIL,
1401 : "wrong data in reply buffer\n");
1402 0 : ret = false;
1403 : }
1404 :
1405 2 : done:
1406 1 : smbcli_close(cli->tree, fnum);
1407 1 : smbcli_deltree(cli->tree, BASEDIR);
1408 :
1409 1 : return ret;
1410 : }
1411 :
1412 : /*
1413 : test RAW_OPEN_OPENX without a leading slash on the path.
1414 : NetApp filers are known to fail on this.
1415 :
1416 : */
1417 1 : static bool test_no_leading_slash(struct torture_context *tctx, struct smbcli_state *cli)
1418 : {
1419 : union smb_open io;
1420 1 : const char *fname = BASEDIR "\\torture_no_leading_slash.txt";
1421 : NTSTATUS status;
1422 1 : int fnum = -1;
1423 1 : bool ret = true;
1424 1 : const char buf[] = "test";
1425 :
1426 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1427 :
1428 1 : smbcli_unlink(cli->tree, fname);
1429 :
1430 : /* Create the file */
1431 1 : fnum = create_complex_file(cli, tctx, fname);
1432 1 : smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1433 1 : smbcli_close(cli->tree, fnum);
1434 :
1435 : /* Prepare to open the file using path without leading slash */
1436 1 : io.openx.level = RAW_OPEN_OPENX;
1437 1 : io.openx.in.fname = fname + 1;
1438 1 : io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1439 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1440 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1441 1 : io.openx.in.search_attrs = 0;
1442 1 : io.openx.in.file_attrs = 0;
1443 1 : io.openx.in.write_time = 0;
1444 1 : io.openx.in.size = 1024*1024;
1445 1 : io.openx.in.timeout = 0;
1446 :
1447 1 : status = smb_raw_open(cli->tree, tctx, &io);
1448 1 : CHECK_STATUS(status, NT_STATUS_OK);
1449 1 : fnum = io.openx.out.file.fnum;
1450 :
1451 1 : done:
1452 1 : smbcli_close(cli->tree, fnum);
1453 1 : smbcli_deltree(cli->tree, BASEDIR);
1454 :
1455 1 : return ret;
1456 : }
1457 :
1458 : /*
1459 : test RAW_OPEN_OPENX against an existing directory to
1460 : ensure it returns NT_STATUS_FILE_IS_A_DIRECTORY.
1461 : Samba 3.2.0 - 3.2.6 are known to fail this.
1462 :
1463 : */
1464 1 : static bool test_openx_over_dir(struct torture_context *tctx, struct smbcli_state *cli)
1465 : {
1466 : union smb_open io;
1467 1 : const char *fname = BASEDIR "\\openx_over_dir";
1468 : NTSTATUS status;
1469 1 : int d_fnum = -1;
1470 1 : int fnum = -1;
1471 1 : bool ret = true;
1472 :
1473 1 : ZERO_STRUCT(io);
1474 :
1475 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1476 :
1477 : /* Create the Directory */
1478 1 : status = create_directory_handle(cli->tree, fname, &d_fnum);
1479 1 : smbcli_close(cli->tree, d_fnum);
1480 :
1481 : /* Prepare to open the file over the directory. */
1482 1 : io.openx.level = RAW_OPEN_OPENX;
1483 1 : io.openx.in.fname = fname;
1484 1 : io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1485 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1486 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1487 1 : io.openx.in.search_attrs = 0;
1488 1 : io.openx.in.file_attrs = 0;
1489 1 : io.openx.in.write_time = 0;
1490 1 : io.openx.in.size = 1024*1024;
1491 1 : io.openx.in.timeout = 0;
1492 :
1493 1 : status = smb_raw_open(cli->tree, tctx, &io);
1494 1 : CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
1495 1 : fnum = io.openx.out.file.fnum;
1496 :
1497 1 : done:
1498 1 : smbcli_close(cli->tree, fnum);
1499 1 : smbcli_deltree(cli->tree, BASEDIR);
1500 :
1501 1 : return ret;
1502 : }
1503 :
1504 :
1505 : /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
1506 :
1507 1 : static bool test_raw_open_multi(struct torture_context *tctx, struct smbcli_state *cli_ignored)
1508 : {
1509 : struct smbcli_state *cli;
1510 1 : TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
1511 1 : const char *fname = "\\test_oplock.dat";
1512 : NTSTATUS status;
1513 1 : bool ret = true;
1514 : union smb_open io;
1515 : struct smbcli_state **clients;
1516 : struct smbcli_request **requests;
1517 : union smb_open *ios;
1518 1 : const char *host = torture_setting_string(tctx, "host", NULL);
1519 1 : const char *share = torture_setting_string(tctx, "share", NULL);
1520 1 : int i, num_files = 3;
1521 1 : int num_ok = 0;
1522 1 : int num_collision = 0;
1523 :
1524 1 : clients = talloc_array(mem_ctx, struct smbcli_state *, num_files);
1525 1 : requests = talloc_array(mem_ctx, struct smbcli_request *, num_files);
1526 1 : ios = talloc_array(mem_ctx, union smb_open, num_files);
1527 1 : if ((tctx->ev == NULL) || (clients == NULL) || (requests == NULL) ||
1528 : (ios == NULL)) {
1529 0 : torture_result(tctx, TORTURE_FAIL, "(%s): talloc failed\n",
1530 : __location__);
1531 0 : return false;
1532 : }
1533 :
1534 1 : if (!torture_open_connection_share(mem_ctx, &cli, tctx, host, share, tctx->ev)) {
1535 0 : return false;
1536 : }
1537 :
1538 1 : cli->tree->session->transport->options.request_timeout = 60;
1539 :
1540 4 : for (i=0; i<num_files; i++) {
1541 3 : if (!torture_open_connection_share(mem_ctx, &(clients[i]),
1542 : tctx, host, share, tctx->ev)) {
1543 0 : torture_result(tctx, TORTURE_FAIL,
1544 : "(%s): Could not open %d'th connection\n",
1545 : __location__, i);
1546 0 : return false;
1547 : }
1548 3 : clients[i]->tree->session->transport->options.request_timeout = 60;
1549 : }
1550 :
1551 : /* cleanup */
1552 1 : smbcli_unlink(cli->tree, fname);
1553 :
1554 : /*
1555 : base ntcreatex parms
1556 : */
1557 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1558 1 : io.ntcreatex.in.root_fid.fnum = 0;
1559 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1560 1 : io.ntcreatex.in.alloc_size = 0;
1561 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1562 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1563 : NTCREATEX_SHARE_ACCESS_WRITE|
1564 : NTCREATEX_SHARE_ACCESS_DELETE;
1565 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1566 1 : io.ntcreatex.in.create_options = 0;
1567 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1568 1 : io.ntcreatex.in.security_flags = 0;
1569 1 : io.ntcreatex.in.fname = fname;
1570 1 : io.ntcreatex.in.flags = 0;
1571 :
1572 4 : for (i=0; i<num_files; i++) {
1573 3 : ios[i] = io;
1574 3 : requests[i] = smb_raw_open_send(clients[i]->tree, &ios[i]);
1575 3 : if (requests[i] == NULL) {
1576 0 : torture_result(tctx, TORTURE_FAIL,
1577 : "(%s): could not send %d'th request\n",
1578 : __location__, i);
1579 0 : return false;
1580 : }
1581 : }
1582 :
1583 1 : torture_comment(tctx, "waiting for replies\n");
1584 9 : while (1) {
1585 10 : bool unreplied = false;
1586 18 : for (i=0; i<num_files; i++) {
1587 17 : if (requests[i] == NULL) {
1588 5 : continue;
1589 : }
1590 12 : if (requests[i]->state < SMBCLI_REQUEST_DONE) {
1591 9 : unreplied = true;
1592 9 : break;
1593 : }
1594 3 : status = smb_raw_open_recv(requests[i], mem_ctx,
1595 3 : &ios[i]);
1596 :
1597 3 : torture_comment(tctx, "File %d returned status %s\n", i,
1598 : nt_errstr(status));
1599 :
1600 3 : if (NT_STATUS_IS_OK(status)) {
1601 1 : num_ok += 1;
1602 : }
1603 :
1604 3 : if (NT_STATUS_EQUAL(status,
1605 : NT_STATUS_OBJECT_NAME_COLLISION)) {
1606 2 : num_collision += 1;
1607 : }
1608 :
1609 3 : requests[i] = NULL;
1610 : }
1611 10 : if (!unreplied) {
1612 1 : break;
1613 : }
1614 :
1615 9 : if (tevent_loop_once(tctx->ev) != 0) {
1616 0 : torture_result(tctx, TORTURE_FAIL,
1617 : "(%s): tevent_loop_once failed\n", __location__);
1618 0 : return false;
1619 : }
1620 : }
1621 :
1622 1 : if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1623 0 : ret = false;
1624 : }
1625 :
1626 4 : for (i=0; i<num_files; i++) {
1627 3 : torture_close_connection(clients[i]);
1628 : }
1629 1 : talloc_free(mem_ctx);
1630 1 : return ret;
1631 : }
1632 :
1633 : /*
1634 : test opening for delete on a read-only attribute file.
1635 : */
1636 1 : static bool test_open_for_delete(struct torture_context *tctx, struct smbcli_state *cli)
1637 : {
1638 : union smb_open io;
1639 : union smb_fileinfo finfo;
1640 1 : const char *fname = BASEDIR "\\torture_open_for_delete.txt";
1641 : NTSTATUS status;
1642 1 : int fnum = -1;
1643 1 : bool ret = true;
1644 :
1645 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1646 :
1647 : /* reasonable default parameters */
1648 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1649 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1650 1 : io.ntcreatex.in.root_fid.fnum = 0;
1651 1 : io.ntcreatex.in.alloc_size = 0;
1652 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1653 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_READONLY;
1654 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1655 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1656 1 : io.ntcreatex.in.create_options = 0;
1657 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1658 1 : io.ntcreatex.in.security_flags = 0;
1659 1 : io.ntcreatex.in.fname = fname;
1660 :
1661 : /* Create the readonly file. */
1662 :
1663 1 : status = smb_raw_open(cli->tree, tctx, &io);
1664 1 : CHECK_STATUS(status, NT_STATUS_OK);
1665 1 : fnum = io.ntcreatex.out.file.fnum;
1666 :
1667 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1668 1 : io.ntcreatex.in.create_options = 0;
1669 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
1670 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1671 1 : smbcli_close(cli->tree, fnum);
1672 :
1673 : /* Now try and open for delete only - should succeed. */
1674 1 : io.ntcreatex.in.access_mask = SEC_STD_DELETE;
1675 1 : io.ntcreatex.in.file_attr = 0;
1676 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
1677 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1678 1 : status = smb_raw_open(cli->tree, tctx, &io);
1679 1 : CHECK_STATUS(status, NT_STATUS_OK);
1680 :
1681 1 : smbcli_unlink(cli->tree, fname);
1682 :
1683 1 : done:
1684 1 : smbcli_close(cli->tree, fnum);
1685 1 : smbcli_deltree(cli->tree, BASEDIR);
1686 :
1687 1 : return ret;
1688 : }
1689 :
1690 : /*
1691 : test chained RAW_OPEN_NTCREATEX_READX
1692 : Send chained NTCREATEX_READX on a file that doesn't exist, then create
1693 : the file and try again.
1694 : */
1695 1 : static bool test_chained_ntcreatex_readx(struct torture_context *tctx, struct smbcli_state *cli)
1696 : {
1697 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1698 : union smb_open io;
1699 1 : const char *fname = BASEDIR "\\torture_chained.txt";
1700 : NTSTATUS status;
1701 1 : int fnum = -1;
1702 1 : bool ret = true;
1703 1 : const char buf[] = "test";
1704 : char buf2[4];
1705 :
1706 1 : ZERO_STRUCT(io);
1707 :
1708 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1709 :
1710 1 : torture_comment(tctx, "Checking RAW_NTCREATEX_READX chained on "
1711 : "non-existent file \n");
1712 :
1713 : /* ntcreatex parameters */
1714 1 : io.generic.level = RAW_OPEN_NTCREATEX_READX;
1715 1 : io.ntcreatexreadx.in.flags = 0;
1716 1 : io.ntcreatexreadx.in.root_fid.fnum = 0;
1717 1 : io.ntcreatexreadx.in.access_mask = SEC_FILE_READ_DATA;
1718 1 : io.ntcreatexreadx.in.alloc_size = 0;
1719 1 : io.ntcreatexreadx.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1720 1 : io.ntcreatexreadx.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1721 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
1722 1 : io.ntcreatexreadx.in.open_disposition = NTCREATEX_DISP_OPEN;
1723 1 : io.ntcreatexreadx.in.create_options = 0;
1724 1 : io.ntcreatexreadx.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1725 1 : io.ntcreatexreadx.in.security_flags = 0;
1726 1 : io.ntcreatexreadx.in.fname = fname;
1727 :
1728 : /* readx parameters */
1729 1 : io.ntcreatexreadx.in.offset = 0;
1730 1 : io.ntcreatexreadx.in.mincnt = sizeof(buf2);
1731 1 : io.ntcreatexreadx.in.maxcnt = sizeof(buf2);
1732 1 : io.ntcreatexreadx.in.remaining = 0;
1733 1 : io.ntcreatexreadx.out.data = (uint8_t *)buf2;
1734 :
1735 : /* try to open the non-existent file */
1736 1 : status = smb_raw_open(cli->tree, mem_ctx, &io);
1737 1 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1738 1 : fnum = io.ntcreatexreadx.out.file.fnum;
1739 :
1740 1 : smbcli_close(cli->tree, fnum);
1741 1 : smbcli_unlink(cli->tree, fname);
1742 :
1743 1 : torture_comment(tctx, "Checking RAW_NTCREATEX_READX chained on "
1744 : "existing file \n");
1745 :
1746 1 : fnum = create_complex_file(cli, mem_ctx, fname);
1747 1 : smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1748 1 : smbcli_close(cli->tree, fnum);
1749 :
1750 1 : status = smb_raw_open(cli->tree, mem_ctx, &io);
1751 1 : CHECK_STATUS(status, NT_STATUS_OK);
1752 1 : fnum = io.ntcreatexreadx.out.file.fnum;
1753 :
1754 1 : if (memcmp(buf, buf2, MIN(sizeof(buf), sizeof(buf2))) != 0) {
1755 0 : torture_result(tctx, TORTURE_FAIL,
1756 : "(%s): wrong data in reply buffer\n", __location__);
1757 0 : ret = false;
1758 : }
1759 :
1760 2 : done:
1761 1 : smbcli_close(cli->tree, fnum);
1762 1 : smbcli_deltree(cli->tree, BASEDIR);
1763 1 : talloc_free(mem_ctx);
1764 :
1765 1 : return ret;
1766 : }
1767 :
1768 1 : static bool test_ntcreatex_opendisp_dir(struct torture_context *tctx,
1769 : struct smbcli_state *cli)
1770 : {
1771 1 : const char *dname = BASEDIR "\\torture_ntcreatex_opendisp_dir";
1772 : NTSTATUS status;
1773 1 : bool ret = true;
1774 : int i;
1775 : struct {
1776 : uint32_t open_disp;
1777 : bool dir_exists;
1778 : NTSTATUS correct_status;
1779 1 : } open_funcs_dir[] = {
1780 : { NTCREATEX_DISP_SUPERSEDE, true, NT_STATUS_INVALID_PARAMETER },
1781 : { NTCREATEX_DISP_SUPERSEDE, false, NT_STATUS_INVALID_PARAMETER },
1782 : { NTCREATEX_DISP_OPEN, true, NT_STATUS_OK },
1783 : { NTCREATEX_DISP_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
1784 : { NTCREATEX_DISP_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
1785 : { NTCREATEX_DISP_CREATE, false, NT_STATUS_OK },
1786 : { NTCREATEX_DISP_OPEN_IF, true, NT_STATUS_OK },
1787 : { NTCREATEX_DISP_OPEN_IF, false, NT_STATUS_OK },
1788 : { NTCREATEX_DISP_OVERWRITE, true, NT_STATUS_INVALID_PARAMETER },
1789 : { NTCREATEX_DISP_OVERWRITE, false, NT_STATUS_INVALID_PARAMETER },
1790 : { NTCREATEX_DISP_OVERWRITE_IF, true, NT_STATUS_INVALID_PARAMETER },
1791 : { NTCREATEX_DISP_OVERWRITE_IF, false, NT_STATUS_INVALID_PARAMETER },
1792 : { 6, true, NT_STATUS_INVALID_PARAMETER },
1793 : { 6, false, NT_STATUS_INVALID_PARAMETER },
1794 : };
1795 : union smb_open io;
1796 :
1797 1 : ZERO_STRUCT(io);
1798 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1799 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1800 1 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1801 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1802 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1803 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1804 1 : io.ntcreatex.in.fname = dname;
1805 :
1806 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1807 :
1808 1 : smbcli_rmdir(cli->tree, dname);
1809 1 : smbcli_unlink(cli->tree, dname);
1810 :
1811 : /* test the open disposition for directories */
1812 1 : torture_comment(tctx, "Testing open dispositions for directories...\n");
1813 :
1814 15 : for (i=0; i<ARRAY_SIZE(open_funcs_dir); i++) {
1815 14 : if (open_funcs_dir[i].dir_exists) {
1816 7 : status = smbcli_mkdir(cli->tree, dname);
1817 7 : if (!NT_STATUS_IS_OK(status)) {
1818 0 : torture_result(tctx, TORTURE_FAIL,
1819 : "(%s): Failed to make directory "
1820 : "%s - %s\n", __location__, dname,
1821 : smbcli_errstr(cli->tree));
1822 0 : ret = false;
1823 0 : goto done;
1824 : }
1825 : }
1826 :
1827 14 : io.ntcreatex.in.open_disposition = open_funcs_dir[i].open_disp;
1828 14 : status = smb_raw_open(cli->tree, tctx, &io);
1829 14 : if (!NT_STATUS_EQUAL(status, open_funcs_dir[i].correct_status)) {
1830 0 : torture_result(tctx, TORTURE_FAIL,
1831 : "(%s) incorrect status %s should be %s "
1832 : "(i=%d dir_exists=%d open_disp=%d)\n",
1833 : __location__, nt_errstr(status),
1834 : nt_errstr(open_funcs_dir[i].correct_status),
1835 0 : i, (int)open_funcs_dir[i].dir_exists,
1836 0 : (int)open_funcs_dir[i].open_disp);
1837 0 : ret = false;
1838 : }
1839 14 : if (NT_STATUS_IS_OK(status) || open_funcs_dir[i].dir_exists) {
1840 9 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1841 9 : smbcli_rmdir(cli->tree, dname);
1842 : }
1843 : }
1844 :
1845 1 : done:
1846 1 : smbcli_deltree(cli->tree, BASEDIR);
1847 :
1848 1 : return ret;
1849 : }
1850 :
1851 : /**
1852 : * Test what happens when trying to open a file with directory parameters and
1853 : * vice-versa. Also test that NTCREATEX_OPTIONS_DIRECTORY is treated as
1854 : * mandatory and FILE_ATTRIBUTE_DIRECTORY is advisory for directory
1855 : * creation/opening.
1856 : */
1857 1 : static bool test_ntcreatexdir(struct torture_context *tctx,
1858 : struct smbcli_state *cli)
1859 : {
1860 : union smb_open io;
1861 1 : const char *fname = BASEDIR "\\torture_ntcreatex.txt";
1862 1 : const char *dname = BASEDIR "\\torture_ntcreatex_dir";
1863 : NTSTATUS status;
1864 : int i;
1865 :
1866 : struct {
1867 : uint32_t open_disp;
1868 : uint32_t file_attr;
1869 : uint32_t create_options;
1870 : NTSTATUS correct_status;
1871 1 : } open_funcs[] = {
1872 : { NTCREATEX_DISP_SUPERSEDE, 0, NTCREATEX_OPTIONS_DIRECTORY,
1873 : NT_STATUS_INVALID_PARAMETER },
1874 : { NTCREATEX_DISP_OPEN, 0, NTCREATEX_OPTIONS_DIRECTORY,
1875 : NT_STATUS_OBJECT_NAME_NOT_FOUND },
1876 : { NTCREATEX_DISP_CREATE, 0, NTCREATEX_OPTIONS_DIRECTORY,
1877 : NT_STATUS_OK },
1878 : { NTCREATEX_DISP_OPEN_IF, 0, NTCREATEX_OPTIONS_DIRECTORY,
1879 : NT_STATUS_OK },
1880 : { NTCREATEX_DISP_OVERWRITE, 0, NTCREATEX_OPTIONS_DIRECTORY,
1881 : NT_STATUS_INVALID_PARAMETER },
1882 : { NTCREATEX_DISP_OVERWRITE_IF, 0, NTCREATEX_OPTIONS_DIRECTORY,
1883 : NT_STATUS_INVALID_PARAMETER },
1884 : { NTCREATEX_DISP_SUPERSEDE, FILE_ATTRIBUTE_DIRECTORY, 0,
1885 : NT_STATUS_OK },
1886 : { NTCREATEX_DISP_OPEN, FILE_ATTRIBUTE_DIRECTORY, 0,
1887 : NT_STATUS_OBJECT_NAME_NOT_FOUND },
1888 : { NTCREATEX_DISP_CREATE, FILE_ATTRIBUTE_DIRECTORY, 0,
1889 : NT_STATUS_OK },
1890 : { NTCREATEX_DISP_OPEN_IF, FILE_ATTRIBUTE_DIRECTORY, 0,
1891 : NT_STATUS_OK },
1892 : { NTCREATEX_DISP_OVERWRITE, FILE_ATTRIBUTE_DIRECTORY, 0,
1893 : NT_STATUS_OBJECT_NAME_NOT_FOUND },
1894 : { NTCREATEX_DISP_OVERWRITE_IF, FILE_ATTRIBUTE_DIRECTORY, 0,
1895 : NT_STATUS_OK },
1896 :
1897 : };
1898 :
1899 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1900 :
1901 : /* setup some base params. */
1902 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1903 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1904 1 : io.ntcreatex.in.root_fid.fnum = 0;
1905 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1906 1 : io.ntcreatex.in.alloc_size = 0;
1907 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1908 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1909 1 : io.ntcreatex.in.security_flags = 0;
1910 1 : io.ntcreatex.in.fname = fname;
1911 :
1912 : /*
1913 : * Test the validity checking for create dispositions, which is done
1914 : * against the requested parameters rather than what's actually on
1915 : * disk.
1916 : */
1917 13 : for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
1918 12 : io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
1919 12 : io.ntcreatex.in.file_attr = open_funcs[i].file_attr;
1920 12 : io.ntcreatex.in.create_options = open_funcs[i].create_options;
1921 12 : status = smb_raw_open(cli->tree, tctx, &io);
1922 12 : if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
1923 0 : torture_result(tctx, TORTURE_FAIL,
1924 : "(%s) incorrect status %s should be %s "
1925 : "(i=%d open_disp=%d)\n",
1926 : __location__, nt_errstr(status),
1927 : nt_errstr(open_funcs[i].correct_status),
1928 0 : i, (int)open_funcs[i].open_disp);
1929 0 : return false;
1930 : }
1931 : /* Close and delete the file. */
1932 12 : if (NT_STATUS_IS_OK(status)) {
1933 6 : if (open_funcs[i].create_options != 0) {
1934 : /* out attrib should be a directory. */
1935 2 : torture_assert_int_equal(tctx,
1936 : io.ntcreatex.out.attrib,
1937 : FILE_ATTRIBUTE_DIRECTORY, "should have "
1938 : "created a directory");
1939 :
1940 2 : smbcli_close(cli->tree,
1941 2 : io.ntcreatex.out.file.fnum);
1942 :
1943 : /* Make sure unlink fails. */
1944 2 : status = smbcli_unlink(cli->tree, fname);
1945 2 : torture_assert_ntstatus_equal(tctx, status,
1946 : NT_STATUS_FILE_IS_A_DIRECTORY,
1947 : "unlink should fail for a directory");
1948 :
1949 2 : status = smbcli_rmdir(cli->tree, fname);
1950 2 : torture_assert_ntstatus_ok(tctx, status,
1951 : "rmdir failed");
1952 : } else {
1953 4 : torture_assert_int_equal(tctx,
1954 : io.ntcreatex.out.attrib,
1955 : FILE_ATTRIBUTE_ARCHIVE, "should not have "
1956 : "created a directory");
1957 :
1958 4 : smbcli_close(cli->tree,
1959 4 : io.ntcreatex.out.file.fnum);
1960 :
1961 : /* Make sure rmdir fails. */
1962 4 : status = smbcli_rmdir(cli->tree, fname);
1963 4 : torture_assert_ntstatus_equal(tctx, status,
1964 : NT_STATUS_NOT_A_DIRECTORY,
1965 : "rmdir should fail for a file");
1966 :
1967 4 : status = smbcli_unlink(cli->tree, fname);
1968 4 : torture_assert_ntstatus_ok(tctx, status,
1969 : "unlink failed");
1970 : }
1971 : }
1972 : }
1973 :
1974 : /* Create a file. */
1975 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1976 1 : io.ntcreatex.in.create_options = 0;
1977 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1978 1 : status = smb_raw_open(cli->tree, tctx, &io);
1979 1 : torture_assert_ntstatus_ok(tctx, status, "Failed to create file.");
1980 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1981 :
1982 : /* Try and open the file with file_attr_dir and check the error. */
1983 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1984 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1985 :
1986 1 : status = smb_raw_open(cli->tree, tctx, &io);
1987 1 : torture_assert_ntstatus_ok(tctx, status, "FILE_ATTRIBUTE_DIRECTORY "
1988 : "doesn't produce a hard failure.");
1989 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1990 :
1991 : /* Try and open file with createx_option_dir and check the error. */
1992 1 : io.ntcreatex.in.file_attr = 0;
1993 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1994 :
1995 1 : status = smb_raw_open(cli->tree, tctx, &io);
1996 1 : torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_A_DIRECTORY,
1997 : "NTCREATEX_OPTIONS_DIRECTORY will a file from being opened.");
1998 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1999 :
2000 : /* Delete the file and move onto directory testing. */
2001 1 : smbcli_unlink(cli->tree, fname);
2002 :
2003 : /* Now try some tests on a directory. */
2004 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2005 1 : io.ntcreatex.in.file_attr = 0;
2006 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2007 1 : io.ntcreatex.in.fname = dname;
2008 :
2009 1 : status = smb_raw_open(cli->tree, tctx, &io);
2010 1 : torture_assert_ntstatus_ok(tctx, status, "Failed to create dir.");
2011 :
2012 : /* out attrib should be a directory. */
2013 1 : torture_assert_int_equal(tctx, io.ntcreatex.out.attrib,
2014 : FILE_ATTRIBUTE_DIRECTORY, "should have created a directory");
2015 :
2016 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2017 :
2018 : /* Try and open it with normal attr and check the error. */
2019 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2020 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2021 :
2022 1 : status = smb_raw_open(cli->tree, tctx, &io);
2023 1 : torture_assert_ntstatus_ok(tctx, status, "FILE_ATTRIBUTE_NORMAL "
2024 : "doesn't produce a hard failure.");
2025 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2026 :
2027 : /* Try and open it with file create_options and check the error. */
2028 1 : io.ntcreatex.in.file_attr = 0;
2029 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
2030 :
2031 1 : status = smb_raw_open(cli->tree, tctx, &io);
2032 1 : torture_assert_ntstatus_equal(tctx, status,
2033 : NT_STATUS_FILE_IS_A_DIRECTORY,
2034 : "NTCREATEX_OPTIONS_NON_DIRECTORY_FILE should be returned ");
2035 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2036 :
2037 1 : smbcli_deltree(cli->tree, BASEDIR);
2038 :
2039 1 : return true;
2040 : }
2041 :
2042 : /*
2043 : test opening with truncate on an already open file
2044 : returns share violation and doesn't truncate the file.
2045 : Regression test for bug #10671.
2046 : */
2047 1 : static bool test_open_for_truncate(struct torture_context *tctx, struct smbcli_state *cli)
2048 : {
2049 : union smb_open io;
2050 : union smb_fileinfo finfo;
2051 1 : const char *fname = BASEDIR "\\torture_open_for_truncate.txt";
2052 : NTSTATUS status;
2053 1 : int fnum = -1;
2054 1 : ssize_t val = 0;
2055 1 : char c = '\0';
2056 1 : bool ret = true;
2057 :
2058 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
2059 : "Failed to setup up test directory: " BASEDIR);
2060 :
2061 1 : torture_comment(tctx, "Testing open truncate disposition.\n");
2062 :
2063 : /* reasonable default parameters */
2064 1 : ZERO_STRUCT(io);
2065 1 : io.generic.level = RAW_OPEN_NTCREATEX;
2066 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
2067 1 : io.ntcreatex.in.root_fid.fnum = 0;
2068 1 : io.ntcreatex.in.alloc_size = 0;
2069 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2070 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2071 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2072 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2073 1 : io.ntcreatex.in.create_options = 0;
2074 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2075 1 : io.ntcreatex.in.security_flags = 0;
2076 1 : io.ntcreatex.in.fname = fname;
2077 :
2078 1 : status = smb_raw_open(cli->tree, tctx, &io);
2079 1 : CHECK_STATUS(status, NT_STATUS_OK);
2080 1 : fnum = io.ntcreatex.out.file.fnum;
2081 :
2082 : /* Write a byte at offset 1k-1. */
2083 1 : val =smbcli_write(cli->tree, fnum, 0, &c, 1023, 1);
2084 1 : torture_assert_int_equal(tctx, val, 1, "write failed\n");
2085 :
2086 : /* Now try and open for read/write with truncate - should fail. */
2087 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_WRITE|SEC_RIGHTS_FILE_READ;
2088 1 : io.ntcreatex.in.file_attr = 0;
2089 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2090 : NTCREATEX_SHARE_ACCESS_WRITE |
2091 : NTCREATEX_SHARE_ACCESS_DELETE;
2092 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2093 1 : status = smb_raw_open(cli->tree, tctx, &io);
2094 1 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
2095 :
2096 : /* Ensure file size is still 1k */
2097 1 : finfo.generic.level = RAW_FILEINFO_GETATTRE;
2098 1 : finfo.generic.in.file.fnum = fnum;
2099 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
2100 1 : CHECK_STATUS(status, NT_STATUS_OK);
2101 1 : CHECK_VAL(finfo.getattre.out.size, 1024);
2102 :
2103 1 : smbcli_close(cli->tree, fnum);
2104 :
2105 1 : status = smb_raw_open(cli->tree, tctx, &io);
2106 1 : CHECK_STATUS(status, NT_STATUS_OK);
2107 1 : fnum = io.ntcreatex.out.file.fnum;
2108 :
2109 : /* Ensure truncate actually works */
2110 1 : finfo.generic.level = RAW_FILEINFO_GETATTRE;
2111 1 : finfo.generic.in.file.fnum = fnum;
2112 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
2113 1 : CHECK_STATUS(status, NT_STATUS_OK);
2114 1 : CHECK_VAL(finfo.getattre.out.size, 0);
2115 :
2116 1 : smbcli_close(cli->tree, fnum);
2117 1 : smbcli_unlink(cli->tree, fname);
2118 :
2119 1 : done:
2120 1 : smbcli_close(cli->tree, fnum);
2121 1 : smbcli_deltree(cli->tree, BASEDIR);
2122 :
2123 1 : return ret;
2124 : }
2125 :
2126 : /**
2127 : * Test for file size to be 0 after create with FILE_SUPERSEDE
2128 : */
2129 1 : static bool test_ntcreatex_supersede(struct torture_context *tctx, struct smbcli_state *cli)
2130 : {
2131 : union smb_open io;
2132 : union smb_setfileinfo sfi;
2133 : union smb_fileinfo finfo;
2134 1 : const char *fname = BASEDIR "\\torture_ntcreatex_supersede.txt";
2135 : NTSTATUS status;
2136 1 : int fnum = -1;
2137 1 : bool ret = true;
2138 :
2139 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
2140 :
2141 : /* reasonable default parameters */
2142 1 : io.generic.level = RAW_OPEN_NTCREATEX;
2143 1 : io.ntcreatex.in.flags = 0;
2144 1 : io.ntcreatex.in.root_fid.fnum = 0;
2145 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2146 1 : io.ntcreatex.in.alloc_size = 0;
2147 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2148 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2149 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2150 1 : io.ntcreatex.in.create_options = 0;
2151 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2152 1 : io.ntcreatex.in.security_flags = 0;
2153 1 : io.ntcreatex.in.fname = fname;
2154 :
2155 1 : status = smb_raw_open(cli->tree, tctx, &io);
2156 1 : CHECK_STATUS(status, NT_STATUS_OK);
2157 1 : fnum = io.ntcreatex.out.file.fnum;
2158 :
2159 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2160 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
2161 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2162 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2163 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
2164 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
2165 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2166 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2167 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
2168 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2169 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2170 :
2171 : /* extend the file size */
2172 1 : ZERO_STRUCT(sfi);
2173 1 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
2174 1 : sfi.generic.in.file.fnum = fnum;
2175 1 : sfi.end_of_file_info.in.size = 512;
2176 1 : status = smb_raw_setfileinfo(cli->tree, &sfi);
2177 1 : CHECK_STATUS(status, NT_STATUS_OK);
2178 :
2179 : /* close the file and re-open with to verify new size */
2180 1 : smbcli_close(cli->tree, fnum);
2181 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2182 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ;
2183 1 : status = smb_raw_open(cli->tree, tctx, &io);
2184 1 : CHECK_STATUS(status, NT_STATUS_OK);
2185 1 : fnum = io.ntcreatex.out.file.fnum;
2186 :
2187 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2188 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
2189 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2190 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2191 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
2192 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
2193 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2194 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2195 1 : CHECK_VAL(io.ntcreatex.out.size, 512);
2196 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2197 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2198 :
2199 : /* close and re-open the file with SUPERSEDE flag */
2200 1 : smbcli_close(cli->tree, fnum);
2201 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_SUPERSEDE;
2202 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ;
2203 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2204 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2205 1 : io.ntcreatex.in.create_options = 0;
2206 :
2207 1 : status = smb_raw_open(cli->tree, tctx, &io);
2208 1 : CHECK_STATUS(status, NT_STATUS_OK);
2209 1 : fnum = io.ntcreatex.out.file.fnum;
2210 :
2211 : /* The file size in the superseded create response should be 0 */
2212 1 : CHECK_VAL(io.ntcreatex.out.size, 0);
2213 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2214 1 : CHECK_VAL(io.ntcreatex.out.create_action, FILE_WAS_SUPERSEDED);
2215 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2216 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2217 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2218 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2219 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2220 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2221 2 : done:
2222 1 : smbcli_close(cli->tree, fnum);
2223 1 : smbcli_deltree(cli->tree, BASEDIR);
2224 :
2225 1 : return ret;
2226 : }
2227 :
2228 : /* basic testing of all RAW_OPEN_* calls
2229 : */
2230 964 : struct torture_suite *torture_raw_open(TALLOC_CTX *mem_ctx)
2231 : {
2232 964 : struct torture_suite *suite = torture_suite_create(mem_ctx, "open");
2233 :
2234 964 : torture_suite_add_1smb_test(suite, "brlocked", test_ntcreatex_brlocked);
2235 964 : torture_suite_add_1smb_test(suite, "open", test_open);
2236 964 : torture_suite_add_1smb_test(suite, "open-multi", test_raw_open_multi);
2237 964 : torture_suite_add_1smb_test(suite, "openx", test_openx);
2238 964 : torture_suite_add_1smb_test(suite, "ntcreatex", test_ntcreatex);
2239 964 : torture_suite_add_1smb_test(suite, "nttrans-create", test_nttrans_create);
2240 964 : torture_suite_add_1smb_test(suite, "t2open", test_t2open);
2241 964 : torture_suite_add_1smb_test(suite, "mknew", test_mknew);
2242 964 : torture_suite_add_1smb_test(suite, "create", test_create);
2243 964 : torture_suite_add_1smb_test(suite, "ctemp", test_ctemp);
2244 964 : torture_suite_add_1smb_test(suite, "chained-openx", test_chained);
2245 964 : torture_suite_add_1smb_test(suite, "chained-ntcreatex", test_chained_ntcreatex_readx);
2246 964 : torture_suite_add_1smb_test(suite, "no-leading-slash", test_no_leading_slash);
2247 964 : torture_suite_add_1smb_test(suite, "openx-over-dir", test_openx_over_dir);
2248 964 : torture_suite_add_1smb_test(suite, "open-for-delete", test_open_for_delete);
2249 964 : torture_suite_add_1smb_test(suite, "opendisp-dir", test_ntcreatex_opendisp_dir);
2250 964 : torture_suite_add_1smb_test(suite, "ntcreatedir", test_ntcreatexdir);
2251 964 : torture_suite_add_1smb_test(suite, "open-for-truncate", test_open_for_truncate);
2252 964 : torture_suite_add_1smb_test(suite, "ntcreatex_supersede", test_ntcreatex_supersede);
2253 :
2254 964 : return suite;
2255 : }
|