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