r24872: Use torture API a bit more
[kai/samba.git] / source4 / torture / raw / samba3misc.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Test some misc Samba3 code paths
4    Copyright (C) Volker Lendecke 2006
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 "system/time.h"
24 #include "system/filesys.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
27 #include "lib/events/events.h"
28
29 #define CHECK_STATUS(status, correct) do { \
30         if (!NT_STATUS_EQUAL(status, correct)) { \
31                 printf("(%s) Incorrect status %s - should be %s\n", \
32                        __location__, nt_errstr(status), nt_errstr(correct)); \
33                 ret = False; \
34         } \
35 } while (0)
36
37 BOOL torture_samba3_checkfsp(struct torture_context *torture)
38 {
39         struct smbcli_state *cli;
40         const char *fname = "test.txt";
41         const char *dirname = "testdir";
42         int fnum;
43         NTSTATUS status;
44         BOOL ret = True;
45         TALLOC_CTX *mem_ctx;
46         ssize_t nread;
47         char buf[16];
48         struct smbcli_tree *tree2;
49
50         if ((mem_ctx = talloc_init("torture_samba3_checkfsp")) == NULL) {
51                 d_printf("talloc_init failed\n");
52                 return False;
53         }
54
55         if (!torture_open_connection_share(
56                     torture, &cli, torture_setting_string(torture, "host", NULL),
57                     torture_setting_string(torture, "share", NULL), NULL)) {
58                 d_printf("torture_open_connection_share failed\n");
59                 ret = False;
60                 goto done;
61         }
62
63         smbcli_deltree(cli->tree, dirname);
64
65         status = torture_second_tcon(torture, cli->session,
66                                      torture_setting_string(torture, "share", NULL),
67                                      &tree2);
68         CHECK_STATUS(status, NT_STATUS_OK);
69         if (!NT_STATUS_IS_OK(status))
70                 goto done;
71
72         /* Try a read on an invalid FID */
73
74         nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
75         CHECK_STATUS(smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);
76
77         /* Try a read on a directory handle */
78
79         status = smbcli_mkdir(cli->tree, dirname);
80         if (!NT_STATUS_IS_OK(status)) {
81                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
82                 ret = False;
83                 goto done;
84         }
85
86         /* Open the directory */
87         {
88                 union smb_open io;
89                 io.generic.level = RAW_OPEN_NTCREATEX;
90                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
91                 io.ntcreatex.in.root_fid = 0;
92                 io.ntcreatex.in.security_flags = 0;
93                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
94                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
95                 io.ntcreatex.in.alloc_size = 0;
96                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
97                 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
98                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
99                 io.ntcreatex.in.create_options = 0;
100                 io.ntcreatex.in.fname = dirname;
101                 status = smb_raw_open(cli->tree, mem_ctx, &io);
102                 if (!NT_STATUS_IS_OK(status)) {
103                         d_printf("smb_open on the directory failed: %s\n",
104                                  nt_errstr(status));
105                         ret = False;
106                         goto done;
107                 }
108                 fnum = io.ntcreatex.out.file.fnum;
109         }
110
111         /* Try a read on the directory */
112
113         nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
114         if (nread >= 0) {
115                 d_printf("smbcli_read on a directory succeeded, expected "
116                          "failure\n");
117                 ret = False;
118         }
119
120         CHECK_STATUS(smbcli_nt_error(cli->tree),
121                      NT_STATUS_INVALID_DEVICE_REQUEST);
122
123         /* Same test on the second tcon */
124
125         nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
126         if (nread >= 0) {
127                 d_printf("smbcli_read on a directory succeeded, expected "
128                          "failure\n");
129                 ret = False;
130         }
131
132         CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
133
134         smbcli_close(cli->tree, fnum);
135
136         /* Try a normal file read on a second tcon */
137
138         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
139         if (fnum == -1) {
140                 d_printf("Failed to create %s - %s\n", fname,
141                          smbcli_errstr(cli->tree));
142                 ret = False;
143                 goto done;
144         }
145
146         nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
147         CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
148
149         smbcli_close(cli->tree, fnum);
150
151  done:
152         smbcli_deltree(cli->tree, dirname);
153         torture_close_connection(cli);
154         talloc_free(mem_ctx);
155
156         return ret;
157 }
158
159 static NTSTATUS raw_smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
160 {
161         union smb_open open_parms;
162         uint_t openfn=0;
163         uint_t accessmode=0;
164         TALLOC_CTX *mem_ctx;
165         NTSTATUS status;
166
167         mem_ctx = talloc_init("raw_open");
168         if (!mem_ctx) return NT_STATUS_NO_MEMORY;
169
170         if (flags & O_CREAT) {
171                 openfn |= OPENX_OPEN_FUNC_CREATE;
172         }
173         if (!(flags & O_EXCL)) {
174                 if (flags & O_TRUNC) {
175                         openfn |= OPENX_OPEN_FUNC_TRUNC;
176                 } else {
177                         openfn |= OPENX_OPEN_FUNC_OPEN;
178                 }
179         }
180
181         accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
182
183         if ((flags & O_ACCMODE) == O_RDWR) {
184                 accessmode |= OPENX_MODE_ACCESS_RDWR;
185         } else if ((flags & O_ACCMODE) == O_WRONLY) {
186                 accessmode |= OPENX_MODE_ACCESS_WRITE;
187         } else if ((flags & O_ACCMODE) == O_RDONLY) {
188                 accessmode |= OPENX_MODE_ACCESS_READ;
189         }
190
191 #if defined(O_SYNC)
192         if ((flags & O_SYNC) == O_SYNC) {
193                 accessmode |= OPENX_MODE_WRITE_THRU;
194         }
195 #endif
196
197         if (share_mode == DENY_FCB) {
198                 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
199         }
200
201         open_parms.openx.level = RAW_OPEN_OPENX;
202         open_parms.openx.in.flags = 0;
203         open_parms.openx.in.open_mode = accessmode;
204         open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
205         open_parms.openx.in.file_attrs = 0;
206         open_parms.openx.in.write_time = 0;
207         open_parms.openx.in.open_func = openfn;
208         open_parms.openx.in.size = 0;
209         open_parms.openx.in.timeout = 0;
210         open_parms.openx.in.fname = fname;
211
212         status = smb_raw_open(tree, mem_ctx, &open_parms);
213         talloc_free(mem_ctx);
214
215         if (fnum && NT_STATUS_IS_OK(status)) {
216                 *fnum = open_parms.openx.out.file.fnum;
217         }
218
219         return status;
220 }
221
222 static NTSTATUS raw_smbcli_t2open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
223 {
224         union smb_open io;
225         uint_t openfn=0;
226         uint_t accessmode=0;
227         TALLOC_CTX *mem_ctx;
228         NTSTATUS status;
229
230         mem_ctx = talloc_init("raw_t2open");
231         if (!mem_ctx) return NT_STATUS_NO_MEMORY;
232
233         if (flags & O_CREAT) {
234                 openfn |= OPENX_OPEN_FUNC_CREATE;
235         }
236         if (!(flags & O_EXCL)) {
237                 if (flags & O_TRUNC) {
238                         openfn |= OPENX_OPEN_FUNC_TRUNC;
239                 } else {
240                         openfn |= OPENX_OPEN_FUNC_OPEN;
241                 }
242         }
243
244         accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
245
246         if ((flags & O_ACCMODE) == O_RDWR) {
247                 accessmode |= OPENX_MODE_ACCESS_RDWR;
248         } else if ((flags & O_ACCMODE) == O_WRONLY) {
249                 accessmode |= OPENX_MODE_ACCESS_WRITE;
250         } else if ((flags & O_ACCMODE) == O_RDONLY) {
251                 accessmode |= OPENX_MODE_ACCESS_READ;
252         }
253
254 #if defined(O_SYNC)
255         if ((flags & O_SYNC) == O_SYNC) {
256                 accessmode |= OPENX_MODE_WRITE_THRU;
257         }
258 #endif
259
260         if (share_mode == DENY_FCB) {
261                 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
262         }
263
264         memset(&io, '\0', sizeof(io));
265         io.t2open.level = RAW_OPEN_T2OPEN;
266         io.t2open.in.flags = 0;
267         io.t2open.in.open_mode = accessmode;
268         io.t2open.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
269         io.t2open.in.file_attrs = 0;
270         io.t2open.in.write_time = 0;
271         io.t2open.in.open_func = openfn;
272         io.t2open.in.size = 0;
273         io.t2open.in.timeout = 0;
274         io.t2open.in.fname = fname;
275
276         io.t2open.in.num_eas = 1;
277         io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
278         io.t2open.in.eas[0].flags = 0;
279         io.t2open.in.eas[0].name.s = ".CLASSINFO";
280         io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
281
282         status = smb_raw_open(tree, mem_ctx, &io);
283         talloc_free(mem_ctx);
284
285         if (fnum && NT_STATUS_IS_OK(status)) {
286                 *fnum = io.openx.out.file.fnum;
287         }
288
289         return status;
290 }
291
292 static NTSTATUS raw_smbcli_ntcreate(struct smbcli_tree *tree, const char *fname, int *fnum)
293 {
294         union smb_open io;
295         TALLOC_CTX *mem_ctx;
296         NTSTATUS status;
297
298         mem_ctx = talloc_init("raw_t2open");
299         if (!mem_ctx) return NT_STATUS_NO_MEMORY;
300
301         memset(&io, '\0', sizeof(io));
302         io.generic.level = RAW_OPEN_NTCREATEX;
303         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
304         io.ntcreatex.in.root_fid = 0;
305         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
306         io.ntcreatex.in.alloc_size = 0;
307         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
308         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
309         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
310         io.ntcreatex.in.create_options = 0;
311         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
312         io.ntcreatex.in.security_flags = 0;
313         io.ntcreatex.in.fname = fname;
314
315         status = smb_raw_open(tree, mem_ctx, &io);
316         talloc_free(mem_ctx);
317
318         if (fnum && NT_STATUS_IS_OK(status)) {
319                 *fnum = io.openx.out.file.fnum;
320         }
321
322         return status;
323 }
324
325
326 BOOL torture_samba3_badpath(struct torture_context *torture)
327 {
328         struct smbcli_state *cli_nt;
329         struct smbcli_state *cli_dos;
330         const char *fname = "test.txt";
331         const char *fname1 = "test1.txt";
332         const char *dirname = "testdir";
333         char *fpath;
334         char *fpath1;
335         int fnum;
336         NTSTATUS status;
337         BOOL ret = True;
338         TALLOC_CTX *mem_ctx;
339         BOOL nt_status_support;
340
341         if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) {
342                 d_printf("talloc_init failed\n");
343                 return False;
344         }
345
346         nt_status_support = lp_nt_status_support();
347
348         if (!lp_set_cmdline("nt status support", "yes")) {
349                 printf("Could not set 'nt status support = yes'\n");
350                 goto fail;
351         }
352
353         if (!torture_open_connection(&cli_nt, 0)) {
354                 goto fail;
355         }
356
357         if (!lp_set_cmdline("nt status support", "no")) {
358                 printf("Could not set 'nt status support = yes'\n");
359                 goto fail;
360         }
361
362         if (!torture_open_connection(&cli_dos, 1)) {
363                 goto fail;
364         }
365
366         if (!lp_set_cmdline("nt status support",
367                             nt_status_support ? "yes":"no")) {
368                 printf("Could not reset 'nt status support = yes'");
369                 goto fail;
370         }
371
372         smbcli_deltree(cli_nt->tree, dirname);
373
374         status = smbcli_mkdir(cli_nt->tree, dirname);
375         if (!NT_STATUS_IS_OK(status)) {
376                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
377                 ret = False;
378                 goto done;
379         }
380
381         status = smbcli_chkpath(cli_nt->tree, dirname);
382         CHECK_STATUS(status, NT_STATUS_OK);
383
384         status = smbcli_chkpath(cli_nt->tree,
385                                 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
386         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
387
388         status = smbcli_chkpath(cli_dos->tree,
389                                 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
390         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
391
392         status = smbcli_chkpath(cli_nt->tree,
393                                 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
394                                                 dirname));
395         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
396         status = smbcli_chkpath(cli_dos->tree,
397                                 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
398                                                 dirname));
399         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
400
401         if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
402                 goto fail;
403         }
404         fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
405         if (fnum == -1) {
406                 d_printf("Could not create file %s: %s\n", fpath,
407                          smbcli_errstr(cli_nt->tree));
408                 goto fail;
409         }
410         smbcli_close(cli_nt->tree, fnum);
411
412         if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
413                 goto fail;
414         }
415         fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
416         if (fnum == -1) {
417                 d_printf("Could not create file %s: %s\n", fpath1,
418                          smbcli_errstr(cli_nt->tree));
419                 goto fail;
420         }
421         smbcli_close(cli_nt->tree, fnum);
422
423         /*
424          * Do a whole bunch of error code checks on chkpath
425          */
426
427         status = smbcli_chkpath(cli_nt->tree, fpath);
428         CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
429         status = smbcli_chkpath(cli_dos->tree, fpath);
430         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
431
432         status = smbcli_chkpath(cli_nt->tree, "..");
433         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
434         status = smbcli_chkpath(cli_dos->tree, "..");
435         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
436
437         status = smbcli_chkpath(cli_nt->tree, ".");
438         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
439         status = smbcli_chkpath(cli_dos->tree, ".");
440         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
441
442         status = smbcli_chkpath(cli_nt->tree, "\t");
443         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
444         status = smbcli_chkpath(cli_dos->tree, "\t");
445         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
446
447         status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
448         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
449         status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
450         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
451
452         status = smbcli_chkpath(cli_nt->tree, "<");
453         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
454         status = smbcli_chkpath(cli_dos->tree, "<");
455         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
456
457         status = smbcli_chkpath(cli_nt->tree, "<\\bla");
458         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
459         status = smbcli_chkpath(cli_dos->tree, "<\\bla");
460         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
461
462         /*
463          * .... And the same gang against getatr. Note that the DOS error codes
464          * differ....
465          */
466
467         status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
468         CHECK_STATUS(status, NT_STATUS_OK);
469         status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
470         CHECK_STATUS(status, NT_STATUS_OK);
471
472         status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
473         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
474         status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
475         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
476
477         status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
478         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
479         status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
480         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
481
482         status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
483         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
484         status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
485         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
486
487         status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
488         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
489         status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
490         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
491
492         status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
493         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
494         status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
495         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
496
497         status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
498         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
499         status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
500         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
501
502         /* Try the same set with openX. */
503
504         status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
505         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
506         status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
507         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
508
509         status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
510         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
511         status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
512         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
513
514         status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
515         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
516         status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
517         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
518
519         status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
520         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
521         status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
522         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
523
524         status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
525         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
526         status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
527         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
528
529         status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
530         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
531         status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
532         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
533
534         /* Let's test EEXIST error code mapping. */
535         status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
536         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
537         status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
538         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
539
540         status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
541         if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
542             || !torture_setting_bool(torture, "samba3", false)) {
543                 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
544                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
545         }
546         status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
547         if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
548             || !torture_setting_bool(torture, "samba3", false)) {
549                 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
550                 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
551         }
552
553         status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
554         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
555         status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
556         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
557
558         /* Try the rename test. */
559         {
560                 union smb_rename io;
561                 memset(&io, '\0', sizeof(io));
562                 io.rename.in.pattern1 = fpath1;
563                 io.rename.in.pattern2 = fpath;
564
565                 /* Try with SMBmv rename. */
566                 status = smb_raw_rename(cli_nt->tree, &io);
567                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
568                 status = smb_raw_rename(cli_dos->tree, &io);
569                 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
570
571                 /* Try with NT rename. */
572                 io.generic.level = RAW_RENAME_NTRENAME;
573                 io.ntrename.in.old_name = fpath1;
574                 io.ntrename.in.new_name = fpath;
575                 io.ntrename.in.attrib = 0;
576                 io.ntrename.in.cluster_size = 0;
577                 io.ntrename.in.flags = RENAME_FLAG_RENAME;
578
579                 status = smb_raw_rename(cli_nt->tree, &io);
580                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
581                 status = smb_raw_rename(cli_dos->tree, &io);
582                 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
583         }
584
585         goto done;
586
587  fail:
588         ret = False;
589
590  done:
591         if (cli_nt != NULL) {
592                 smbcli_deltree(cli_nt->tree, dirname);
593                 torture_close_connection(cli_nt);
594         }
595         if (cli_dos != NULL) {
596                 torture_close_connection(cli_dos);
597         }
598         talloc_free(mem_ctx);
599
600         return ret;
601 }
602
603 static void count_fn(struct clilist_file_info *info, const char *name,
604                      void *private_data)
605 {
606         int *counter = (int *)private_data;
607         *counter += 1;
608 }
609
610 BOOL torture_samba3_caseinsensitive(struct torture_context *torture)
611 {
612         struct smbcli_state *cli;
613         TALLOC_CTX *mem_ctx;
614         NTSTATUS status;
615         const char *dirname = "insensitive";
616         const char *ucase_dirname = "InSeNsItIvE";
617         const char *fname = "foo";
618         char *fpath;
619         int fnum;
620         int counter = 0;
621         BOOL ret = True;
622
623         if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
624                 d_printf("talloc_init failed\n");
625                 return False;
626         }
627
628         if (!torture_open_connection(&cli, 0)) {
629                 goto done;
630         }
631
632         smbcli_deltree(cli->tree, dirname);
633
634         status = smbcli_mkdir(cli->tree, dirname);
635         if (!NT_STATUS_IS_OK(status)) {
636                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
637                 goto done;
638         }
639
640         if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
641                 goto done;
642         }
643         fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
644         if (fnum == -1) {
645                 d_printf("Could not create file %s: %s\n", fpath,
646                          smbcli_errstr(cli->tree));
647                 goto done;
648         }
649         smbcli_close(cli->tree, fnum);
650
651         smbcli_list(cli->tree, talloc_asprintf(
652                             mem_ctx, "%s\\*", ucase_dirname),
653                     FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN
654                     |FILE_ATTRIBUTE_SYSTEM,
655                     count_fn, (void *)&counter);
656
657         if (counter == 3) {
658                 ret = True;
659         }
660         else {
661                 d_fprintf(stderr, "expected 3 entries, got %d\n", counter);
662                 ret = False;
663         }
664
665  done:
666         talloc_free(mem_ctx);
667         return ret;
668 }
669
670 /*
671  * Check that Samba3 correctly deals with conflicting posix byte range locks
672  * on an underlying file
673  */
674
675 BOOL torture_samba3_posixtimedlock(struct torture_context *tctx)
676 {
677         struct smbcli_state *cli;
678         NTSTATUS status;
679         BOOL ret = True;
680         const char *dirname = "posixlock";
681         const char *fname = "locked";
682         const char *fpath;
683         const char *localdir;
684         const char *localname;
685         int fnum = -1;
686
687         int fd = -1;
688         struct flock posix_lock;
689
690         union smb_lock io;
691         struct smb_lock_entry lock_entry;
692         struct smbcli_request *req;
693
694         if (!torture_open_connection(&cli, 0)) {
695                 ret = False;
696                 goto done;
697         }
698
699         smbcli_deltree(cli->tree, dirname);
700
701         status = smbcli_mkdir(cli->tree, dirname);
702         if (!NT_STATUS_IS_OK(status)) {
703                 torture_warning(tctx, "smbcli_mkdir failed: %s\n",
704                                 nt_errstr(status));
705                 ret = False;
706                 goto done;
707         }
708
709         if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) {
710                 torture_warning(tctx, "talloc failed\n");
711                 ret = False;
712                 goto done;
713         }
714         fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
715         if (fnum == -1) {
716                 torture_warning(tctx, "Could not create file %s: %s\n", fpath,
717                                 smbcli_errstr(cli->tree));
718                 ret = False;
719                 goto done;
720         }
721
722         if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) {
723                 torture_warning(tctx, "Need 'localdir' setting\n");
724                 ret = False;
725                 goto done;
726         }
727
728         if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname,
729                                           fname))) {
730                 torture_warning(tctx, "talloc failed\n");
731                 ret = False;
732                 goto done;
733         }
734
735         /*
736          * Lock a byte range from posix
737          */
738
739         fd = open(localname, O_RDWR);
740         if (fd == -1) {
741                 torture_warning(tctx, "open(%s) failed: %s\n",
742                                 localname, strerror(errno));
743                 goto done;
744         }
745
746         posix_lock.l_type = F_WRLCK;
747         posix_lock.l_whence = SEEK_SET;
748         posix_lock.l_start = 0;
749         posix_lock.l_len = 1;
750
751         if (fcntl(fd, F_SETLK, &posix_lock) == -1) {
752                 torture_warning(tctx, "fcntl failed: %s\n", strerror(errno));
753                 ret = False;
754                 goto done;
755         }
756
757         /*
758          * Try a cifs brlock without timeout to see if posix locking = yes
759          */
760
761         io.lockx.in.ulock_cnt = 0;
762         io.lockx.in.lock_cnt = 1;
763
764         lock_entry.count = 1;
765         lock_entry.offset = 0;
766         lock_entry.pid = cli->tree->session->pid;
767
768         io.lockx.level = RAW_LOCK_LOCKX;
769         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
770         io.lockx.in.timeout = 0;
771         io.lockx.in.locks = &lock_entry;
772         io.lockx.in.file.fnum = fnum;
773
774         status = smb_raw_lock(cli->tree, &io);
775
776         ret = True;
777         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
778
779         if (!ret) {
780                 goto done;
781         }
782
783         /*
784          * Now fire off a timed brlock, unlock the posix lock and see if the
785          * timed lock gets through.
786          */
787
788         io.lockx.in.timeout = 5000;
789
790         req = smb_raw_lock_send(cli->tree, &io);
791         if (req == NULL) {
792                 torture_warning(tctx, "smb_raw_lock_send failed\n");
793                 ret = False;
794                 goto done;
795         }
796
797         /*
798          * Ship the async timed request to the server
799          */
800         event_loop_once(req->transport->socket->event.ctx);
801         msleep(500);
802
803         close(fd);
804
805         status = smbcli_request_simple_recv(req);
806
807         CHECK_STATUS(status, NT_STATUS_OK);
808
809  done:
810         if (fnum != -1) {
811                 smbcli_close(cli->tree, fnum);
812         }
813         if (fd != -1) {
814                 close(fd);
815         }
816         smbcli_deltree(cli->tree, dirname);
817         return ret;
818 }