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