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 2 of the License, or
9    (at your option) any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "librpc/gen_ndr/security.h"
27 #include "lib/events/events.h"
28 #include "libcli/libcli.h"
29 #include "torture/util.h"
30 
31 /* enum for whether reads/writes are possible on a file */
32 enum rdwr_mode {RDWR_NONE, RDWR_RDONLY, RDWR_WRONLY, RDWR_RDWR};
33 
34 #define BASEDIR "\\rawopen"
35 
36 /*
37   check if a open file can be read/written
38 */
check_rdwr(struct smbcli_tree * tree,int fnum)39 static enum rdwr_mode check_rdwr(struct smbcli_tree *tree, int fnum)
40 {
41 	uint8_t c = 1;
42 	BOOL can_read  = (smbcli_read(tree, fnum, &c, 0, 1) == 1);
43 	BOOL can_write = (smbcli_write(tree, fnum, 0, &c, 0, 1) == 1);
44 	if ( can_read &&  can_write) return RDWR_RDWR;
45 	if ( can_read && !can_write) return RDWR_RDONLY;
46 	if (!can_read &&  can_write) return RDWR_WRONLY;
47 	return RDWR_NONE;
48 }
49 
50 /*
51   describe a RDWR mode as a string
52 */
rdwr_string(enum rdwr_mode m)53 static const char *rdwr_string(enum rdwr_mode m)
54 {
55 	switch (m) {
56 	case RDWR_NONE: return "NONE";
57 	case RDWR_RDONLY: return "RDONLY";
58 	case RDWR_WRONLY: return "WRONLY";
59 	case RDWR_RDWR: return "RDWR";
60 	}
61 	return "-";
62 }
63 
64 #define CHECK_STATUS(status, correct) do { \
65 	if (!NT_STATUS_EQUAL(status, correct)) { \
66 		printf("(%s) Incorrect status %s - should be %s\n", \
67 		       __location__, nt_errstr(status), nt_errstr(correct)); \
68 		ret = False; \
69 		goto done; \
70 	}} while (0)
71 
72 #define CREATE_FILE do { \
73 	fnum = create_complex_file(cli, mem_ctx, fname); \
74 	if (fnum == -1) { \
75 		printf("(%s) Failed to create %s - %s\n", __location__, fname, smbcli_errstr(cli->tree)); \
76 		ret = False; \
77 		goto done; \
78 	}} while (0)
79 
80 #define CHECK_RDWR(fnum, correct) do { \
81 	enum rdwr_mode m = check_rdwr(cli->tree, fnum); \
82 	if (m != correct) { \
83 		printf("(%s) Incorrect readwrite mode %s - expected %s\n", \
84 		       __location__, rdwr_string(m), rdwr_string(correct)); \
85 		ret = False; \
86 	}} while (0)
87 
88 #define CHECK_TIME(t, field) do { \
89 	time_t t1, t2; \
90 	finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
91 	finfo.all_info.in.file.path = fname; \
92 	status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
93 	CHECK_STATUS(status, NT_STATUS_OK); \
94 	t1 = t & ~1; \
95 	t2 = nt_time_to_unix(finfo.all_info.out.field) & ~1; \
96 	if (abs(t1-t2) > 2) { \
97 		printf("(%s) wrong time for field %s  %s - %s\n", \
98 		       __location__, #field, \
99 		       timestring(mem_ctx, t1), \
100 		       timestring(mem_ctx, t2)); \
101 		dump_all_info(mem_ctx, &finfo); \
102 		ret = False; \
103 	}} while (0)
104 
105 #define CHECK_NTTIME(t, field) do { \
106 	NTTIME t2; \
107 	finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
108 	finfo.all_info.in.file.path = fname; \
109 	status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
110 	CHECK_STATUS(status, NT_STATUS_OK); \
111 	t2 = finfo.all_info.out.field; \
112 	if (t != t2) { \
113 		printf("(%s) wrong time for field %s  %s - %s\n", \
114 		       __location__, #field, \
115 		       nt_time_string(mem_ctx, t), \
116 		       nt_time_string(mem_ctx, t2)); \
117 		dump_all_info(mem_ctx, &finfo); \
118 		ret = False; \
119 	}} while (0)
120 
121 #define CHECK_ALL_INFO(v, field) do { \
122 	finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
123 	finfo.all_info.in.file.path = fname; \
124 	status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
125 	CHECK_STATUS(status, NT_STATUS_OK); \
126 	if ((v) != (finfo.all_info.out.field)) { \
127 		printf("(%s) wrong value for field %s  0x%x - 0x%x\n", \
128 		       __location__, #field, (int)v, (int)(finfo.all_info.out.field)); \
129 		dump_all_info(mem_ctx, &finfo); \
130 		ret = False; \
131 	}} while (0)
132 
133 #define CHECK_VAL(v, correct) do { \
134 	if ((v) != (correct)) { \
135 		printf("(%s) wrong value for %s  0x%x - should be 0x%x\n", \
136 		       __location__, #v, (int)(v), (int)correct); \
137 		ret = False; \
138 	}} while (0)
139 
140 #define SET_ATTRIB(sattrib) do { \
141 	union smb_setfileinfo sfinfo; \
142 	ZERO_STRUCT(sfinfo.basic_info.in); \
143 	sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION; \
144 	sfinfo.basic_info.in.file.path = fname; \
145 	sfinfo.basic_info.in.attrib = sattrib; \
146 	status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
147 	if (!NT_STATUS_IS_OK(status)) { \
148 		printf("(%s) Failed to set attrib 0x%x on %s\n", \
149 		       __location__, sattrib, fname); \
150 	}} while (0)
151 
152 /*
153   test RAW_OPEN_OPEN
154 */
test_open(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)155 static BOOL test_open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
156 {
157 	union smb_open io;
158 	union smb_fileinfo finfo;
159 	const char *fname = BASEDIR "\\torture_open.txt";
160 	NTSTATUS status;
161 	int fnum = -1, fnum2;
162 	BOOL ret = True;
163 
164 	printf("Checking RAW_OPEN_OPEN\n");
165 
166 	io.openold.level = RAW_OPEN_OPEN;
167 	io.openold.in.fname = fname;
168 	io.openold.in.open_mode = OPEN_FLAGS_FCB;
169 	io.openold.in.search_attrs = 0;
170 	status = smb_raw_open(cli->tree, mem_ctx, &io);
171 	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
172 	fnum = io.openold.out.file.fnum;
173 
174 	smbcli_unlink(cli->tree, fname);
175 	CREATE_FILE;
176 	smbcli_close(cli->tree, fnum);
177 
178 	status = smb_raw_open(cli->tree, mem_ctx, &io);
179 	CHECK_STATUS(status, NT_STATUS_OK);
180 	fnum = io.openold.out.file.fnum;
181 	CHECK_RDWR(fnum, RDWR_RDWR);
182 
183 	status = smb_raw_open(cli->tree, mem_ctx, &io);
184 	CHECK_STATUS(status, NT_STATUS_OK);
185 	fnum2 = io.openold.out.file.fnum;
186 	CHECK_RDWR(fnum2, RDWR_RDWR);
187 	smbcli_close(cli->tree, fnum2);
188 	smbcli_close(cli->tree, fnum);
189 
190 	/* check the read/write modes */
191 	io.openold.level = RAW_OPEN_OPEN;
192 	io.openold.in.fname = fname;
193 	io.openold.in.search_attrs = 0;
194 
195 	io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
196 	status = smb_raw_open(cli->tree, mem_ctx, &io);
197 	CHECK_STATUS(status, NT_STATUS_OK);
198 	fnum = io.openold.out.file.fnum;
199 	CHECK_RDWR(fnum, RDWR_RDONLY);
200 	smbcli_close(cli->tree, fnum);
201 
202 	io.openold.in.open_mode = OPEN_FLAGS_OPEN_WRITE;
203 	status = smb_raw_open(cli->tree, mem_ctx, &io);
204 	CHECK_STATUS(status, NT_STATUS_OK);
205 	fnum = io.openold.out.file.fnum;
206 	CHECK_RDWR(fnum, RDWR_WRONLY);
207 	smbcli_close(cli->tree, fnum);
208 
209 	io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR;
210 	status = smb_raw_open(cli->tree, mem_ctx, &io);
211 	CHECK_STATUS(status, NT_STATUS_OK);
212 	fnum = io.openold.out.file.fnum;
213 	CHECK_RDWR(fnum, RDWR_RDWR);
214 	smbcli_close(cli->tree, fnum);
215 
216 	/* check the share modes roughly - not a complete matrix */
217 	io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_WRITE;
218 	status = smb_raw_open(cli->tree, mem_ctx, &io);
219 	CHECK_STATUS(status, NT_STATUS_OK);
220 	fnum = io.openold.out.file.fnum;
221 	CHECK_RDWR(fnum, RDWR_RDWR);
222 
223 	if (io.openold.in.open_mode != io.openold.out.rmode) {
224 		printf("(%s) rmode should equal open_mode - 0x%x 0x%x\n",
225 		       __location__, io.openold.out.rmode, io.openold.in.open_mode);
226 	}
227 
228 	io.openold.in.open_mode = OPEN_FLAGS_OPEN_RDWR | OPEN_FLAGS_DENY_NONE;
229 	status = smb_raw_open(cli->tree, mem_ctx, &io);
230 	CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
231 
232 	io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ | OPEN_FLAGS_DENY_NONE;
233 	status = smb_raw_open(cli->tree, mem_ctx, &io);
234 	CHECK_STATUS(status, NT_STATUS_OK);
235 	fnum2 = io.openold.out.file.fnum;
236 	CHECK_RDWR(fnum2, RDWR_RDONLY);
237 	smbcli_close(cli->tree, fnum);
238 	smbcli_close(cli->tree, fnum2);
239 
240 
241 	/* check the returned write time */
242 	io.openold.level = RAW_OPEN_OPEN;
243 	io.openold.in.fname = fname;
244 	io.openold.in.search_attrs = 0;
245 	io.openold.in.open_mode = OPEN_FLAGS_OPEN_READ;
246 	status = smb_raw_open(cli->tree, mem_ctx, &io);
247 	CHECK_STATUS(status, NT_STATUS_OK);
248 	fnum = io.openold.out.file.fnum;
249 
250 	/* check other reply fields */
251 	CHECK_TIME(io.openold.out.write_time, write_time);
252 	CHECK_ALL_INFO(io.openold.out.size, size);
253 	CHECK_ALL_INFO(io.openold.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
254 
255 done:
256 	smbcli_close(cli->tree, fnum);
257 	smbcli_unlink(cli->tree, fname);
258 
259 	return ret;
260 }
261 
262 
263 /*
264   test RAW_OPEN_OPENX
265 */
test_openx(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)266 static BOOL test_openx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
267 {
268 	union smb_open io;
269 	union smb_fileinfo finfo;
270 	const char *fname = BASEDIR "\\torture_openx.txt";
271 	const char *fname_exe = BASEDIR "\\torture_openx.exe";
272 	NTSTATUS status;
273 	int fnum = -1, fnum2;
274 	BOOL ret = True;
275 	int i;
276 	struct timeval tv;
277 	struct {
278 		uint16_t open_func;
279 		BOOL with_file;
280 		NTSTATUS correct_status;
281 	} open_funcs[] = {
282 		{ OPENX_OPEN_FUNC_OPEN, 	                  True,  NT_STATUS_OK },
283 		{ OPENX_OPEN_FUNC_OPEN,  	                  False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
284 		{ OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
285 		{ OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
286 		{ OPENX_OPEN_FUNC_FAIL, 	                  True,  NT_STATUS_DOS(ERRDOS, ERRbadaccess) },
287 		{ OPENX_OPEN_FUNC_FAIL, 	                  False, NT_STATUS_DOS(ERRDOS, ERRbadaccess) },
288 		{ OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OBJECT_NAME_COLLISION },
289 		{ OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
290 		{ OPENX_OPEN_FUNC_TRUNC, 	                  True,  NT_STATUS_OK },
291 		{ OPENX_OPEN_FUNC_TRUNC, 	                  False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
292 		{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
293 		{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
294 	};
295 
296 	printf("Checking RAW_OPEN_OPENX\n");
297 	smbcli_unlink(cli->tree, fname);
298 
299 	io.openx.level = RAW_OPEN_OPENX;
300 	io.openx.in.fname = fname;
301 	io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
302 	io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
303 	io.openx.in.search_attrs = 0;
304 	io.openx.in.file_attrs = 0;
305 	io.openx.in.write_time = 0;
306 	io.openx.in.size = 1024*1024;
307 	io.openx.in.timeout = 0;
308 
309 	/* check all combinations of open_func */
310 	for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
311 		if (open_funcs[i].with_file) {
312 			fnum = create_complex_file(cli, mem_ctx, fname);
313 			if (fnum == -1) {
314 				d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
315 				ret = False;
316 				goto done;
317 			}
318 			smbcli_close(cli->tree, fnum);
319 		}
320 		io.openx.in.open_func = open_funcs[i].open_func;
321 		status = smb_raw_open(cli->tree, mem_ctx, &io);
322 		if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
323 			printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n",
324 			       __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
325 			       i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
326 			ret = False;
327 		}
328 		if (NT_STATUS_IS_OK(status)) {
329 			smbcli_close(cli->tree, io.openx.out.file.fnum);
330 		}
331 		if (open_funcs[i].with_file) {
332 			smbcli_unlink(cli->tree, fname);
333 		}
334 	}
335 
336 	smbcli_unlink(cli->tree, fname);
337 
338 	/* check the basic return fields */
339 	io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
340 	status = smb_raw_open(cli->tree, mem_ctx, &io);
341 	CHECK_STATUS(status, NT_STATUS_OK);
342 	fnum = io.openx.out.file.fnum;
343 
344 	CHECK_ALL_INFO(io.openx.out.size, size);
345 	CHECK_TIME(io.openx.out.write_time, write_time);
346 	CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
347 	CHECK_VAL(io.openx.out.access, OPENX_MODE_ACCESS_RDWR);
348 	CHECK_VAL(io.openx.out.ftype, 0);
349 	CHECK_VAL(io.openx.out.devstate, 0);
350 	CHECK_VAL(io.openx.out.action, OPENX_ACTION_CREATED);
351 	CHECK_VAL(io.openx.out.size, 1024*1024);
352 	CHECK_ALL_INFO(io.openx.in.size, size);
353 	smbcli_close(cli->tree, fnum);
354 	smbcli_unlink(cli->tree, fname);
355 
356 	/* check the fields when the file already existed */
357 	fnum2 = create_complex_file(cli, mem_ctx, fname);
358 	if (fnum2 == -1) {
359 		ret = False;
360 		goto done;
361 	}
362 	smbcli_close(cli->tree, fnum2);
363 
364 	io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
365 	status = smb_raw_open(cli->tree, mem_ctx, &io);
366 	CHECK_STATUS(status, NT_STATUS_OK);
367 	fnum = io.openx.out.file.fnum;
368 
369 	CHECK_ALL_INFO(io.openx.out.size, size);
370 	CHECK_TIME(io.openx.out.write_time, write_time);
371 	CHECK_VAL(io.openx.out.action, OPENX_ACTION_EXISTED);
372 	CHECK_VAL(io.openx.out.unknown, 0);
373 	CHECK_ALL_INFO(io.openx.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
374 	smbcli_close(cli->tree, fnum);
375 
376 	/* now check the search attrib for hidden files - win2003 ignores this? */
377 	SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
378 	CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
379 
380 	io.openx.in.search_attrs = FILE_ATTRIBUTE_HIDDEN;
381 	status = smb_raw_open(cli->tree, mem_ctx, &io);
382 	CHECK_STATUS(status, NT_STATUS_OK);
383 	smbcli_close(cli->tree, io.openx.out.file.fnum);
384 
385 	io.openx.in.search_attrs = 0;
386 	status = smb_raw_open(cli->tree, mem_ctx, &io);
387 	CHECK_STATUS(status, NT_STATUS_OK);
388 	smbcli_close(cli->tree, io.openx.out.file.fnum);
389 
390 	SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
391 	smbcli_unlink(cli->tree, fname);
392 
393 	/* and check attrib on create */
394 	io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
395 	io.openx.in.search_attrs = 0;
396 	io.openx.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
397 	status = smb_raw_open(cli->tree, mem_ctx, &io);
398 	CHECK_STATUS(status, NT_STATUS_OK);
399 	CHECK_ALL_INFO(FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE,
400 		       attrib & ~FILE_ATTRIBUTE_NONINDEXED);
401 	smbcli_close(cli->tree, io.openx.out.file.fnum);
402 	smbcli_unlink(cli->tree, fname);
403 
404 	/* check timeout on create - win2003 ignores the timeout! */
405 	io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
406 	io.openx.in.file_attrs = 0;
407 	io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
408 	status = smb_raw_open(cli->tree, mem_ctx, &io);
409 	CHECK_STATUS(status, NT_STATUS_OK);
410 	fnum = io.openx.out.file.fnum;
411 
412 	io.openx.in.timeout = 20000;
413 	tv = timeval_current();
414 	io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_NONE;
415 	status = smb_raw_open(cli->tree, mem_ctx, &io);
416 	CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
417 	if (timeval_elapsed(&tv) > 3.0) {
418 		printf("(%s) Incorrect timing in openx with timeout - waited %.2f seconds\n",
419 		       __location__, timeval_elapsed(&tv));
420 		ret = False;
421 	}
422 	smbcli_close(cli->tree, fnum);
423 	smbcli_unlink(cli->tree, fname);
424 
425 	/* now this is a really weird one - open for execute implies create?! */
426 	io.openx.in.fname = fname;
427 	io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
428 	io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
429 	io.openx.in.search_attrs = 0;
430 	io.openx.in.open_func = OPENX_OPEN_FUNC_FAIL;
431 	io.openx.in.file_attrs = 0;
432 	io.openx.in.write_time = 0;
433 	io.openx.in.size = 0;
434 	io.openx.in.timeout = 0;
435 	status = smb_raw_open(cli->tree, mem_ctx, &io);
436 	CHECK_STATUS(status, NT_STATUS_OK);
437 	smbcli_close(cli->tree, io.openx.out.file.fnum);
438 
439 	/* check the extended return flag */
440 	io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO | OPENX_FLAGS_EXTENDED_RETURN;
441 	io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
442 	status = smb_raw_open(cli->tree, mem_ctx, &io);
443 	CHECK_STATUS(status, NT_STATUS_OK);
444 	CHECK_VAL(io.openx.out.access_mask, SEC_STD_ALL);
445 	smbcli_close(cli->tree, io.openx.out.file.fnum);
446 
447 	io.openx.in.fname = "\\A.+,;=[].B";
448 	status = smb_raw_open(cli->tree, mem_ctx, &io);
449 	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
450 
451 	/* Check the mapping for open exec. */
452 
453 	/* First create an .exe file. */
454 	smbcli_unlink(cli->tree, fname_exe);
455 	fnum = create_complex_file(cli, mem_ctx, fname_exe);
456 	smbcli_close(cli->tree, fnum);
457 
458 	io.openx.level = RAW_OPEN_OPENX;
459 	io.openx.in.fname = fname_exe;
460 	io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
461 	io.openx.in.open_mode = OPENX_MODE_ACCESS_EXEC | OPENX_MODE_DENY_NONE;
462 	io.openx.in.search_attrs = 0;
463 	io.openx.in.file_attrs = 0;
464 	io.openx.in.write_time = 0;
465 	io.openx.in.size = 0;
466 	io.openx.in.timeout = 0;
467 	status = smb_raw_open(cli->tree, mem_ctx, &io);
468 	CHECK_STATUS(status, NT_STATUS_OK);
469 
470 	/* Can we read and write ? */
471 	CHECK_RDWR(io.openx.out.file.fnum, RDWR_RDONLY);
472 	smbcli_close(cli->tree, io.openx.out.file.fnum);
473 	smbcli_unlink(cli->tree, fname);
474 
475 done:
476 	smbcli_close(cli->tree, fnum);
477 	smbcli_unlink(cli->tree, fname_exe);
478 	smbcli_unlink(cli->tree, fname);
479 
480 	return ret;
481 }
482 
483 
484 /*
485   test RAW_OPEN_T2OPEN
486 
487   many thanks to kukks for a sniff showing how this works with os2->w2k
488 */
test_t2open(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)489 static BOOL test_t2open(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
490 {
491 	union smb_open io;
492 	union smb_fileinfo finfo;
493 	const char *fname1 = BASEDIR "\\torture_t2open_yes.txt";
494 	const char *fname2 = BASEDIR "\\torture_t2open_no.txt";
495 	const char *fname = BASEDIR "\\torture_t2open_3.txt";
496 	NTSTATUS status;
497 	int fnum;
498 	BOOL ret = True;
499 	int i;
500 	struct {
501 		uint16_t open_func;
502 		BOOL with_file;
503 		NTSTATUS correct_status;
504 	} open_funcs[] = {
505 		{ OPENX_OPEN_FUNC_OPEN, 	                  True,  NT_STATUS_OK },
506 		{ OPENX_OPEN_FUNC_OPEN,  	                  False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
507 		{ OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
508 		{ OPENX_OPEN_FUNC_OPEN  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
509 		{ OPENX_OPEN_FUNC_FAIL, 	                  True,  NT_STATUS_OBJECT_NAME_COLLISION },
510 		{ OPENX_OPEN_FUNC_FAIL, 	                  False, NT_STATUS_OBJECT_NAME_COLLISION },
511 		{ OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OBJECT_NAME_COLLISION },
512 		{ OPENX_OPEN_FUNC_FAIL  | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OBJECT_NAME_COLLISION },
513 		{ OPENX_OPEN_FUNC_TRUNC, 	                  True,  NT_STATUS_OK },
514 		{ OPENX_OPEN_FUNC_TRUNC, 	                  False, NT_STATUS_OK },
515 		{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, True,  NT_STATUS_OK },
516 		{ OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE, False, NT_STATUS_OK },
517 	};
518 
519 	fnum = create_complex_file(cli, mem_ctx, fname1);
520 	if (fnum == -1) {
521 		d_printf("Failed to create file %s - %s\n", fname1, smbcli_errstr(cli->tree));
522 		ret = False;
523 		goto done;
524 	}
525 	smbcli_close(cli->tree, fnum);
526 
527 	printf("Checking RAW_OPEN_T2OPEN\n");
528 
529 	io.t2open.level = RAW_OPEN_T2OPEN;
530 	io.t2open.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
531 	io.t2open.in.open_mode = OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR;
532 	io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
533 	io.t2open.in.search_attrs = 0;
534 	io.t2open.in.file_attrs = 0;
535 	io.t2open.in.write_time = 0;
536 	io.t2open.in.size = 0;
537 	io.t2open.in.timeout = 0;
538 
539 	io.t2open.in.num_eas = 3;
540 	io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
541 	io.t2open.in.eas[0].flags = 0;
542 	io.t2open.in.eas[0].name.s = ".CLASSINFO";
543 	io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
544 	io.t2open.in.eas[1].flags = 0;
545 	io.t2open.in.eas[1].name.s = "EA TWO";
546 	io.t2open.in.eas[1].value = data_blob_talloc(mem_ctx, "foo", 3);
547 	io.t2open.in.eas[2].flags = 0;
548 	io.t2open.in.eas[2].name.s = "X THIRD";
549 	io.t2open.in.eas[2].value = data_blob_talloc(mem_ctx, "xy", 2);
550 
551 	/* check all combinations of open_func */
552 	for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
553 		if (open_funcs[i].with_file) {
554 			io.t2open.in.fname = fname1;
555 		} else {
556 			io.t2open.in.fname = fname2;
557 		}
558 		io.t2open.in.open_func = open_funcs[i].open_func;
559 		status = smb_raw_open(cli->tree, mem_ctx, &io);
560 		if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
561 			printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_func=0x%x)\n",
562 			       __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
563 			       i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_func);
564 			ret = False;
565 		}
566 		if (NT_STATUS_IS_OK(status)) {
567 			smbcli_close(cli->tree, io.t2open.out.file.fnum);
568 		}
569 	}
570 
571 	smbcli_unlink(cli->tree, fname1);
572 	smbcli_unlink(cli->tree, fname2);
573 
574 	/* check the basic return fields */
575 	io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
576 	io.t2open.in.write_time = 0;
577 	io.t2open.in.fname = fname;
578 	status = smb_raw_open(cli->tree, mem_ctx, &io);
579 	CHECK_STATUS(status, NT_STATUS_OK);
580 	fnum = io.t2open.out.file.fnum;
581 
582 	CHECK_ALL_INFO(io.t2open.out.size, size);
583 #if 0
584 	/* windows appears to leak uninitialised memory here */
585 	CHECK_VAL(io.t2open.out.write_time, 0);
586 #endif
587 	CHECK_ALL_INFO(io.t2open.out.attrib, attrib & ~FILE_ATTRIBUTE_NONINDEXED);
588 	CHECK_VAL(io.t2open.out.access, OPENX_MODE_DENY_NONE | OPENX_MODE_ACCESS_RDWR);
589 	CHECK_VAL(io.t2open.out.ftype, 0);
590 	CHECK_VAL(io.t2open.out.devstate, 0);
591 	CHECK_VAL(io.t2open.out.action, OPENX_ACTION_CREATED);
592 	smbcli_close(cli->tree, fnum);
593 
594 	status = torture_check_ea(cli, fname, ".CLASSINFO", "first value");
595 	CHECK_STATUS(status, NT_STATUS_OK);
596 	status = torture_check_ea(cli, fname, "EA TWO", "foo");
597 	CHECK_STATUS(status, NT_STATUS_OK);
598 	status = torture_check_ea(cli, fname, "X THIRD", "xy");
599 	CHECK_STATUS(status, NT_STATUS_OK);
600 
601 	/* now check the search attrib for hidden files - win2003 ignores this? */
602 	SET_ATTRIB(FILE_ATTRIBUTE_HIDDEN);
603 	CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN, attrib);
604 
605 	status = smb_raw_open(cli->tree, mem_ctx, &io);
606 	CHECK_STATUS(status, NT_STATUS_OK);
607 	smbcli_close(cli->tree, io.t2open.out.file.fnum);
608 
609 	status = smb_raw_open(cli->tree, mem_ctx, &io);
610 	CHECK_STATUS(status, NT_STATUS_OK);
611 	smbcli_close(cli->tree, io.t2open.out.file.fnum);
612 
613 	SET_ATTRIB(FILE_ATTRIBUTE_NORMAL);
614 	smbcli_unlink(cli->tree, fname);
615 
616 	/* and check attrib on create */
617 	io.t2open.in.open_func = OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE;
618 	io.t2open.in.file_attrs = FILE_ATTRIBUTE_SYSTEM;
619 	status = smb_raw_open(cli->tree, mem_ctx, &io);
620 	CHECK_STATUS(status, NT_STATUS_OK);
621 
622 	/* check timeout on create - win2003 ignores the timeout! */
623 	io.t2open.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
624 	io.t2open.in.file_attrs = 0;
625 	io.t2open.in.timeout = 20000;
626 	io.t2open.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_ALL;
627 	status = smb_raw_open(cli->tree, mem_ctx, &io);
628 	CHECK_STATUS(status, NT_STATUS_SHARING_VIOLATION);
629 
630 done:
631 	smbcli_close(cli->tree, fnum);
632 	smbcli_unlink(cli->tree, fname);
633 
634 	return ret;
635 }
636 
637 
638 /*
639   test RAW_OPEN_NTCREATEX
640 */
test_ntcreatex(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)641 static BOOL test_ntcreatex(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
642 {
643 	union smb_open io;
644 	union smb_fileinfo finfo;
645 	const char *fname = BASEDIR "\\torture_ntcreatex.txt";
646 	const char *dname = BASEDIR "\\torture_ntcreatex.dir";
647 	NTSTATUS status;
648 	int fnum = -1;
649 	BOOL ret = True;
650 	int i;
651 	struct {
652 		uint32_t open_disp;
653 		BOOL with_file;
654 		NTSTATUS correct_status;
655 	} open_funcs[] = {
656 		{ NTCREATEX_DISP_SUPERSEDE, 	True,  NT_STATUS_OK },
657 		{ NTCREATEX_DISP_SUPERSEDE, 	False, NT_STATUS_OK },
658 		{ NTCREATEX_DISP_OPEN, 	        True,  NT_STATUS_OK },
659 		{ NTCREATEX_DISP_OPEN, 	        False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
660 		{ NTCREATEX_DISP_CREATE, 	True,  NT_STATUS_OBJECT_NAME_COLLISION },
661 		{ NTCREATEX_DISP_CREATE, 	False, NT_STATUS_OK },
662 		{ NTCREATEX_DISP_OPEN_IF, 	True,  NT_STATUS_OK },
663 		{ NTCREATEX_DISP_OPEN_IF, 	False, NT_STATUS_OK },
664 		{ NTCREATEX_DISP_OVERWRITE, 	True,  NT_STATUS_OK },
665 		{ NTCREATEX_DISP_OVERWRITE, 	False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
666 		{ NTCREATEX_DISP_OVERWRITE_IF, 	True,  NT_STATUS_OK },
667 		{ NTCREATEX_DISP_OVERWRITE_IF, 	False, NT_STATUS_OK },
668 		{ 6, 			        True,  NT_STATUS_INVALID_PARAMETER },
669 		{ 6, 	                        False, NT_STATUS_INVALID_PARAMETER },
670 	};
671 
672 	printf("Checking RAW_OPEN_NTCREATEX\n");
673 
674 	/* reasonable default parameters */
675 	io.generic.level = RAW_OPEN_NTCREATEX;
676 	io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
677 	io.ntcreatex.in.root_fid = 0;
678 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
679 	io.ntcreatex.in.alloc_size = 1024*1024;
680 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
681 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
682 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
683 	io.ntcreatex.in.create_options = 0;
684 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
685 	io.ntcreatex.in.security_flags = 0;
686 	io.ntcreatex.in.fname = fname;
687 
688 	/* test the open disposition */
689 	for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
690 		if (open_funcs[i].with_file) {
691 			fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
692 			if (fnum == -1) {
693 				d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
694 				ret = False;
695 				goto done;
696 			}
697 			smbcli_close(cli->tree, fnum);
698 		}
699 		io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
700 		status = smb_raw_open(cli->tree, mem_ctx, &io);
701 		if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
702 			printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n",
703 			       __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
704 			       i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp);
705 			ret = False;
706 		}
707 		if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
708 			smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
709 			smbcli_unlink(cli->tree, fname);
710 		}
711 	}
712 
713 	/* basic field testing */
714 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
715 
716 	status = smb_raw_open(cli->tree, mem_ctx, &io);
717 	CHECK_STATUS(status, NT_STATUS_OK);
718 	fnum = io.ntcreatex.out.file.fnum;
719 
720 	CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
721 	CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
722 	CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
723 	CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
724 	CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
725 	CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
726 	CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
727 	CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
728 	CHECK_ALL_INFO(io.ntcreatex.out.size, size);
729 	CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
730 	CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
731 
732 	/* check fields when the file already existed */
733 	smbcli_close(cli->tree, fnum);
734 	smbcli_unlink(cli->tree, fname);
735 	fnum = create_complex_file(cli, mem_ctx, fname);
736 	if (fnum == -1) {
737 		ret = False;
738 		goto done;
739 	}
740 	smbcli_close(cli->tree, fnum);
741 
742 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
743 	status = smb_raw_open(cli->tree, mem_ctx, &io);
744 	CHECK_STATUS(status, NT_STATUS_OK);
745 	fnum = io.ntcreatex.out.file.fnum;
746 
747 	CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
748 	CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
749 	CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
750 	CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
751 	CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
752 	CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
753 	CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
754 	CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
755 	CHECK_ALL_INFO(io.ntcreatex.out.size, size);
756 	CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
757 	CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
758 	smbcli_close(cli->tree, fnum);
759 	smbcli_unlink(cli->tree, fname);
760 
761 
762 	/* create a directory */
763 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
764 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
765 	io.ntcreatex.in.alloc_size = 0;
766 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
767 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
768 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
769 	io.ntcreatex.in.create_options = 0;
770 	io.ntcreatex.in.fname = dname;
771 	fname = dname;
772 
773 	smbcli_rmdir(cli->tree, fname);
774 	smbcli_unlink(cli->tree, fname);
775 
776 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
777 	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
778 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
779 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
780 	status = smb_raw_open(cli->tree, mem_ctx, &io);
781 	CHECK_STATUS(status, NT_STATUS_OK);
782 	fnum = io.ntcreatex.out.file.fnum;
783 
784 	CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
785 	CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
786 	CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
787 	CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
788 	CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
789 	CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
790 	CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
791 	CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
792 		  FILE_ATTRIBUTE_DIRECTORY);
793 	CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
794 	CHECK_ALL_INFO(io.ntcreatex.out.size, size);
795 	CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
796 	CHECK_VAL(io.ntcreatex.out.is_directory, 1);
797 	CHECK_VAL(io.ntcreatex.out.size, 0);
798 	CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
799 	CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
800 	smbcli_unlink(cli->tree, fname);
801 
802 
803 done:
804 	smbcli_close(cli->tree, fnum);
805 	smbcli_unlink(cli->tree, fname);
806 
807 	return ret;
808 }
809 
810 
811 /*
812   test RAW_OPEN_NTTRANS_CREATE
813 */
test_nttrans_create(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)814 static BOOL test_nttrans_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
815 {
816 	union smb_open io;
817 	union smb_fileinfo finfo;
818 	const char *fname = BASEDIR "\\torture_ntcreatex.txt";
819 	const char *dname = BASEDIR "\\torture_ntcreatex.dir";
820 	NTSTATUS status;
821 	int fnum = -1;
822 	BOOL ret = True;
823 	int i;
824 	struct {
825 		uint32_t open_disp;
826 		BOOL with_file;
827 		NTSTATUS correct_status;
828 	} open_funcs[] = {
829 		{ NTCREATEX_DISP_SUPERSEDE, 	True,  NT_STATUS_OK },
830 		{ NTCREATEX_DISP_SUPERSEDE, 	False, NT_STATUS_OK },
831 		{ NTCREATEX_DISP_OPEN, 	        True,  NT_STATUS_OK },
832 		{ NTCREATEX_DISP_OPEN, 	        False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
833 		{ NTCREATEX_DISP_CREATE, 	True,  NT_STATUS_OBJECT_NAME_COLLISION },
834 		{ NTCREATEX_DISP_CREATE, 	False, NT_STATUS_OK },
835 		{ NTCREATEX_DISP_OPEN_IF, 	True,  NT_STATUS_OK },
836 		{ NTCREATEX_DISP_OPEN_IF, 	False, NT_STATUS_OK },
837 		{ NTCREATEX_DISP_OVERWRITE, 	True,  NT_STATUS_OK },
838 		{ NTCREATEX_DISP_OVERWRITE, 	False, NT_STATUS_OBJECT_NAME_NOT_FOUND },
839 		{ NTCREATEX_DISP_OVERWRITE_IF, 	True,  NT_STATUS_OK },
840 		{ NTCREATEX_DISP_OVERWRITE_IF, 	False, NT_STATUS_OK },
841 		{ 6, 			        True,  NT_STATUS_INVALID_PARAMETER },
842 		{ 6, 	                        False, NT_STATUS_INVALID_PARAMETER },
843 	};
844 
845 	printf("Checking RAW_OPEN_NTTRANS_CREATE\n");
846 
847 	/* reasonable default parameters */
848 	io.generic.level = RAW_OPEN_NTTRANS_CREATE;
849 	io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
850 	io.ntcreatex.in.root_fid = 0;
851 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
852 	io.ntcreatex.in.alloc_size = 1024*1024;
853 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
854 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
855 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
856 	io.ntcreatex.in.create_options = 0;
857 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
858 	io.ntcreatex.in.security_flags = 0;
859 	io.ntcreatex.in.fname = fname;
860 	io.ntcreatex.in.sec_desc = NULL;
861 	io.ntcreatex.in.ea_list = NULL;
862 
863 	/* test the open disposition */
864 	for (i=0; i<ARRAY_SIZE(open_funcs); i++) {
865 		if (open_funcs[i].with_file) {
866 			fnum = smbcli_open(cli->tree, fname, O_CREAT|O_RDWR|O_TRUNC, DENY_NONE);
867 			if (fnum == -1) {
868 				d_printf("Failed to create file %s - %s\n", fname, smbcli_errstr(cli->tree));
869 				ret = False;
870 				goto done;
871 			}
872 			smbcli_close(cli->tree, fnum);
873 		}
874 		io.ntcreatex.in.open_disposition = open_funcs[i].open_disp;
875 		status = smb_raw_open(cli->tree, mem_ctx, &io);
876 		if (!NT_STATUS_EQUAL(status, open_funcs[i].correct_status)) {
877 			printf("(%s) incorrect status %s should be %s (i=%d with_file=%d open_disp=%d)\n",
878 			       __location__, nt_errstr(status), nt_errstr(open_funcs[i].correct_status),
879 			       i, (int)open_funcs[i].with_file, (int)open_funcs[i].open_disp);
880 			ret = False;
881 		}
882 		if (NT_STATUS_IS_OK(status) || open_funcs[i].with_file) {
883 			smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
884 			smbcli_unlink(cli->tree, fname);
885 		}
886 	}
887 
888 	/* basic field testing */
889 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
890 
891 	status = smb_raw_open(cli->tree, mem_ctx, &io);
892 	CHECK_STATUS(status, NT_STATUS_OK);
893 	fnum = io.ntcreatex.out.file.fnum;
894 
895 	CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
896 	CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
897 	CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
898 	CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
899 	CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
900 	CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
901 	CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
902 	CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
903 	CHECK_ALL_INFO(io.ntcreatex.out.size, size);
904 	CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
905 	CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
906 
907 	/* check fields when the file already existed */
908 	smbcli_close(cli->tree, fnum);
909 	smbcli_unlink(cli->tree, fname);
910 	fnum = create_complex_file(cli, mem_ctx, fname);
911 	if (fnum == -1) {
912 		ret = False;
913 		goto done;
914 	}
915 	smbcli_close(cli->tree, fnum);
916 
917 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
918 	status = smb_raw_open(cli->tree, mem_ctx, &io);
919 	CHECK_STATUS(status, NT_STATUS_OK);
920 	fnum = io.ntcreatex.out.file.fnum;
921 
922 	CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
923 	CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_EXISTED);
924 	CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
925 	CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
926 	CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
927 	CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
928 	CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
929 	CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
930 	CHECK_ALL_INFO(io.ntcreatex.out.size, size);
931 	CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
932 	CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
933 	smbcli_close(cli->tree, fnum);
934 	smbcli_unlink(cli->tree, fname);
935 
936 
937 	/* create a directory */
938 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
939 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
940 	io.ntcreatex.in.alloc_size = 0;
941 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
942 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
943 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
944 	io.ntcreatex.in.create_options = 0;
945 	io.ntcreatex.in.fname = dname;
946 	fname = dname;
947 
948 	smbcli_rmdir(cli->tree, fname);
949 	smbcli_unlink(cli->tree, fname);
950 
951 	io.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
952 	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
953 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
954 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
955 	status = smb_raw_open(cli->tree, mem_ctx, &io);
956 	CHECK_STATUS(status, NT_STATUS_OK);
957 	fnum = io.ntcreatex.out.file.fnum;
958 
959 	CHECK_VAL(io.ntcreatex.out.oplock_level, 0);
960 	CHECK_VAL(io.ntcreatex.out.create_action, NTCREATEX_ACTION_CREATED);
961 	CHECK_NTTIME(io.ntcreatex.out.create_time, create_time);
962 	CHECK_NTTIME(io.ntcreatex.out.access_time, access_time);
963 	CHECK_NTTIME(io.ntcreatex.out.write_time, write_time);
964 	CHECK_NTTIME(io.ntcreatex.out.change_time, change_time);
965 	CHECK_ALL_INFO(io.ntcreatex.out.attrib, attrib);
966 	CHECK_VAL(io.ntcreatex.out.attrib & ~FILE_ATTRIBUTE_NONINDEXED,
967 		  FILE_ATTRIBUTE_DIRECTORY);
968 	CHECK_ALL_INFO(io.ntcreatex.out.alloc_size, alloc_size);
969 	CHECK_ALL_INFO(io.ntcreatex.out.size, size);
970 	CHECK_ALL_INFO(io.ntcreatex.out.is_directory, directory);
971 	CHECK_VAL(io.ntcreatex.out.is_directory, 1);
972 	CHECK_VAL(io.ntcreatex.out.size, 0);
973 	CHECK_VAL(io.ntcreatex.out.alloc_size, 0);
974 	CHECK_VAL(io.ntcreatex.out.file_type, FILE_TYPE_DISK);
975 	smbcli_unlink(cli->tree, fname);
976 
977 
978 done:
979 	smbcli_close(cli->tree, fnum);
980 	smbcli_unlink(cli->tree, fname);
981 
982 	return ret;
983 }
984 
985 /*
986   test RAW_OPEN_NTCREATEX with an already opened and byte range locked file
987 
988   I've got an application that does a similar sequence of ntcreate&x,
989   locking&x and another ntcreate&x with
990   open_disposition==NTCREATEX_DISP_OVERWRITE_IF. Windows 2003 allows the
991   second open.
992 */
test_ntcreatex_brlocked(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)993 static BOOL test_ntcreatex_brlocked(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
994 {
995 	union smb_open io, io1;
996 	union smb_lock io2;
997 	struct smb_lock_entry lock[1];
998 	const char *fname = BASEDIR "\\torture_ntcreatex.txt";
999 	NTSTATUS status;
1000 	BOOL ret = True;
1001 
1002 	printf("Testing ntcreatex with a byte range locked file\n");
1003 
1004 	io.generic.level = RAW_OPEN_NTCREATEX;
1005 	io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1006 	io.ntcreatex.in.root_fid = 0;
1007 	io.ntcreatex.in.access_mask = 0x2019f;
1008 	io.ntcreatex.in.alloc_size = 0;
1009 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1010 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1011 		NTCREATEX_SHARE_ACCESS_WRITE;
1012 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1013 	io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_NON_DIRECTORY_FILE;
1014 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1015 	io.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1016 		NTCREATEX_SECURITY_ALL;
1017 	io.ntcreatex.in.fname = fname;
1018 
1019 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1020 	CHECK_STATUS(status, NT_STATUS_OK);
1021 
1022 	io2.lockx.level = RAW_LOCK_LOCKX;
1023 	io2.lockx.in.file.fnum = io.ntcreatex.out.file.fnum;
1024 	io2.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1025 	io2.lockx.in.timeout = 0;
1026 	io2.lockx.in.ulock_cnt = 0;
1027 	io2.lockx.in.lock_cnt = 1;
1028 	lock[0].pid = cli->session->pid;
1029 	lock[0].offset = 0;
1030 	lock[0].count = 0x1;
1031 	io2.lockx.in.locks = &lock[0];
1032 	status = smb_raw_lock(cli->tree, &io2);
1033 	CHECK_STATUS(status, NT_STATUS_OK);
1034 
1035 	io1.generic.level = RAW_OPEN_NTCREATEX;
1036 	io1.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1037 	io1.ntcreatex.in.root_fid = 0;
1038 	io1.ntcreatex.in.access_mask = 0x20196;
1039 	io1.ntcreatex.in.alloc_size = 0;
1040 	io1.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1041 	io1.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ |
1042 		NTCREATEX_SHARE_ACCESS_WRITE;
1043 	io1.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
1044 	io1.ntcreatex.in.create_options = 0;
1045 	io1.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION;
1046 	io1.ntcreatex.in.security_flags = NTCREATEX_SECURITY_DYNAMIC |
1047 		NTCREATEX_SECURITY_ALL;
1048 	io1.ntcreatex.in.fname = fname;
1049 
1050 	status = smb_raw_open(cli->tree, mem_ctx, &io1);
1051 	CHECK_STATUS(status, NT_STATUS_OK);
1052 
1053  done:
1054 	smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
1055 	smbcli_close(cli->tree, io1.ntcreatex.out.file.fnum);
1056 	smbcli_unlink(cli->tree, fname);
1057 	return ret;
1058 }
1059 
1060 /*
1061   test RAW_OPEN_MKNEW
1062 */
test_mknew(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1063 static BOOL test_mknew(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1064 {
1065 	union smb_open io;
1066 	const char *fname = BASEDIR "\\torture_mknew.txt";
1067 	NTSTATUS status;
1068 	int fnum = -1;
1069 	BOOL ret = True;
1070 	time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1071 	union smb_fileinfo finfo;
1072 
1073 	printf("Checking RAW_OPEN_MKNEW\n");
1074 
1075 	io.mknew.level = RAW_OPEN_MKNEW;
1076 	io.mknew.in.attrib = 0;
1077 	io.mknew.in.write_time = 0;
1078 	io.mknew.in.fname = fname;
1079 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1080 	CHECK_STATUS(status, NT_STATUS_OK);
1081 	fnum = io.mknew.out.file.fnum;
1082 
1083 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1084 	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
1085 
1086 	smbcli_close(cli->tree, fnum);
1087 	smbcli_unlink(cli->tree, fname);
1088 
1089 	/* make sure write_time works */
1090 	io.mknew.in.write_time = basetime;
1091 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1092 	CHECK_STATUS(status, NT_STATUS_OK);
1093 	fnum = io.mknew.out.file.fnum;
1094 	CHECK_TIME(basetime, write_time);
1095 
1096 	smbcli_close(cli->tree, fnum);
1097 	smbcli_unlink(cli->tree, fname);
1098 
1099 	/* make sure file_attrs works */
1100 	io.mknew.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1101 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1102 	CHECK_STATUS(status, NT_STATUS_OK);
1103 	fnum = io.mknew.out.file.fnum;
1104 	CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE,
1105 		       attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1106 
1107 done:
1108 	smbcli_close(cli->tree, fnum);
1109 	smbcli_unlink(cli->tree, fname);
1110 
1111 	return ret;
1112 }
1113 
1114 
1115 /*
1116   test RAW_OPEN_CREATE
1117 */
test_create(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1118 static BOOL test_create(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1119 {
1120 	union smb_open io;
1121 	const char *fname = BASEDIR "\\torture_create.txt";
1122 	NTSTATUS status;
1123 	int fnum = -1;
1124 	BOOL ret = True;
1125 	time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1126 	union smb_fileinfo finfo;
1127 
1128 	printf("Checking RAW_OPEN_CREATE\n");
1129 
1130 	io.create.level = RAW_OPEN_CREATE;
1131 	io.create.in.attrib = 0;
1132 	io.create.in.write_time = 0;
1133 	io.create.in.fname = fname;
1134 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1135 	CHECK_STATUS(status, NT_STATUS_OK);
1136 	fnum = io.create.out.file.fnum;
1137 
1138 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1139 	CHECK_STATUS(status, NT_STATUS_OK);
1140 
1141 	smbcli_close(cli->tree, io.create.out.file.fnum);
1142 	smbcli_close(cli->tree, fnum);
1143 	smbcli_unlink(cli->tree, fname);
1144 
1145 	/* make sure write_time works */
1146 	io.create.in.write_time = basetime;
1147 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1148 	CHECK_STATUS(status, NT_STATUS_OK);
1149 	fnum = io.create.out.file.fnum;
1150 	CHECK_TIME(basetime, write_time);
1151 
1152 	smbcli_close(cli->tree, fnum);
1153 	smbcli_unlink(cli->tree, fname);
1154 
1155 	/* make sure file_attrs works */
1156 	io.create.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1157 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1158 	CHECK_STATUS(status, NT_STATUS_OK);
1159 	fnum = io.create.out.file.fnum;
1160 	CHECK_ALL_INFO(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_ARCHIVE,
1161 		       attrib & ~FILE_ATTRIBUTE_NONINDEXED);
1162 
1163 done:
1164 	smbcli_close(cli->tree, fnum);
1165 	smbcli_unlink(cli->tree, fname);
1166 
1167 	return ret;
1168 }
1169 
1170 
1171 /*
1172   test RAW_OPEN_CTEMP
1173 */
test_ctemp(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1174 static BOOL test_ctemp(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1175 {
1176 	union smb_open io;
1177 	NTSTATUS status;
1178 	int fnum = -1;
1179 	BOOL ret = True;
1180 	time_t basetime = (time(NULL) + 3600*24*3) & ~1;
1181 	union smb_fileinfo finfo;
1182 	const char *name, *fname = NULL;
1183 
1184 	printf("Checking RAW_OPEN_CTEMP\n");
1185 
1186 	io.ctemp.level = RAW_OPEN_CTEMP;
1187 	io.ctemp.in.attrib = FILE_ATTRIBUTE_HIDDEN;
1188 	io.ctemp.in.write_time = basetime;
1189 	io.ctemp.in.directory = BASEDIR;
1190 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1191 	CHECK_STATUS(status, NT_STATUS_OK);
1192 	fnum = io.ctemp.out.file.fnum;
1193 
1194 	name = io.ctemp.out.name;
1195 
1196 	finfo.generic.level = RAW_FILEINFO_NAME_INFO;
1197 	finfo.generic.in.file.fnum = fnum;
1198 	status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo);
1199 	CHECK_STATUS(status, NT_STATUS_OK);
1200 
1201 	fname = finfo.name_info.out.fname.s;
1202 	d_printf("ctemp name=%s  real name=%s\n", name, fname);
1203 
1204 done:
1205 	smbcli_close(cli->tree, fnum);
1206 	if (fname) {
1207 		smbcli_unlink(cli->tree, fname);
1208 	}
1209 
1210 	return ret;
1211 }
1212 
1213 
1214 /*
1215   test chained RAW_OPEN_OPENX_READX
1216 */
test_chained(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1217 static BOOL test_chained(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1218 {
1219 	union smb_open io;
1220 	const char *fname = BASEDIR "\\torture_chained.txt";
1221 	NTSTATUS status;
1222 	int fnum = -1;
1223 	BOOL ret = True;
1224 	const char *buf = "test";
1225 	char buf2[4];
1226 
1227 	printf("Checking RAW_OPEN_OPENX chained with READX\n");
1228 	smbcli_unlink(cli->tree, fname);
1229 
1230 	fnum = create_complex_file(cli, mem_ctx, fname);
1231 
1232 	smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1233 
1234 	smbcli_close(cli->tree, fnum);
1235 
1236 	io.openxreadx.level = RAW_OPEN_OPENX_READX;
1237 	io.openxreadx.in.fname = fname;
1238 	io.openxreadx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1239 	io.openxreadx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1240 	io.openxreadx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1241 	io.openxreadx.in.search_attrs = 0;
1242 	io.openxreadx.in.file_attrs = 0;
1243 	io.openxreadx.in.write_time = 0;
1244 	io.openxreadx.in.size = 1024*1024;
1245 	io.openxreadx.in.timeout = 0;
1246 
1247 	io.openxreadx.in.offset = 0;
1248 	io.openxreadx.in.mincnt = sizeof(buf);
1249 	io.openxreadx.in.maxcnt = sizeof(buf);
1250 	io.openxreadx.in.remaining = 0;
1251 	io.openxreadx.out.data = (uint8_t *)buf2;
1252 
1253 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1254 	CHECK_STATUS(status, NT_STATUS_OK);
1255 	fnum = io.openxreadx.out.file.fnum;
1256 
1257 	if (memcmp(buf, buf2, sizeof(buf)) != 0) {
1258 		d_printf("wrong data in reply buffer\n");
1259 		ret = False;
1260 	}
1261 
1262 done:
1263 	smbcli_close(cli->tree, fnum);
1264 	smbcli_unlink(cli->tree, fname);
1265 
1266 	return ret;
1267 }
1268 
1269 /*
1270   test RAW_OPEN_OPENX without a leading slash on the path.
1271   NetApp filers are known to fail on this.
1272 
1273 */
test_no_leading_slash(struct smbcli_state * cli,TALLOC_CTX * mem_ctx)1274 static BOOL test_no_leading_slash(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1275 {
1276 	union smb_open io;
1277 	const char *fname = BASEDIR "\\torture_no_leading_slash.txt";
1278 	NTSTATUS status;
1279 	int fnum = -1;
1280 	BOOL ret = True;
1281 	const char *buf = "test";
1282 
1283 	printf("Checking RAW_OPEN_OPENX without leading slash on path\n");
1284 	smbcli_unlink(cli->tree, fname);
1285 
1286         /* Create the file */
1287 	fnum = create_complex_file(cli, mem_ctx, fname);
1288 	smbcli_write(cli->tree, fnum, 0, buf, 0, sizeof(buf));
1289 	smbcli_close(cli->tree, fnum);
1290 
1291         /* Prepare to open the file using path without leading slash */
1292 	io.openx.level = RAW_OPEN_OPENX;
1293 	io.openx.in.fname = fname + 1;
1294 	io.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
1295 	io.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR;
1296 	io.openx.in.open_func = OPENX_OPEN_FUNC_OPEN;
1297 	io.openx.in.search_attrs = 0;
1298 	io.openx.in.file_attrs = 0;
1299 	io.openx.in.write_time = 0;
1300 	io.openx.in.size = 1024*1024;
1301 	io.openx.in.timeout = 0;
1302 
1303 	status = smb_raw_open(cli->tree, mem_ctx, &io);
1304 	CHECK_STATUS(status, NT_STATUS_OK);
1305 	fnum = io.openx.out.file.fnum;
1306 
1307 done:
1308 	smbcli_close(cli->tree, fnum);
1309 	smbcli_unlink(cli->tree, fname);
1310 
1311 	return ret;
1312 }
1313 
1314 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
1315 
test_raw_open_multi(void)1316 static BOOL test_raw_open_multi(void)
1317 {
1318 	struct smbcli_state *cli;
1319 	TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
1320 	const char *fname = "\\test_oplock.dat";
1321 	NTSTATUS status;
1322 	BOOL ret = True;
1323 	union smb_open io;
1324 	struct smbcli_state **clients;
1325 	struct smbcli_request **requests;
1326 	union smb_open *ios;
1327 	const char *host = lp_parm_string(-1, "torture", "host");
1328 	const char *share = lp_parm_string(-1, "torture", "share");
1329 	int i, num_files = 3;
1330 	struct event_context *ev;
1331 	int num_ok = 0;
1332 	int num_collision = 0;
1333 
1334 	ev = event_context_init(mem_ctx);
1335 	clients = talloc_array(mem_ctx, struct smbcli_state *, num_files);
1336 	requests = talloc_array(mem_ctx, struct smbcli_request *, num_files);
1337 	ios = talloc_array(mem_ctx, union smb_open, num_files);
1338 	if ((ev == NULL) || (clients == NULL) || (requests == NULL) ||
1339 	    (ios == NULL)) {
1340 		DEBUG(0, ("talloc failed\n"));
1341 		return False;
1342 	}
1343 
1344 	if (!torture_open_connection_share(mem_ctx, &cli, host, share, ev)) {
1345 		return False;
1346 	}
1347 
1348 	cli->tree->session->transport->options.request_timeout = 60000;
1349 
1350 	for (i=0; i<num_files; i++) {
1351 		if (!torture_open_connection_share(mem_ctx, &(clients[i]),
1352 						   host, share, ev)) {
1353 			DEBUG(0, ("Could not open %d'th connection\n", i));
1354 			return False;
1355 		}
1356 		clients[i]->tree->session->transport->
1357 			options.request_timeout = 60000;
1358 	}
1359 
1360 	/* cleanup */
1361 	smbcli_unlink(cli->tree, fname);
1362 
1363 	/*
1364 	  base ntcreatex parms
1365 	*/
1366 	io.generic.level = RAW_OPEN_NTCREATEX;
1367 	io.ntcreatex.in.root_fid = 0;
1368 	io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1369 	io.ntcreatex.in.alloc_size = 0;
1370 	io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1371 	io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1372 		NTCREATEX_SHARE_ACCESS_WRITE|
1373 		NTCREATEX_SHARE_ACCESS_DELETE;
1374 	io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1375 	io.ntcreatex.in.create_options = 0;
1376 	io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1377 	io.ntcreatex.in.security_flags = 0;
1378 	io.ntcreatex.in.fname = fname;
1379 	io.ntcreatex.in.flags = 0;
1380 
1381 	for (i=0; i<num_files; i++) {
1382 		ios[i] = io;
1383 		requests[i] = smb_raw_open_send(clients[i]->tree, &ios[i]);
1384 		if (requests[i] == NULL) {
1385 			DEBUG(0, ("could not send %d'th request\n", i));
1386 			return False;
1387 		}
1388 	}
1389 
1390 	DEBUG(10, ("waiting for replies\n"));
1391 	while (1) {
1392 		BOOL unreplied = False;
1393 		for (i=0; i<num_files; i++) {
1394 			if (requests[i] == NULL) {
1395 				continue;
1396 			}
1397 			if (requests[i]->state < SMBCLI_REQUEST_DONE) {
1398 				unreplied = True;
1399 				break;
1400 			}
1401 			status = smb_raw_open_recv(requests[i], mem_ctx,
1402 						   &ios[i]);
1403 
1404 			DEBUG(0, ("File %d returned status %s\n", i,
1405 				  nt_errstr(status)));
1406 
1407 			if (NT_STATUS_IS_OK(status)) {
1408 				num_ok += 1;
1409 			}
1410 
1411 			if (NT_STATUS_EQUAL(status,
1412 					    NT_STATUS_OBJECT_NAME_COLLISION)) {
1413 				num_collision += 1;
1414 			}
1415 
1416 			requests[i] = NULL;
1417 		}
1418 		if (!unreplied) {
1419 			break;
1420 		}
1421 
1422 		if (event_loop_once(ev) != 0) {
1423 			DEBUG(0, ("event_loop_once failed\n"));
1424 			return False;
1425 		}
1426 	}
1427 
1428 	if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1429 		ret = False;
1430 	}
1431 
1432 	for (i=0; i<num_files; i++) {
1433 		torture_close_connection(clients[i]);
1434 	}
1435 	talloc_free(mem_ctx);
1436 	return ret;
1437 }
1438 
1439 /* basic testing of all RAW_OPEN_* calls
1440 */
torture_raw_open(struct torture_context * torture)1441 BOOL torture_raw_open(struct torture_context *torture)
1442 {
1443 	struct smbcli_state *cli;
1444 	BOOL ret = True;
1445 	TALLOC_CTX *mem_ctx;
1446 
1447 	if (!torture_open_connection(&cli, 0)) {
1448 		return False;
1449 	}
1450 
1451 	mem_ctx = talloc_init("torture_raw_open");
1452 
1453 	if (!torture_setup_dir(cli, BASEDIR)) {
1454 		return False;
1455 	}
1456 
1457 	ret &= test_ntcreatex_brlocked(cli, mem_ctx);
1458 	ret &= test_open(cli, mem_ctx);
1459 	ret &= test_raw_open_multi();
1460 	ret &= test_openx(cli, mem_ctx);
1461 	ret &= test_ntcreatex(cli, mem_ctx);
1462 	ret &= test_nttrans_create(cli, mem_ctx);
1463 	ret &= test_t2open(cli, mem_ctx);
1464 	ret &= test_mknew(cli, mem_ctx);
1465 	ret &= test_create(cli, mem_ctx);
1466 	ret &= test_ctemp(cli, mem_ctx);
1467 	ret &= test_chained(cli, mem_ctx);
1468 	ret &= test_no_leading_slash(cli, mem_ctx);
1469 
1470 	smb_raw_exit(cli->session);
1471 	smbcli_deltree(cli->tree, BASEDIR);
1472 
1473 	torture_close_connection(cli);
1474 	talloc_free(mem_ctx);
1475 	return ret;
1476 }
1477