r16907: Add an index parameter to torture_open_connection. Next step is to enable the
[jelmer/samba4-debian.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 "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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 /* A little torture test to expose a race condition in Samba 3.0.20 ... :-) */
1270
1271 static BOOL test_raw_open_multi(void)
1272 {
1273         struct smbcli_state *cli;
1274         TALLOC_CTX *mem_ctx = talloc_init("torture_test_oplock_multi");
1275         const char *fname = "\\test_oplock.dat";
1276         NTSTATUS status;
1277         BOOL ret = True;
1278         union smb_open io;
1279         struct smbcli_state **clients;
1280         struct smbcli_request **requests;
1281         union smb_open *ios;
1282         const char *host = lp_parm_string(-1, "torture", "host");
1283         const char *share = lp_parm_string(-1, "torture", "share");
1284         int i, num_files = 3;
1285         struct event_context *ev;
1286         int num_ok = 0;
1287         int num_collision = 0;
1288         
1289         ev = event_context_init(mem_ctx);
1290         clients = talloc_array(mem_ctx, struct smbcli_state *, num_files);
1291         requests = talloc_array(mem_ctx, struct smbcli_request *, num_files);
1292         ios = talloc_array(mem_ctx, union smb_open, num_files);
1293         if ((ev == NULL) || (clients == NULL) || (requests == NULL) ||
1294             (ios == NULL)) {
1295                 DEBUG(0, ("talloc failed\n"));
1296                 return False;
1297         }
1298
1299         if (!torture_open_connection_share(mem_ctx, &cli, host, share, ev)) {
1300                 return False;
1301         }
1302
1303         cli->tree->session->transport->options.request_timeout = 60000;
1304
1305         for (i=0; i<num_files; i++) {
1306                 if (!torture_open_connection_share(mem_ctx, &(clients[i]),
1307                                                    host, share, ev)) {
1308                         DEBUG(0, ("Could not open %d'th connection\n", i));
1309                         return False;
1310                 }
1311                 clients[i]->tree->session->transport->
1312                         options.request_timeout = 60000;
1313         }
1314
1315         /* cleanup */
1316         smbcli_unlink(cli->tree, fname);
1317
1318         /*
1319           base ntcreatex parms
1320         */
1321         io.generic.level = RAW_OPEN_NTCREATEX;
1322         io.ntcreatex.in.root_fid = 0;
1323         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1324         io.ntcreatex.in.alloc_size = 0;
1325         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1326         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1327                 NTCREATEX_SHARE_ACCESS_WRITE|
1328                 NTCREATEX_SHARE_ACCESS_DELETE;
1329         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1330         io.ntcreatex.in.create_options = 0;
1331         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1332         io.ntcreatex.in.security_flags = 0;
1333         io.ntcreatex.in.fname = fname;
1334         io.ntcreatex.in.flags = 0;
1335
1336         for (i=0; i<num_files; i++) {
1337                 ios[i] = io;
1338                 requests[i] = smb_raw_open_send(clients[i]->tree, &ios[i]);
1339                 if (requests[i] == NULL) {
1340                         DEBUG(0, ("could not send %d'th request\n", i));
1341                         return False;
1342                 }
1343         }
1344
1345         DEBUG(10, ("waiting for replies\n"));
1346         while (1) {
1347                 BOOL unreplied = False;
1348                 for (i=0; i<num_files; i++) {
1349                         if (requests[i] == NULL) {
1350                                 continue;
1351                         }
1352                         if (requests[i]->state < SMBCLI_REQUEST_DONE) {
1353                                 unreplied = True;
1354                                 break;
1355                         }
1356                         status = smb_raw_open_recv(requests[i], mem_ctx,
1357                                                    &ios[i]);
1358
1359                         DEBUG(0, ("File %d returned status %s\n", i,
1360                                   nt_errstr(status)));
1361
1362                         if (NT_STATUS_IS_OK(status)) {
1363                                 num_ok += 1;
1364                         } 
1365
1366                         if (NT_STATUS_EQUAL(status,
1367                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
1368                                 num_collision += 1;
1369                         }
1370
1371                         requests[i] = NULL;
1372                 }
1373                 if (!unreplied) {
1374                         break;
1375                 }
1376
1377                 if (event_loop_once(ev) != 0) {
1378                         DEBUG(0, ("event_loop_once failed\n"));
1379                         return False;
1380                 }
1381         }
1382
1383         if ((num_ok != 1) || (num_ok + num_collision != num_files)) {
1384                 ret = False;
1385         }
1386
1387         for (i=0; i<num_files; i++) {
1388                 torture_close_connection(clients[i]);
1389         }
1390         talloc_free(mem_ctx);
1391         return ret;
1392 }
1393
1394 /* basic testing of all RAW_OPEN_* calls 
1395 */
1396 BOOL torture_raw_open(struct torture_context *torture)
1397 {
1398         struct smbcli_state *cli;
1399         BOOL ret = True;
1400         TALLOC_CTX *mem_ctx;
1401
1402         if (!torture_open_connection(&cli, 0)) {
1403                 return False;
1404         }
1405
1406         mem_ctx = talloc_init("torture_raw_open");
1407
1408         if (!torture_setup_dir(cli, BASEDIR)) {
1409                 return False;
1410         }
1411
1412         ret &= test_ntcreatex_brlocked(cli, mem_ctx);
1413         ret &= test_open(cli, mem_ctx);
1414         ret &= test_raw_open_multi();
1415         ret &= test_openx(cli, mem_ctx);
1416         ret &= test_ntcreatex(cli, mem_ctx);
1417         ret &= test_nttrans_create(cli, mem_ctx);
1418         ret &= test_t2open(cli, mem_ctx);
1419         ret &= test_mknew(cli, mem_ctx);
1420         ret &= test_create(cli, mem_ctx);
1421         ret &= test_ctemp(cli, mem_ctx);
1422         ret &= test_chained(cli, mem_ctx);
1423
1424         smb_raw_exit(cli->session);
1425         smbcli_deltree(cli->tree, BASEDIR);
1426
1427         torture_close_connection(cli);
1428         talloc_free(mem_ctx);
1429         return ret;
1430 }