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