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 1 : 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 1 : 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.file_type, FILE_TYPE_DISK);
844 1 : smbcli_unlink(cli->tree, fname);
845 :
846 :
847 1 : done:
848 1 : smbcli_close(cli->tree, fnum);
849 1 : smbcli_deltree(cli->tree, BASEDIR);
850 :
851 1 : return ret;
852 : }
853 :
854 :
855 : /*
856 : test RAW_OPEN_NTTRANS_CREATE
857 : */
858 1 : static bool test_nttrans_create(struct torture_context *tctx, struct smbcli_state *cli)
859 : {
860 : union smb_open io;
861 : union smb_fileinfo finfo;
862 1 : const char *fname = BASEDIR "\\torture_ntcreatex.txt";
863 1 : const char *dname = BASEDIR "\\torture_ntcreatex.dir";
864 : NTSTATUS status;
865 1 : int fnum = -1;
866 1 : bool ret = true;
867 : int i;
868 : uint32_t ok_mask, not_supported_mask, invalid_parameter_mask;
869 : uint32_t not_a_directory_mask, unexpected_mask;
870 : struct {
871 : uint32_t open_disp;
872 : bool with_file;
873 : NTSTATUS correct_status;
874 1 : } open_funcs[] = {
875 : { NTCREATEX_DISP_SUPERSEDE, true, NT_STATUS_OK },
876 : { NTCREATEX_DISP_SUPERSEDE, false, NT_STATUS_OK },
877 : { NTCREATEX_DISP_OPEN, true, NT_STATUS_OK },
878 : { NTCREATEX_DISP_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
879 : { NTCREATEX_DISP_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
880 : { NTCREATEX_DISP_CREATE, false, NT_STATUS_OK },
881 : { NTCREATEX_DISP_OPEN_IF, true, NT_STATUS_OK },
882 : { NTCREATEX_DISP_OPEN_IF, false, NT_STATUS_OK },
883 : { NTCREATEX_DISP_OVERWRITE, true, NT_STATUS_OK },
884 : { NTCREATEX_DISP_OVERWRITE, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
885 : { NTCREATEX_DISP_OVERWRITE_IF, true, NT_STATUS_OK },
886 : { NTCREATEX_DISP_OVERWRITE_IF, false, NT_STATUS_OK },
887 : { 6, true, NT_STATUS_INVALID_PARAMETER },
888 : { 6, false, NT_STATUS_INVALID_PARAMETER },
889 : };
890 :
891 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
892 :
893 : /* reasonable default parameters */
894 1 : io.generic.level = RAW_OPEN_NTTRANS_CREATE;
895 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
896 1 : io.ntcreatex.in.root_fid.fnum = 0;
897 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
898 1 : io.ntcreatex.in.alloc_size = 1024*1024;
899 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
900 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
901 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
902 1 : io.ntcreatex.in.create_options = 0;
903 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
904 1 : io.ntcreatex.in.security_flags = 0;
905 1 : io.ntcreatex.in.fname = fname;
906 1 : io.ntcreatex.in.sec_desc = NULL;
907 1 : io.ntcreatex.in.ea_list = NULL;
908 :
909 : /* test the open disposition */
910 15 : for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
911 14 : if (open_funcs[i].with_file) {
912 7 : fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
913 7 : if (fnum == -1) {
914 0 : torture_result(tctx, TORTURE_FAIL,
915 : "Failed to create file %s - %s\n",
916 : fname, smbcli_errstr(cli->tree));
917 0 : ret = false;
918 0 : goto done;
919 : }
920 7 : smbcli_close(cli->tree, fnum);
921 : }
922 14 : io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
923 14 : status = smb_raw_open(cli->tree, tctx, &io);
924 14 : if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
925 0 : torture_result(tctx, TORTURE_FAIL,
926 : "(%s) incorrect status %s should be %s "
927 : "(i=%d with_file=%d open_disp=%d)\n",
928 : __location__, nt_errstr(status),
929 : nt_errstr(open_funcs[i].correct_status),
930 0 : i, (int)open_funcs[i].with_file,
931 0 : (int)open_funcs[i].open_disp);
932 0 : ret = false;
933 : }
934 14 : if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
935 11 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
936 11 : smbcli_unlink(cli->tree, fname);
937 : }
938 : }
939 :
940 : /* basic field testing */
941 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
942 :
943 1 : status = smb_raw_open(cli->tree, tctx, &io);
944 1 : CHECK_STATUS(status, NT_STATUS_OK);
945 1 : fnum = io.ntcreatex.out.file.fnum;
946 :
947 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
948 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
949 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
950 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
951 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
952 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
953 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
954 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
955 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
956 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
957 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
958 :
959 : /* check fields when the file already existed */
960 1 : smbcli_close(cli->tree, fnum);
961 1 : smbcli_unlink(cli->tree, fname);
962 1 : fnum = create_complex_file(cli, tctx, fname);
963 1 : if (fnum == -1) {
964 0 : ret = false;
965 0 : goto done;
966 : }
967 1 : smbcli_close(cli->tree, fnum);
968 :
969 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
970 1 : status = smb_raw_open(cli->tree, tctx, &io);
971 1 : CHECK_STATUS(status, NT_STATUS_OK);
972 1 : fnum = io.ntcreatex.out.file.fnum;
973 :
974 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
975 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
976 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
977 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
978 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
979 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
980 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
981 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
982 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
983 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
984 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
985 1 : smbcli_close(cli->tree, fnum);
986 :
987 : /* check no-recall - don't pull a file from tape on a HSM */
988 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NO_RECALL;
989 1 : status = smb_raw_open(cli->tree, tctx, &io);
990 1 : CHECK_STATUS(status, NT_STATUS_OK);
991 1 : fnum = io.ntcreatex.out.file.fnum;
992 :
993 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
994 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
995 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
996 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
997 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
998 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
999 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1000 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1001 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1002 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1003 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1004 1 : smbcli_close(cli->tree, fnum);
1005 :
1006 : /* Check some create options (these all should be ignored) */
1007 33 : for (i=0; i < 32; i++) {
1008 32 : uint32_t create_option =
1009 32 : ((uint32_t)1 << i) & NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
1010 32 : if (create_option == 0) {
1011 25 : continue;
1012 : }
1013 7 : io.ntcreatex.in.create_options = create_option;
1014 7 : status = smb_raw_open(cli->tree, tctx, &io);
1015 7 : if (!NT_STATUS_IS_OK(status)) {
1016 0 : torture_warning(tctx, "ntcreatex create option 0x%08x "
1017 : "gave %s - should give NT_STATUS_OK\n",
1018 : create_option, nt_errstr(status));
1019 : }
1020 7 : CHECK_STATUS(status, NT_STATUS_OK);
1021 7 : fnum = io.ntcreatex.out.file.fnum;
1022 :
1023 7 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1024 7 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
1025 7 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
1026 7 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
1027 7 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
1028 7 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
1029 7 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1030 7 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1031 7 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1032 7 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1033 7 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1034 7 : smbcli_close(cli->tree, fnum);
1035 : }
1036 :
1037 1 : io.ntcreatex.in.file_attr = 0;
1038 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1039 1 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1040 :
1041 : /* Check for options that should return NOT_SUPPORTED, OK or INVALID_PARAMETER */
1042 1 : ok_mask = 0;
1043 1 : not_supported_mask = 0;
1044 1 : invalid_parameter_mask = 0;
1045 1 : not_a_directory_mask = 0;
1046 1 : unexpected_mask = 0;
1047 33 : for (i=0; i < 32; i++) {
1048 32 : uint32_t create_option = (uint32_t)1<<i;
1049 32 : if (create_option & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
1050 1 : continue;
1051 : }
1052 31 : io.ntcreatex.in.create_options = create_option;
1053 31 : status = smb_raw_open(cli->tree, tctx, &io);
1054 31 : if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) {
1055 1 : not_supported_mask |= create_option;
1056 30 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1057 18 : ok_mask |= create_option;
1058 18 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1059 12 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
1060 11 : invalid_parameter_mask |= create_option;
1061 1 : } else if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1062 1 : not_a_directory_mask |= 1<<i;
1063 : } else {
1064 0 : unexpected_mask |= 1<<i;
1065 0 : torture_comment(tctx, "create option 0x%08x returned %s\n",
1066 : create_option, nt_errstr(status));
1067 : }
1068 : }
1069 :
1070 1 : CHECK_VAL(ok_mask, 0x00efcfce);
1071 1 : CHECK_VAL(not_a_directory_mask, 0x00000001);
1072 1 : CHECK_VAL(not_supported_mask, 0x00002000);
1073 1 : CHECK_VAL(invalid_parameter_mask, 0xff100030);
1074 1 : CHECK_VAL(unexpected_mask, 0x00000000);
1075 :
1076 1 : smbcli_unlink(cli->tree, fname);
1077 :
1078 :
1079 : /* create a directory */
1080 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1081 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1082 1 : io.ntcreatex.in.alloc_size = 0;
1083 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1084 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1085 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1086 1 : io.ntcreatex.in.create_options = 0;
1087 1 : io.ntcreatex.in.fname = dname;
1088 1 : fname = dname;
1089 :
1090 1 : smbcli_rmdir(cli->tree, fname);
1091 1 : smbcli_unlink(cli->tree, fname);
1092 :
1093 1 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1094 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1095 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1096 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1097 1 : status = smb_raw_open(cli->tree, tctx, &io);
1098 1 : CHECK_STATUS(status, NT_STATUS_OK);
1099 1 : fnum = io.ntcreatex.out.file.fnum;
1100 :
1101 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1102 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
1103 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
1104 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
1105 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
1106 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
1107 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1108 1 : CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
1109 : FILE_ATTRIBUTE_DIRECTORY);
1110 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
1111 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
1112 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
1113 1 : CHECK_VAL(io.ntcreatex.out.is_directory, 1);
1114 1 : CHECK_VAL(io.ntcreatex.out.size, 0);
1115 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
1116 1 : smbcli_unlink(cli->tree, fname);
1117 :
1118 :
1119 1 : done:
1120 1 : smbcli_close(cli->tree, fnum);
1121 1 : smbcli_deltree(cli->tree, BASEDIR);
1122 :
1123 1 : return ret;
1124 : }
1125 :
1126 : /*
1127 : test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
1128 :
1129 : I've got an application that does a similar sequence of ntcreate&x,
1130 : locking&x and another ntcreate&x with
1131 : open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
1132 : second open.
1133 : */
1134 1 : static bool test_ntcreatex_brlocked(struct torture_context *tctx, struct smbcli_state *cli)
1135 : {
1136 : union smb_open io, io1;
1137 : union smb_lock io2;
1138 : struct smb_lock_entry lock[1];
1139 1 : const char *fname = BASEDIR "\\torture_ntcreatex.txt";
1140 : NTSTATUS status;
1141 1 : bool ret = true;
1142 :
1143 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1144 :
1145 1 : torture_comment(tctx, "Testing ntcreatex with a byte range locked file\n");
1146 :
1147 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1148 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1149 1 : io.ntcreatex.in.root_fid.fnum = 0;
1150 1 : io.ntcreatex.in.access_mask = 0x2019f;
1151 1 : io.ntcreatex.in.alloc_size = 0;
1152 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1153 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1154 : NTCREATEX_SHARE_ACCESS_WRITE;
1155 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1156 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1157 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1158 1 : io.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1159 : NTCREATEX_SECURITY_ALL;
1160 1 : io.ntcreatex.in.fname = fname;
1161 :
1162 1 : status = smb_raw_open(cli->tree, tctx, &io);
1163 1 : CHECK_STATUS(status, NT_STATUS_OK);
1164 :
1165 1 : io2.lockx.level = RAW_LOCK_LOCKX;
1166 1 : io2.lockx.in.file.fnum = io.ntcreatex.out.file.fnum;
1167 1 : io2.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1168 1 : io2.lockx.in.timeout = 0;
1169 1 : io2.lockx.in.ulock_cnt = 0;
1170 1 : io2.lockx.in.lock_cnt = 1;
1171 1 : lock[0].pid = cli->session->pid;
1172 1 : lock[0].offset = 0;
1173 1 : lock[0].count = 0x1;
1174 1 : io2.lockx.in.locks = &lock[0];
1175 1 : status = smb_raw_lock(cli->tree, &io2);
1176 1 : CHECK_STATUS(status, NT_STATUS_OK);
1177 :
1178 1 : io1.generic.level = RAW_OPEN_NTCREATEX;
1179 1 : io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1180 1 : io1.ntcreatex.in.root_fid.fnum = 0;
1181 1 : io1.ntcreatex.in.access_mask = 0x20196;
1182 1 : io1.ntcreatex.in.alloc_size = 0;
1183 1 : io1.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1184 1 : io1.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1185 : NTCREATEX_SHARE_ACCESS_WRITE;
1186 1 : io1.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1187 1 : io1.ntcreatex.in.create_options = 0;
1188 1 : io1.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1189 1 : io1.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1190 : NTCREATEX_SECURITY_ALL;
1191 1 : io1.ntcreatex.in.fname = fname;
1192 :
1193 1 : status = smb_raw_open(cli->tree, tctx, &io1);
1194 1 : CHECK_STATUS(status, NT_STATUS_OK);
1195 :
1196 1 : done:
1197 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1198 1 : smbcli_close(cli->tree, io1.ntcreatex.out.file.fnum);
1199 1 : smbcli_deltree(cli->tree, BASEDIR);
1200 1 : return ret;
1201 : }
1202 :
1203 : /*
1204 : test RAW_OPEN_MKNEW
1205 : */
1206 1 : static bool test_mknew(struct torture_context *tctx, struct smbcli_state *cli)
1207 : {
1208 : union smb_open io;
1209 1 : const char *fname = BASEDIR "\\torture_mknew.txt";
1210 : NTSTATUS status;
1211 1 : int fnum = -1;
1212 1 : bool ret = true;
1213 1 : time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1214 : union smb_fileinfo finfo;
1215 :
1216 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1217 :
1218 1 : io.mknew.level = RAW_OPEN_MKNEW;
1219 1 : io.mknew.in.attrib = 0;
1220 1 : io.mknew.in.write_time = 0;
1221 1 : io.mknew.in.fname = fname;
1222 1 : status = smb_raw_open(cli->tree, tctx, &io);
1223 1 : CHECK_STATUS(status, NT_STATUS_OK);
1224 1 : fnum = io.mknew.out.file.fnum;
1225 :
1226 1 : status = smb_raw_open(cli->tree, tctx, &io);
1227 1 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
1228 :
1229 1 : smbcli_close(cli->tree, fnum);
1230 1 : smbcli_unlink(cli->tree, fname);
1231 :
1232 : /* make sure write_time works */
1233 1 : io.mknew.in.write_time = basetime;
1234 1 : status = smb_raw_open(cli->tree, tctx, &io);
1235 1 : CHECK_STATUS(status, NT_STATUS_OK);
1236 1 : fnum = io.mknew.out.file.fnum;
1237 1 : CHECK_TIME(basetime, write_time);
1238 :
1239 1 : smbcli_close(cli->tree, fnum);
1240 1 : smbcli_unlink(cli->tree, fname);
1241 :
1242 : /* make sure file_attrs works */
1243 1 : io.mknew.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1244 1 : status = smb_raw_open(cli->tree, tctx, &io);
1245 1 : CHECK_STATUS(status, NT_STATUS_OK);
1246 1 : fnum = io.mknew.out.file.fnum;
1247 1 : CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE,
1248 : attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1249 :
1250 1 : done:
1251 1 : smbcli_close(cli->tree, fnum);
1252 1 : smbcli_deltree(cli->tree, BASEDIR);
1253 :
1254 1 : return ret;
1255 : }
1256 :
1257 :
1258 : /*
1259 : test RAW_OPEN_CREATE
1260 : */
1261 1 : static bool test_create(struct torture_context *tctx, struct smbcli_state *cli)
1262 : {
1263 : union smb_open io;
1264 1 : const char *fname = BASEDIR "\\torture_create.txt";
1265 : NTSTATUS status;
1266 1 : int fnum = -1;
1267 1 : bool ret = true;
1268 1 : time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1269 : union smb_fileinfo finfo;
1270 :
1271 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1272 :
1273 1 : io.create.level = RAW_OPEN_CREATE;
1274 1 : io.create.in.attrib = 0;
1275 1 : io.create.in.write_time = 0;
1276 1 : io.create.in.fname = fname;
1277 1 : status = smb_raw_open(cli->tree, tctx, &io);
1278 1 : CHECK_STATUS(status, NT_STATUS_OK);
1279 1 : fnum = io.create.out.file.fnum;
1280 :
1281 1 : status = smb_raw_open(cli->tree, tctx, &io);
1282 1 : CHECK_STATUS(status, NT_STATUS_OK);
1283 :
1284 1 : smbcli_close(cli->tree, io.create.out.file.fnum);
1285 1 : smbcli_close(cli->tree, fnum);
1286 1 : smbcli_unlink(cli->tree, fname);
1287 :
1288 : /* make sure write_time works */
1289 1 : io.create.in.write_time = basetime;
1290 1 : status = smb_raw_open(cli->tree, tctx, &io);
1291 1 : CHECK_STATUS(status, NT_STATUS_OK);
1292 1 : fnum = io.create.out.file.fnum;
1293 1 : CHECK_TIME(basetime, write_time);
1294 :
1295 1 : smbcli_close(cli->tree, fnum);
1296 1 : smbcli_unlink(cli->tree, fname);
1297 :
1298 : /* make sure file_attrs works */
1299 1 : io.create.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1300 1 : status = smb_raw_open(cli->tree, tctx, &io);
1301 1 : CHECK_STATUS(status, NT_STATUS_OK);
1302 1 : fnum = io.create.out.file.fnum;
1303 1 : CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE,
1304 : attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1305 :
1306 1 : done:
1307 1 : smbcli_close(cli->tree, fnum);
1308 1 : smbcli_deltree(cli->tree, BASEDIR);
1309 :
1310 1 : return ret;
1311 : }
1312 :
1313 :
1314 : /*
1315 : test RAW_OPEN_CTEMP
1316 : */
1317 1 : static bool test_ctemp(struct torture_context *tctx, struct smbcli_state *cli)
1318 : {
1319 : union smb_open io;
1320 : NTSTATUS status;
1321 1 : int fnum = -1;
1322 1 : bool ret = true;
1323 1 : time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1324 : union smb_fileinfo finfo;
1325 1 : const char *name, *fname = NULL;
1326 :
1327 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1328 :
1329 1 : io.ctemp.level = RAW_OPEN_CTEMP;
1330 1 : io.ctemp.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1331 1 : io.ctemp.in.write_time = basetime;
1332 1 : io.ctemp.in.directory = BASEDIR;
1333 1 : status = smb_raw_open(cli->tree, tctx, &io);
1334 1 : CHECK_STATUS(status, NT_STATUS_OK);
1335 1 : fnum = io.ctemp.out.file.fnum;
1336 :
1337 1 : name = io.ctemp.out.name;
1338 :
1339 1 : finfo.generic.level = RAW_FILEINFO_NAME_INFO;
1340 1 : finfo.generic.in.file.fnum = fnum;
1341 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
1342 1 : CHECK_STATUS(status, NT_STATUS_OK);
1343 :
1344 1 : fname = finfo.name_info.out.fname.s;
1345 1 : torture_comment(tctx, "ctemp name=%s real name=%s\n", name, fname);
1346 :
1347 1 : done:
1348 1 : smbcli_close(cli->tree, fnum);
1349 1 : smbcli_deltree(cli->tree, BASEDIR);
1350 :
1351 1 : return ret;
1352 : }
1353 :
1354 :
1355 : /*
1356 : test chained RAW_OPEN_OPENX_READX
1357 : */
1358 1 : static bool test_chained(struct torture_context *tctx, struct smbcli_state *cli)
1359 : {
1360 : union smb_open io;
1361 1 : const char *fname = BASEDIR "\\torture_chained.txt";
1362 : NTSTATUS status;
1363 1 : int fnum = -1;
1364 1 : bool ret = true;
1365 1 : const char buf[] = "test";
1366 : char buf2[4];
1367 :
1368 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1369 :
1370 1 : fnum = create_complex_file(cli, tctx, fname);
1371 :
1372 1 : smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1373 :
1374 1 : smbcli_close(cli->tree, fnum);
1375 :
1376 1 : io.openxreadx.level = RAW_OPEN_OPENX_READX;
1377 1 : io.openxreadx.in.fname = fname;
1378 1 : io.openxreadx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1379 1 : io.openxreadx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1380 1 : io.openxreadx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1381 1 : io.openxreadx.in.search_attrs = 0;
1382 1 : io.openxreadx.in.file_attrs = 0;
1383 1 : io.openxreadx.in.write_time = 0;
1384 1 : io.openxreadx.in.size = 1024*1024;
1385 1 : io.openxreadx.in.timeout = 0;
1386 :
1387 1 : io.openxreadx.in.offset = 0;
1388 1 : io.openxreadx.in.mincnt = sizeof(buf2);
1389 1 : io.openxreadx.in.maxcnt = sizeof(buf2);
1390 1 : io.openxreadx.in.remaining = 0;
1391 1 : io.openxreadx.out.data = (uint8_t *)buf2;
1392 :
1393 1 : status = smb_raw_open(cli->tree, tctx, &io);
1394 1 : CHECK_STATUS(status, NT_STATUS_OK);
1395 1 : fnum = io.openxreadx.out.file.fnum;
1396 :
1397 1 : if (memcmp(buf, buf2, MIN(sizeof(buf), sizeof(buf2))) != 0) {
1398 0 : torture_result(tctx, TORTURE_FAIL,
1399 : "wrong data in reply buffer\n");
1400 0 : ret = false;
1401 : }
1402 :
1403 1 : done:
1404 1 : smbcli_close(cli->tree, fnum);
1405 1 : smbcli_deltree(cli->tree, BASEDIR);
1406 :
1407 1 : return ret;
1408 : }
1409 :
1410 : /*
1411 : test RAW_OPEN_OPENX without a leading slash on the path.
1412 : NetApp filers are known to fail on this.
1413 :
1414 : */
1415 1 : static bool test_no_leading_slash(struct torture_context *tctx, struct smbcli_state *cli)
1416 : {
1417 : union smb_open io;
1418 1 : const char *fname = BASEDIR "\\torture_no_leading_slash.txt";
1419 : NTSTATUS status;
1420 1 : int fnum = -1;
1421 1 : bool ret = true;
1422 1 : const char buf[] = "test";
1423 :
1424 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1425 :
1426 1 : smbcli_unlink(cli->tree, fname);
1427 :
1428 : /* Create the file */
1429 1 : fnum = create_complex_file(cli, tctx, fname);
1430 1 : smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1431 1 : smbcli_close(cli->tree, fnum);
1432 :
1433 : /* Prepare to open the file using path without leading slash */
1434 1 : io.openx.level = RAW_OPEN_OPENX;
1435 1 : io.openx.in.fname = fname + 1;
1436 1 : io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1437 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1438 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1439 1 : io.openx.in.search_attrs = 0;
1440 1 : io.openx.in.file_attrs = 0;
1441 1 : io.openx.in.write_time = 0;
1442 1 : io.openx.in.size = 1024*1024;
1443 1 : io.openx.in.timeout = 0;
1444 :
1445 1 : status = smb_raw_open(cli->tree, tctx, &io);
1446 1 : CHECK_STATUS(status, NT_STATUS_OK);
1447 1 : fnum = io.openx.out.file.fnum;
1448 :
1449 1 : done:
1450 1 : smbcli_close(cli->tree, fnum);
1451 1 : smbcli_deltree(cli->tree, BASEDIR);
1452 :
1453 1 : return ret;
1454 : }
1455 :
1456 : /*
1457 : test RAW_OPEN_OPENX against an existing directory to
1458 : ensure it returns NT_STATUS_FILE_IS_A_DIRECTORY.
1459 : Samba 3.2.0 - 3.2.6 are known to fail this.
1460 :
1461 : */
1462 1 : static bool test_openx_over_dir(struct torture_context *tctx, struct smbcli_state *cli)
1463 : {
1464 : union smb_open io;
1465 1 : const char *fname = BASEDIR "\\openx_over_dir";
1466 : NTSTATUS status;
1467 1 : int d_fnum = -1;
1468 1 : int fnum = -1;
1469 1 : bool ret = true;
1470 :
1471 1 : ZERO_STRUCT(io);
1472 :
1473 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1474 :
1475 : /* Create the Directory */
1476 1 : status = create_directory_handle(cli->tree, fname, &d_fnum);
1477 1 : smbcli_close(cli->tree, d_fnum);
1478 :
1479 : /* Prepare to open the file over the directory. */
1480 1 : io.openx.level = RAW_OPEN_OPENX;
1481 1 : io.openx.in.fname = fname;
1482 1 : io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1483 1 : io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1484 1 : io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1485 1 : io.openx.in.search_attrs = 0;
1486 1 : io.openx.in.file_attrs = 0;
1487 1 : io.openx.in.write_time = 0;
1488 1 : io.openx.in.size = 1024*1024;
1489 1 : io.openx.in.timeout = 0;
1490 :
1491 1 : status = smb_raw_open(cli->tree, tctx, &io);
1492 1 : CHECK_STATUS(status, NT_STATUS_FILE_IS_A_DIRECTORY);
1493 1 : fnum = io.openx.out.file.fnum;
1494 :
1495 1 : done:
1496 1 : smbcli_close(cli->tree, fnum);
1497 1 : smbcli_deltree(cli->tree, BASEDIR);
1498 :
1499 1 : return ret;
1500 : }
1501 :
1502 :
1503 : /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
1504 :
1505 1 : static bool test_raw_open_multi(struct torture_context *tctx, struct smbcli_state *cli_ignored)
1506 : {
1507 : struct smbcli_state *cli;
1508 1 : TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
1509 1 : const char *fname = "\\test_oplock.dat";
1510 : NTSTATUS status;
1511 1 : bool ret = true;
1512 : union smb_open io;
1513 : struct smbcli_state **clients;
1514 : struct smbcli_request **requests;
1515 : union smb_open *ios;
1516 1 : const char *host = torture_setting_string(tctx, "host", NULL);
1517 1 : const char *share = torture_setting_string(tctx, "share", NULL);
1518 1 : int i, num_files = 3;
1519 1 : int num_ok = 0;
1520 1 : int num_collision = 0;
1521 :
1522 1 : clients = talloc_array(mem_ctx, struct smbcli_state *, num_files);
1523 1 : requests = talloc_array(mem_ctx, struct smbcli_request *, num_files);
1524 1 : ios = talloc_array(mem_ctx, union smb_open, num_files);
1525 1 : if ((tctx->ev == NULL) || (clients == NULL) || (requests == NULL) ||
1526 : (ios == NULL)) {
1527 0 : torture_result(tctx, TORTURE_FAIL, "(%s): talloc failed\n",
1528 : __location__);
1529 0 : return false;
1530 : }
1531 :
1532 1 : if (!torture_open_connection_share(mem_ctx, &cli, tctx, host, share, tctx->ev)) {
1533 0 : return false;
1534 : }
1535 :
1536 1 : cli->tree->session->transport->options.request_timeout = 60;
1537 :
1538 4 : for (i=0; i<num_files; i++) {
1539 3 : if (!torture_open_connection_share(mem_ctx, &(clients[i]),
1540 : tctx, host, share, tctx->ev)) {
1541 0 : torture_result(tctx, TORTURE_FAIL,
1542 : "(%s): Could not open %d'th connection\n",
1543 : __location__, i);
1544 0 : return false;
1545 : }
1546 3 : clients[i]->tree->session->transport->options.request_timeout = 60;
1547 : }
1548 :
1549 : /* cleanup */
1550 1 : smbcli_unlink(cli->tree, fname);
1551 :
1552 : /*
1553 : base ntcreatex parms
1554 : */
1555 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1556 1 : io.ntcreatex.in.root_fid.fnum = 0;
1557 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1558 1 : io.ntcreatex.in.alloc_size = 0;
1559 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1560 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1561 : NTCREATEX_SHARE_ACCESS_WRITE|
1562 : NTCREATEX_SHARE_ACCESS_DELETE;
1563 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1564 1 : io.ntcreatex.in.create_options = 0;
1565 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1566 1 : io.ntcreatex.in.security_flags = 0;
1567 1 : io.ntcreatex.in.fname = fname;
1568 1 : io.ntcreatex.in.flags = 0;
1569 :
1570 4 : for (i=0; i<num_files; i++) {
1571 3 : ios[i] = io;
1572 3 : requests[i] = smb_raw_open_send(clients[i]->tree, &ios[i]);
1573 3 : if (requests[i] == NULL) {
1574 0 : torture_result(tctx, TORTURE_FAIL,
1575 : "(%s): could not send %d'th request\n",
1576 : __location__, i);
1577 0 : return false;
1578 : }
1579 : }
1580 :
1581 1 : torture_comment(tctx, "waiting for replies\n");
1582 9 : while (1) {
1583 10 : bool unreplied = false;
1584 18 : for (i=0; i<num_files; i++) {
1585 17 : if (requests[i] == NULL) {
1586 5 : continue;
1587 : }
1588 12 : if (requests[i]->state < SMBCLI_REQUEST_DONE) {
1589 9 : unreplied = true;
1590 9 : break;
1591 : }
1592 3 : status = smb_raw_open_recv(requests[i], mem_ctx,
1593 3 : &ios[i]);
1594 :
1595 3 : torture_comment(tctx, "File %d returned status %s\n", i,
1596 : nt_errstr(status));
1597 :
1598 3 : if (NT_STATUS_IS_OK(status)) {
1599 1 : num_ok += 1;
1600 : }
1601 :
1602 3 : if (NT_STATUS_EQUAL(status,
1603 : NT_STATUS_OBJECT_NAME_COLLISION)) {
1604 2 : num_collision += 1;
1605 : }
1606 :
1607 3 : requests[i] = NULL;
1608 : }
1609 10 : if (!unreplied) {
1610 1 : break;
1611 : }
1612 :
1613 9 : if (tevent_loop_once(tctx->ev) != 0) {
1614 0 : torture_result(tctx, TORTURE_FAIL,
1615 : "(%s): tevent_loop_once failed\n", __location__);
1616 0 : return false;
1617 : }
1618 : }
1619 :
1620 1 : if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1621 0 : ret = false;
1622 : }
1623 :
1624 4 : for (i=0; i<num_files; i++) {
1625 3 : torture_close_connection(clients[i]);
1626 : }
1627 1 : talloc_free(mem_ctx);
1628 1 : return ret;
1629 : }
1630 :
1631 : /*
1632 : test opening for delete on a read-only attribute file.
1633 : */
1634 1 : static bool test_open_for_delete(struct torture_context *tctx, struct smbcli_state *cli)
1635 : {
1636 : union smb_open io;
1637 : union smb_fileinfo finfo;
1638 1 : const char *fname = BASEDIR "\\torture_open_for_delete.txt";
1639 : NTSTATUS status;
1640 1 : int fnum = -1;
1641 1 : bool ret = true;
1642 :
1643 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1644 :
1645 : /* reasonable default parameters */
1646 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1647 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1648 1 : io.ntcreatex.in.root_fid.fnum = 0;
1649 1 : io.ntcreatex.in.alloc_size = 0;
1650 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1651 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_READONLY;
1652 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1653 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1654 1 : io.ntcreatex.in.create_options = 0;
1655 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1656 1 : io.ntcreatex.in.security_flags = 0;
1657 1 : io.ntcreatex.in.fname = fname;
1658 :
1659 : /* Create the readonly file. */
1660 :
1661 1 : status = smb_raw_open(cli->tree, tctx, &io);
1662 1 : CHECK_STATUS(status, NT_STATUS_OK);
1663 1 : fnum = io.ntcreatex.out.file.fnum;
1664 :
1665 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
1666 1 : io.ntcreatex.in.create_options = 0;
1667 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
1668 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
1669 1 : smbcli_close(cli->tree, fnum);
1670 :
1671 : /* Now try and open for delete only - should succeed. */
1672 1 : io.ntcreatex.in.access_mask = SEC_STD_DELETE;
1673 1 : io.ntcreatex.in.file_attr = 0;
1674 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
1675 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1676 1 : status = smb_raw_open(cli->tree, tctx, &io);
1677 1 : CHECK_STATUS(status, NT_STATUS_OK);
1678 :
1679 1 : smbcli_unlink(cli->tree, fname);
1680 :
1681 1 : done:
1682 1 : smbcli_close(cli->tree, fnum);
1683 1 : smbcli_deltree(cli->tree, BASEDIR);
1684 :
1685 1 : return ret;
1686 : }
1687 :
1688 : /*
1689 : test chained RAW_OPEN_NTCREATEX_READX
1690 : Send chained NTCREATEX_READX on a file that doesn't exist, then create
1691 : the file and try again.
1692 : */
1693 1 : static bool test_chained_ntcreatex_readx(struct torture_context *tctx, struct smbcli_state *cli)
1694 : {
1695 1 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
1696 : union smb_open io;
1697 1 : const char *fname = BASEDIR "\\torture_chained.txt";
1698 : NTSTATUS status;
1699 1 : int fnum = -1;
1700 1 : bool ret = true;
1701 1 : const char buf[] = "test";
1702 : char buf2[4];
1703 :
1704 1 : ZERO_STRUCT(io);
1705 :
1706 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1707 :
1708 1 : torture_comment(tctx, "Checking RAW_NTCREATEX_READX chained on "
1709 : "non-existent file \n");
1710 :
1711 : /* ntcreatex parameters */
1712 1 : io.generic.level = RAW_OPEN_NTCREATEX_READX;
1713 1 : io.ntcreatexreadx.in.flags = 0;
1714 1 : io.ntcreatexreadx.in.root_fid.fnum = 0;
1715 1 : io.ntcreatexreadx.in.access_mask = SEC_FILE_READ_DATA;
1716 1 : io.ntcreatexreadx.in.alloc_size = 0;
1717 1 : io.ntcreatexreadx.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1718 1 : io.ntcreatexreadx.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1719 : NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE;
1720 1 : io.ntcreatexreadx.in.open_disposition = NTCREATEX_DISP_OPEN;
1721 1 : io.ntcreatexreadx.in.create_options = 0;
1722 1 : io.ntcreatexreadx.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1723 1 : io.ntcreatexreadx.in.security_flags = 0;
1724 1 : io.ntcreatexreadx.in.fname = fname;
1725 :
1726 : /* readx parameters */
1727 1 : io.ntcreatexreadx.in.offset = 0;
1728 1 : io.ntcreatexreadx.in.mincnt = sizeof(buf2);
1729 1 : io.ntcreatexreadx.in.maxcnt = sizeof(buf2);
1730 1 : io.ntcreatexreadx.in.remaining = 0;
1731 1 : io.ntcreatexreadx.out.data = (uint8_t *)buf2;
1732 :
1733 : /* try to open the non-existent file */
1734 1 : status = smb_raw_open(cli->tree, mem_ctx, &io);
1735 1 : CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
1736 1 : fnum = io.ntcreatexreadx.out.file.fnum;
1737 :
1738 1 : smbcli_close(cli->tree, fnum);
1739 1 : smbcli_unlink(cli->tree, fname);
1740 :
1741 1 : torture_comment(tctx, "Checking RAW_NTCREATEX_READX chained on "
1742 : "existing file \n");
1743 :
1744 1 : fnum = create_complex_file(cli, mem_ctx, fname);
1745 1 : smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1746 1 : smbcli_close(cli->tree, fnum);
1747 :
1748 1 : status = smb_raw_open(cli->tree, mem_ctx, &io);
1749 1 : CHECK_STATUS(status, NT_STATUS_OK);
1750 1 : fnum = io.ntcreatexreadx.out.file.fnum;
1751 :
1752 1 : if (memcmp(buf, buf2, MIN(sizeof(buf), sizeof(buf2))) != 0) {
1753 0 : torture_result(tctx, TORTURE_FAIL,
1754 : "(%s): wrong data in reply buffer\n", __location__);
1755 0 : ret = false;
1756 : }
1757 :
1758 1 : done:
1759 1 : smbcli_close(cli->tree, fnum);
1760 1 : smbcli_deltree(cli->tree, BASEDIR);
1761 1 : talloc_free(mem_ctx);
1762 :
1763 1 : return ret;
1764 : }
1765 :
1766 1 : static bool test_ntcreatex_opendisp_dir(struct torture_context *tctx,
1767 : struct smbcli_state *cli)
1768 : {
1769 1 : const char *dname = BASEDIR "\\torture_ntcreatex_opendisp_dir";
1770 : NTSTATUS status;
1771 1 : bool ret = true;
1772 : int i;
1773 : struct {
1774 : uint32_t open_disp;
1775 : bool dir_exists;
1776 : NTSTATUS correct_status;
1777 1 : } open_funcs_dir[] = {
1778 : { NTCREATEX_DISP_SUPERSEDE, true, NT_STATUS_INVALID_PARAMETER },
1779 : { NTCREATEX_DISP_SUPERSEDE, false, NT_STATUS_INVALID_PARAMETER },
1780 : { NTCREATEX_DISP_OPEN, true, NT_STATUS_OK },
1781 : { NTCREATEX_DISP_OPEN, false, NT_STATUS_OBJECT_NAME_NOT_FOUND },
1782 : { NTCREATEX_DISP_CREATE, true, NT_STATUS_OBJECT_NAME_COLLISION },
1783 : { NTCREATEX_DISP_CREATE, false, NT_STATUS_OK },
1784 : { NTCREATEX_DISP_OPEN_IF, true, NT_STATUS_OK },
1785 : { NTCREATEX_DISP_OPEN_IF, false, NT_STATUS_OK },
1786 : { NTCREATEX_DISP_OVERWRITE, true, NT_STATUS_INVALID_PARAMETER },
1787 : { NTCREATEX_DISP_OVERWRITE, false, NT_STATUS_INVALID_PARAMETER },
1788 : { NTCREATEX_DISP_OVERWRITE_IF, true, NT_STATUS_INVALID_PARAMETER },
1789 : { NTCREATEX_DISP_OVERWRITE_IF, false, NT_STATUS_INVALID_PARAMETER },
1790 : { 6, true, NT_STATUS_INVALID_PARAMETER },
1791 : { 6, false, NT_STATUS_INVALID_PARAMETER },
1792 : };
1793 : union smb_open io;
1794 :
1795 1 : ZERO_STRUCT(io);
1796 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1797 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1798 1 : io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1799 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1800 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
1801 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1802 1 : io.ntcreatex.in.fname = dname;
1803 :
1804 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1805 :
1806 1 : smbcli_rmdir(cli->tree, dname);
1807 1 : smbcli_unlink(cli->tree, dname);
1808 :
1809 : /* test the open disposition for directories */
1810 1 : torture_comment(tctx, "Testing open dispositions for directories...\n");
1811 :
1812 15 : for (i=0; i<ARRAY_SIZE(open_funcs_dir); i++) {
1813 14 : if (open_funcs_dir[i].dir_exists) {
1814 7 : status = smbcli_mkdir(cli->tree, dname);
1815 7 : if (!NT_STATUS_IS_OK(status)) {
1816 0 : torture_result(tctx, TORTURE_FAIL,
1817 : "(%s): Failed to make directory "
1818 : "%s - %s\n", __location__, dname,
1819 : smbcli_errstr(cli->tree));
1820 0 : ret = false;
1821 0 : goto done;
1822 : }
1823 : }
1824 :
1825 14 : io.ntcreatex.in.open_disposition = open_funcs_dir[i].open_disp;
1826 14 : status = smb_raw_open(cli->tree, tctx, &io);
1827 14 : if (!NT_STATUS_EQUAL(status, open_funcs_dir[i].correct_status)) {
1828 0 : torture_result(tctx, TORTURE_FAIL,
1829 : "(%s) incorrect status %s should be %s "
1830 : "(i=%d dir_exists=%d open_disp=%d)\n",
1831 : __location__, nt_errstr(status),
1832 : nt_errstr(open_funcs_dir[i].correct_status),
1833 0 : i, (int)open_funcs_dir[i].dir_exists,
1834 0 : (int)open_funcs_dir[i].open_disp);
1835 0 : ret = false;
1836 : }
1837 14 : if (NT_STATUS_IS_OK(status) || open_funcs_dir[i].dir_exists) {
1838 9 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1839 9 : smbcli_rmdir(cli->tree, dname);
1840 : }
1841 : }
1842 :
1843 1 : done:
1844 1 : smbcli_deltree(cli->tree, BASEDIR);
1845 :
1846 1 : return ret;
1847 : }
1848 :
1849 : /**
1850 : * Test what happens when trying to open a file with directory parameters and
1851 : * vice-versa. Also test that NTCREATEX_OPTIONS_DIRECTORY is treated as
1852 : * mandatory and FILE_ATTRIBUTE_DIRECTORY is advisory for directory
1853 : * creation/opening.
1854 : */
1855 1 : static bool test_ntcreatexdir(struct torture_context *tctx,
1856 : struct smbcli_state *cli)
1857 : {
1858 : union smb_open io;
1859 1 : const char *fname = BASEDIR "\\torture_ntcreatex.txt";
1860 1 : const char *dname = BASEDIR "\\torture_ntcreatex_dir";
1861 : NTSTATUS status;
1862 : int i;
1863 :
1864 : struct {
1865 : uint32_t open_disp;
1866 : uint32_t file_attr;
1867 : uint32_t create_options;
1868 : NTSTATUS correct_status;
1869 1 : } open_funcs[] = {
1870 : { NTCREATEX_DISP_SUPERSEDE, 0, NTCREATEX_OPTIONS_DIRECTORY,
1871 : NT_STATUS_INVALID_PARAMETER },
1872 : { NTCREATEX_DISP_OPEN, 0, NTCREATEX_OPTIONS_DIRECTORY,
1873 : NT_STATUS_OBJECT_NAME_NOT_FOUND },
1874 : { NTCREATEX_DISP_CREATE, 0, NTCREATEX_OPTIONS_DIRECTORY,
1875 : NT_STATUS_OK },
1876 : { NTCREATEX_DISP_OPEN_IF, 0, NTCREATEX_OPTIONS_DIRECTORY,
1877 : NT_STATUS_OK },
1878 : { NTCREATEX_DISP_OVERWRITE, 0, NTCREATEX_OPTIONS_DIRECTORY,
1879 : NT_STATUS_INVALID_PARAMETER },
1880 : { NTCREATEX_DISP_OVERWRITE_IF, 0, NTCREATEX_OPTIONS_DIRECTORY,
1881 : NT_STATUS_INVALID_PARAMETER },
1882 : { NTCREATEX_DISP_SUPERSEDE, FILE_ATTRIBUTE_DIRECTORY, 0,
1883 : NT_STATUS_OK },
1884 : { NTCREATEX_DISP_OPEN, FILE_ATTRIBUTE_DIRECTORY, 0,
1885 : NT_STATUS_OBJECT_NAME_NOT_FOUND },
1886 : { NTCREATEX_DISP_CREATE, FILE_ATTRIBUTE_DIRECTORY, 0,
1887 : NT_STATUS_OK },
1888 : { NTCREATEX_DISP_OPEN_IF, FILE_ATTRIBUTE_DIRECTORY, 0,
1889 : NT_STATUS_OK },
1890 : { NTCREATEX_DISP_OVERWRITE, FILE_ATTRIBUTE_DIRECTORY, 0,
1891 : NT_STATUS_OBJECT_NAME_NOT_FOUND },
1892 : { NTCREATEX_DISP_OVERWRITE_IF, FILE_ATTRIBUTE_DIRECTORY, 0,
1893 : NT_STATUS_OK },
1894 :
1895 : };
1896 :
1897 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
1898 :
1899 : /* setup some base params. */
1900 1 : io.generic.level = RAW_OPEN_NTCREATEX;
1901 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1902 1 : io.ntcreatex.in.root_fid.fnum = 0;
1903 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1904 1 : io.ntcreatex.in.alloc_size = 0;
1905 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1906 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1907 1 : io.ntcreatex.in.security_flags = 0;
1908 1 : io.ntcreatex.in.fname = fname;
1909 :
1910 : /*
1911 : * Test the validity checking for create dispositions, which is done
1912 : * against the requested parameters rather than what's actually on
1913 : * disk.
1914 : */
1915 13 : for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
1916 12 : io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
1917 12 : io.ntcreatex.in.file_attr = open_funcs[i].file_attr;
1918 12 : io.ntcreatex.in.create_options = open_funcs[i].create_options;
1919 12 : status = smb_raw_open(cli->tree, tctx, &io);
1920 12 : if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
1921 0 : torture_result(tctx, TORTURE_FAIL,
1922 : "(%s) incorrect status %s should be %s "
1923 : "(i=%d open_disp=%d)\n",
1924 : __location__, nt_errstr(status),
1925 : nt_errstr(open_funcs[i].correct_status),
1926 0 : i, (int)open_funcs[i].open_disp);
1927 0 : return false;
1928 : }
1929 : /* Close and delete the file. */
1930 12 : if (NT_STATUS_IS_OK(status)) {
1931 6 : if (open_funcs[i].create_options != 0) {
1932 : /* out attrib should be a directory. */
1933 2 : torture_assert_int_equal(tctx,
1934 : io.ntcreatex.out.attrib,
1935 : FILE_ATTRIBUTE_DIRECTORY, "should have "
1936 : "created a directory");
1937 :
1938 2 : smbcli_close(cli->tree,
1939 2 : io.ntcreatex.out.file.fnum);
1940 :
1941 : /* Make sure unlink fails. */
1942 2 : status = smbcli_unlink(cli->tree, fname);
1943 2 : torture_assert_ntstatus_equal(tctx, status,
1944 : NT_STATUS_FILE_IS_A_DIRECTORY,
1945 : "unlink should fail for a directory");
1946 :
1947 2 : status = smbcli_rmdir(cli->tree, fname);
1948 2 : torture_assert_ntstatus_ok(tctx, status,
1949 : "rmdir failed");
1950 : } else {
1951 4 : torture_assert_int_equal(tctx,
1952 : io.ntcreatex.out.attrib,
1953 : FILE_ATTRIBUTE_ARCHIVE, "should not have "
1954 : "created a directory");
1955 :
1956 4 : smbcli_close(cli->tree,
1957 4 : io.ntcreatex.out.file.fnum);
1958 :
1959 : /* Make sure rmdir fails. */
1960 4 : status = smbcli_rmdir(cli->tree, fname);
1961 4 : torture_assert_ntstatus_equal(tctx, status,
1962 : NT_STATUS_NOT_A_DIRECTORY,
1963 : "rmdir should fail for a file");
1964 :
1965 4 : status = smbcli_unlink(cli->tree, fname);
1966 4 : torture_assert_ntstatus_ok(tctx, status,
1967 : "unlink failed");
1968 : }
1969 : }
1970 : }
1971 :
1972 : /* Create a file. */
1973 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1974 1 : io.ntcreatex.in.create_options = 0;
1975 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1976 1 : status = smb_raw_open(cli->tree, tctx, &io);
1977 1 : torture_assert_ntstatus_ok(tctx, status, "Failed to create file.");
1978 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1979 :
1980 : /* Try and open the file with file_attr_dir and check the error. */
1981 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1982 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1983 :
1984 1 : status = smb_raw_open(cli->tree, tctx, &io);
1985 1 : torture_assert_ntstatus_ok(tctx, status, "FILE_ATTRIBUTE_DIRECTORY "
1986 : "doesn't produce a hard failure.");
1987 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1988 :
1989 : /* Try and open file with createx_option_dir and check the error. */
1990 1 : io.ntcreatex.in.file_attr = 0;
1991 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1992 :
1993 1 : status = smb_raw_open(cli->tree, tctx, &io);
1994 1 : torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_A_DIRECTORY,
1995 : "NTCREATEX_OPTIONS_DIRECTORY will a file from being opened.");
1996 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1997 :
1998 : /* Delete the file and move onto directory testing. */
1999 1 : smbcli_unlink(cli->tree, fname);
2000 :
2001 : /* Now try some tests on a directory. */
2002 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2003 1 : io.ntcreatex.in.file_attr = 0;
2004 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
2005 1 : io.ntcreatex.in.fname = dname;
2006 :
2007 1 : status = smb_raw_open(cli->tree, tctx, &io);
2008 1 : torture_assert_ntstatus_ok(tctx, status, "Failed to create dir.");
2009 :
2010 : /* out attrib should be a directory. */
2011 1 : torture_assert_int_equal(tctx, io.ntcreatex.out.attrib,
2012 : FILE_ATTRIBUTE_DIRECTORY, "should have created a directory");
2013 :
2014 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2015 :
2016 : /* Try and open it with normal attr and check the error. */
2017 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2018 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2019 :
2020 1 : status = smb_raw_open(cli->tree, tctx, &io);
2021 1 : torture_assert_ntstatus_ok(tctx, status, "FILE_ATTRIBUTE_NORMAL "
2022 : "doesn't produce a hard failure.");
2023 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2024 :
2025 : /* Try and open it with file create_options and check the error. */
2026 1 : io.ntcreatex.in.file_attr = 0;
2027 1 : io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
2028 :
2029 1 : status = smb_raw_open(cli->tree, tctx, &io);
2030 1 : torture_assert_ntstatus_equal(tctx, status,
2031 : NT_STATUS_FILE_IS_A_DIRECTORY,
2032 : "NTCREATEX_OPTIONS_NON_DIRECTORY_FILE should be returned ");
2033 1 : smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
2034 :
2035 1 : smbcli_deltree(cli->tree, BASEDIR);
2036 :
2037 1 : return true;
2038 : }
2039 :
2040 : /*
2041 : test opening with truncate on an already open file
2042 : returns share violation and doesn't truncate the file.
2043 : Regression test for bug #10671.
2044 : */
2045 1 : static bool test_open_for_truncate(struct torture_context *tctx, struct smbcli_state *cli)
2046 : {
2047 : union smb_open io;
2048 : union smb_fileinfo finfo;
2049 1 : const char *fname = BASEDIR "\\torture_open_for_truncate.txt";
2050 : NTSTATUS status;
2051 1 : int fnum = -1;
2052 1 : ssize_t val = 0;
2053 1 : char c = '\0';
2054 1 : bool ret = true;
2055 :
2056 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR),
2057 : "Failed to setup up test directory: " BASEDIR);
2058 :
2059 1 : torture_comment(tctx, "Testing open truncate disposition.\n");
2060 :
2061 : /* reasonable default parameters */
2062 1 : ZERO_STRUCT(io);
2063 1 : io.generic.level = RAW_OPEN_NTCREATEX;
2064 1 : io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
2065 1 : io.ntcreatex.in.root_fid.fnum = 0;
2066 1 : io.ntcreatex.in.alloc_size = 0;
2067 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2068 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2069 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2070 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2071 1 : io.ntcreatex.in.create_options = 0;
2072 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2073 1 : io.ntcreatex.in.security_flags = 0;
2074 1 : io.ntcreatex.in.fname = fname;
2075 :
2076 1 : status = smb_raw_open(cli->tree, tctx, &io);
2077 1 : CHECK_STATUS(status, NT_STATUS_OK);
2078 1 : fnum = io.ntcreatex.out.file.fnum;
2079 :
2080 : /* Write a byte at offset 1k-1. */
2081 1 : val =smbcli_write(cli->tree, fnum, 0, &c, 1023, 1);
2082 1 : torture_assert_int_equal(tctx, val, 1, "write failed\n");
2083 :
2084 : /* Now try and open for read/write with truncate - should fail. */
2085 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_WRITE|SEC_RIGHTS_FILE_READ;
2086 1 : io.ntcreatex.in.file_attr = 0;
2087 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
2088 : NTCREATEX_SHARE_ACCESS_WRITE |
2089 : NTCREATEX_SHARE_ACCESS_DELETE;
2090 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
2091 1 : status = smb_raw_open(cli->tree, tctx, &io);
2092 1 : CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
2093 :
2094 : /* Ensure file size is still 1k */
2095 1 : finfo.generic.level = RAW_FILEINFO_GETATTRE;
2096 1 : finfo.generic.in.file.fnum = fnum;
2097 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
2098 1 : CHECK_STATUS(status, NT_STATUS_OK);
2099 1 : CHECK_VAL(finfo.getattre.out.size, 1024);
2100 :
2101 1 : smbcli_close(cli->tree, fnum);
2102 :
2103 1 : status = smb_raw_open(cli->tree, tctx, &io);
2104 1 : CHECK_STATUS(status, NT_STATUS_OK);
2105 1 : fnum = io.ntcreatex.out.file.fnum;
2106 :
2107 : /* Ensure truncate actually works */
2108 1 : finfo.generic.level = RAW_FILEINFO_GETATTRE;
2109 1 : finfo.generic.in.file.fnum = fnum;
2110 1 : status = smb_raw_fileinfo(cli->tree, tctx, &finfo);
2111 1 : CHECK_STATUS(status, NT_STATUS_OK);
2112 1 : CHECK_VAL(finfo.getattre.out.size, 0);
2113 :
2114 1 : smbcli_close(cli->tree, fnum);
2115 1 : smbcli_unlink(cli->tree, fname);
2116 :
2117 1 : done:
2118 1 : smbcli_close(cli->tree, fnum);
2119 1 : smbcli_deltree(cli->tree, BASEDIR);
2120 :
2121 1 : return ret;
2122 : }
2123 :
2124 : /**
2125 : * Test for file size to be 0 after create with FILE_SUPERSEDE
2126 : */
2127 1 : static bool test_ntcreatex_supersede(struct torture_context *tctx, struct smbcli_state *cli)
2128 : {
2129 : union smb_open io;
2130 : union smb_setfileinfo sfi;
2131 : union smb_fileinfo finfo;
2132 1 : const char *fname = BASEDIR "\\torture_ntcreatex_supersede.txt";
2133 : NTSTATUS status;
2134 1 : int fnum = -1;
2135 1 : bool ret = true;
2136 :
2137 1 : torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
2138 :
2139 : /* reasonable default parameters */
2140 1 : io.generic.level = RAW_OPEN_NTCREATEX;
2141 1 : io.ntcreatex.in.flags = 0;
2142 1 : io.ntcreatex.in.root_fid.fnum = 0;
2143 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
2144 1 : io.ntcreatex.in.alloc_size = 0;
2145 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2146 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2147 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
2148 1 : io.ntcreatex.in.create_options = 0;
2149 1 : io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
2150 1 : io.ntcreatex.in.security_flags = 0;
2151 1 : io.ntcreatex.in.fname = fname;
2152 :
2153 1 : status = smb_raw_open(cli->tree, tctx, &io);
2154 1 : CHECK_STATUS(status, NT_STATUS_OK);
2155 1 : fnum = io.ntcreatex.out.file.fnum;
2156 :
2157 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2158 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
2159 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2160 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2161 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
2162 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
2163 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2164 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2165 1 : CHECK_ALL_INFO(io.ntcreatex.out.size, size);
2166 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2167 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2168 :
2169 : /* extend the file size */
2170 1 : ZERO_STRUCT(sfi);
2171 1 : sfi.generic.level = RAW_SFILEINFO_END_OF_FILE_INFO;
2172 1 : sfi.generic.in.file.fnum = fnum;
2173 1 : sfi.end_of_file_info.in.size = 512;
2174 1 : status = smb_raw_setfileinfo(cli->tree, &sfi);
2175 1 : CHECK_STATUS(status, NT_STATUS_OK);
2176 :
2177 : /* close the file and re-open with to verify new size */
2178 1 : smbcli_close(cli->tree, fnum);
2179 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2180 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ;
2181 1 : status = smb_raw_open(cli->tree, tctx, &io);
2182 1 : CHECK_STATUS(status, NT_STATUS_OK);
2183 1 : fnum = io.ntcreatex.out.file.fnum;
2184 :
2185 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2186 1 : CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
2187 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2188 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2189 1 : CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
2190 1 : CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
2191 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2192 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2193 1 : CHECK_VAL(io.ntcreatex.out.size, 512);
2194 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2195 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2196 :
2197 : /* close and re-open the file with SUPERSEDE flag */
2198 1 : smbcli_close(cli->tree, fnum);
2199 1 : io.ntcreatex.in.open_disposition = NTCREATEX_DISP_SUPERSEDE;
2200 1 : io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_READ;
2201 1 : io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
2202 1 : io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
2203 1 : io.ntcreatex.in.create_options = 0;
2204 :
2205 1 : status = smb_raw_open(cli->tree, tctx, &io);
2206 1 : CHECK_STATUS(status, NT_STATUS_OK);
2207 1 : fnum = io.ntcreatex.out.file.fnum;
2208 :
2209 : /* The file size in the superseded create response should be 0 */
2210 1 : CHECK_VAL(io.ntcreatex.out.size, 0);
2211 1 : CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
2212 1 : CHECK_VAL(io.ntcreatex.out.create_action, FILE_WAS_SUPERSEDED);
2213 1 : CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
2214 1 : CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
2215 1 : CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
2216 1 : CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
2217 1 : CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
2218 1 : CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
2219 1 : done:
2220 1 : smbcli_close(cli->tree, fnum);
2221 1 : smbcli_deltree(cli->tree, BASEDIR);
2222 :
2223 1 : return ret;
2224 : }
2225 :
2226 : /* basic testing of all RAW_OPEN_* calls
2227 : */
2228 966 : struct torture_suite *torture_raw_open(TALLOC_CTX *mem_ctx)
2229 : {
2230 966 : struct torture_suite *suite = torture_suite_create(mem_ctx, "open");
2231 :
2232 966 : torture_suite_add_1smb_test(suite, "brlocked", test_ntcreatex_brlocked);
2233 966 : torture_suite_add_1smb_test(suite, "open", test_open);
2234 966 : torture_suite_add_1smb_test(suite, "open-multi", test_raw_open_multi);
2235 966 : torture_suite_add_1smb_test(suite, "openx", test_openx);
2236 966 : torture_suite_add_1smb_test(suite, "ntcreatex", test_ntcreatex);
2237 966 : torture_suite_add_1smb_test(suite, "nttrans-create", test_nttrans_create);
2238 966 : torture_suite_add_1smb_test(suite, "t2open", test_t2open);
2239 966 : torture_suite_add_1smb_test(suite, "mknew", test_mknew);
2240 966 : torture_suite_add_1smb_test(suite, "create", test_create);
2241 966 : torture_suite_add_1smb_test(suite, "ctemp", test_ctemp);
2242 966 : torture_suite_add_1smb_test(suite, "chained-openx", test_chained);
2243 966 : torture_suite_add_1smb_test(suite, "chained-ntcreatex", test_chained_ntcreatex_readx);
2244 966 : torture_suite_add_1smb_test(suite, "no-leading-slash", test_no_leading_slash);
2245 966 : torture_suite_add_1smb_test(suite, "openx-over-dir", test_openx_over_dir);
2246 966 : torture_suite_add_1smb_test(suite, "open-for-delete", test_open_for_delete);
2247 966 : torture_suite_add_1smb_test(suite, "opendisp-dir", test_ntcreatex_opendisp_dir);
2248 966 : torture_suite_add_1smb_test(suite, "ntcreatedir", test_ntcreatexdir);
2249 966 : torture_suite_add_1smb_test(suite, "open-for-truncate", test_open_for_truncate);
2250 966 : torture_suite_add_1smb_test(suite, "ntcreatex_supersede", test_ntcreatex_supersede);
2251 :
2252 966 : return suite;
2253 : }
|