r24728: Use more stock torture functions.
[ira/wip.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
28 #define CHECK_STATUS(status, correct) do { \
29         if (!NT_STATUS_EQUAL(status, correct)) { \
30                 printf("(%s) Incorrect status %s - should be %s\n", \
31                        __location__, nt_errstr(status), nt_errstr(correct)); \
32                 ret = False; \
33         } \
34 } while (0)
35
36 BOOL torture_samba3_checkfsp(struct torture_context *torture)
37 {
38         struct smbcli_state *cli;
39         const char *fname = "test.txt";
40         const char *dirname = "testdir";
41         int fnum;
42         NTSTATUS status;
43         BOOL ret = True;
44         TALLOC_CTX *mem_ctx;
45         ssize_t nread;
46         char buf[16];
47         struct smbcli_tree *tree2;
48
49         if ((mem_ctx = talloc_init("torture_samba3_checkfsp")) == NULL) {
50                 d_printf("talloc_init failed\n");
51                 return False;
52         }
53
54         if (!torture_open_connection_share(
55                     torture, &cli, torture_setting_string(torture, "host", NULL),
56                     torture_setting_string(torture, "share", NULL), NULL)) {
57                 d_printf("torture_open_connection_share failed\n");
58                 ret = False;
59                 goto done;
60         }
61
62         smbcli_deltree(cli->tree, dirname);
63
64         status = torture_second_tcon(torture, cli->session,
65                                      torture_setting_string(torture, "share", NULL),
66                                      &tree2);
67         CHECK_STATUS(status, NT_STATUS_OK);
68         if (!NT_STATUS_IS_OK(status))
69                 goto done;
70
71         /* Try a read on an invalid FID */
72
73         nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
74         CHECK_STATUS(smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);
75
76         /* Try a read on a directory handle */
77
78         status = smbcli_mkdir(cli->tree, dirname);
79         if (!NT_STATUS_IS_OK(status)) {
80                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
81                 ret = False;
82                 goto done;
83         }
84
85         /* Open the directory */
86         {
87                 union smb_open io;
88                 io.generic.level = RAW_OPEN_NTCREATEX;
89                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
90                 io.ntcreatex.in.root_fid = 0;
91                 io.ntcreatex.in.security_flags = 0;
92                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
93                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
94                 io.ntcreatex.in.alloc_size = 0;
95                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
96                 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
97                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
98                 io.ntcreatex.in.create_options = 0;
99                 io.ntcreatex.in.fname = dirname;
100                 status = smb_raw_open(cli->tree, mem_ctx, &io);
101                 if (!NT_STATUS_IS_OK(status)) {
102                         d_printf("smb_open on the directory failed: %s\n",
103                                  nt_errstr(status));
104                         ret = False;
105                         goto done;
106                 }
107                 fnum = io.ntcreatex.out.file.fnum;
108         }
109
110         /* Try a read on the directory */
111
112         nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
113         if (nread >= 0) {
114                 d_printf("smbcli_read on a directory succeeded, expected "
115                          "failure\n");
116                 ret = False;
117         }
118
119         CHECK_STATUS(smbcli_nt_error(cli->tree),
120                      NT_STATUS_INVALID_DEVICE_REQUEST);
121
122         /* Same test on the second tcon */
123
124         nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
125         if (nread >= 0) {
126                 d_printf("smbcli_read on a directory succeeded, expected "
127                          "failure\n");
128                 ret = False;
129         }
130
131         CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
132
133         smbcli_close(cli->tree, fnum);
134
135         /* Try a normal file read on a second tcon */
136
137         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
138         if (fnum == -1) {
139                 d_printf("Failed to create %s - %s\n", fname,
140                          smbcli_errstr(cli->tree));
141                 ret = False;
142                 goto done;
143         }
144
145         nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
146         CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
147
148         smbcli_close(cli->tree, fnum);
149
150  done:
151         smbcli_deltree(cli->tree, dirname);
152         torture_close_connection(cli);
153         talloc_free(mem_ctx);
154
155         return ret;
156 }
157
158 static NTSTATUS raw_smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
159 {
160         union smb_open open_parms;
161         uint_t openfn=0;
162         uint_t accessmode=0;
163         TALLOC_CTX *mem_ctx;
164         NTSTATUS status;
165
166         mem_ctx = talloc_init("raw_open");
167         if (!mem_ctx) return NT_STATUS_NO_MEMORY;
168
169         if (flags & O_CREAT) {
170                 openfn |= OPENX_OPEN_FUNC_CREATE;
171         }
172         if (!(flags & O_EXCL)) {
173                 if (flags & O_TRUNC) {
174                         openfn |= OPENX_OPEN_FUNC_TRUNC;
175                 } else {
176                         openfn |= OPENX_OPEN_FUNC_OPEN;
177                 }
178         }
179
180         accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
181
182         if ((flags & O_ACCMODE) == O_RDWR) {
183                 accessmode |= OPENX_MODE_ACCESS_RDWR;
184         } else if ((flags & O_ACCMODE) == O_WRONLY) {
185                 accessmode |= OPENX_MODE_ACCESS_WRITE;
186         } else if ((flags & O_ACCMODE) == O_RDONLY) {
187                 accessmode |= OPENX_MODE_ACCESS_READ;
188         }
189
190 #if defined(O_SYNC)
191         if ((flags & O_SYNC) == O_SYNC) {
192                 accessmode |= OPENX_MODE_WRITE_THRU;
193         }
194 #endif
195
196         if (share_mode == DENY_FCB) {
197                 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
198         }
199
200         open_parms.openx.level = RAW_OPEN_OPENX;
201         open_parms.openx.in.flags = 0;
202         open_parms.openx.in.open_mode = accessmode;
203         open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
204         open_parms.openx.in.file_attrs = 0;
205         open_parms.openx.in.write_time = 0;
206         open_parms.openx.in.open_func = openfn;
207         open_parms.openx.in.size = 0;
208         open_parms.openx.in.timeout = 0;
209         open_parms.openx.in.fname = fname;
210
211         status = smb_raw_open(tree, mem_ctx, &open_parms);
212         talloc_free(mem_ctx);
213
214         if (fnum && NT_STATUS_IS_OK(status)) {
215                 *fnum = open_parms.openx.out.file.fnum;
216         }
217
218         return status;
219 }
220
221 static NTSTATUS raw_smbcli_t2open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
222 {
223         union smb_open io;
224         uint_t openfn=0;
225         uint_t accessmode=0;
226         TALLOC_CTX *mem_ctx;
227         NTSTATUS status;
228
229         mem_ctx = talloc_init("raw_t2open");
230         if (!mem_ctx) return NT_STATUS_NO_MEMORY;
231
232         if (flags & O_CREAT) {
233                 openfn |= OPENX_OPEN_FUNC_CREATE;
234         }
235         if (!(flags & O_EXCL)) {
236                 if (flags & O_TRUNC) {
237                         openfn |= OPENX_OPEN_FUNC_TRUNC;
238                 } else {
239                         openfn |= OPENX_OPEN_FUNC_OPEN;
240                 }
241         }
242
243         accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
244
245         if ((flags & O_ACCMODE) == O_RDWR) {
246                 accessmode |= OPENX_MODE_ACCESS_RDWR;
247         } else if ((flags & O_ACCMODE) == O_WRONLY) {
248                 accessmode |= OPENX_MODE_ACCESS_WRITE;
249         } else if ((flags & O_ACCMODE) == O_RDONLY) {
250                 accessmode |= OPENX_MODE_ACCESS_READ;
251         }
252
253 #if defined(O_SYNC)
254         if ((flags & O_SYNC) == O_SYNC) {
255                 accessmode |= OPENX_MODE_WRITE_THRU;
256         }
257 #endif
258
259         if (share_mode == DENY_FCB) {
260                 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
261         }
262
263         memset(&io, '\0', sizeof(io));
264         io.t2open.level = RAW_OPEN_T2OPEN;
265         io.t2open.in.flags = 0;
266         io.t2open.in.open_mode = accessmode;
267         io.t2open.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
268         io.t2open.in.file_attrs = 0;
269         io.t2open.in.write_time = 0;
270         io.t2open.in.open_func = openfn;
271         io.t2open.in.size = 0;
272         io.t2open.in.timeout = 0;
273         io.t2open.in.fname = fname;
274
275         io.t2open.in.num_eas = 1;
276         io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
277         io.t2open.in.eas[0].flags = 0;
278         io.t2open.in.eas[0].name.s = ".CLASSINFO";
279         io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
280
281         status = smb_raw_open(tree, mem_ctx, &io);
282         talloc_free(mem_ctx);
283
284         if (fnum && NT_STATUS_IS_OK(status)) {
285                 *fnum = io.openx.out.file.fnum;
286         }
287
288         return status;
289 }
290
291 static NTSTATUS raw_smbcli_ntcreate(struct smbcli_tree *tree, const char *fname, int *fnum)
292 {
293         union smb_open io;
294         TALLOC_CTX *mem_ctx;
295         NTSTATUS status;
296
297         mem_ctx = talloc_init("raw_t2open");
298         if (!mem_ctx) return NT_STATUS_NO_MEMORY;
299
300         memset(&io, '\0', sizeof(io));
301         io.generic.level = RAW_OPEN_NTCREATEX;
302         io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
303         io.ntcreatex.in.root_fid = 0;
304         io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
305         io.ntcreatex.in.alloc_size = 0;
306         io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
307         io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
308         io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
309         io.ntcreatex.in.create_options = 0;
310         io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
311         io.ntcreatex.in.security_flags = 0;
312         io.ntcreatex.in.fname = fname;
313
314         status = smb_raw_open(tree, mem_ctx, &io);
315         talloc_free(mem_ctx);
316
317         if (fnum && NT_STATUS_IS_OK(status)) {
318                 *fnum = io.openx.out.file.fnum;
319         }
320
321         return status;
322 }
323
324
325 BOOL torture_samba3_badpath(struct torture_context *torture)
326 {
327         struct smbcli_state *cli_nt;
328         struct smbcli_state *cli_dos;
329         const char *fname = "test.txt";
330         const char *fname1 = "test1.txt";
331         const char *dirname = "testdir";
332         char *fpath;
333         char *fpath1;
334         int fnum;
335         NTSTATUS status;
336         BOOL ret = True;
337         TALLOC_CTX *mem_ctx;
338         BOOL nt_status_support;
339
340         if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) {
341                 d_printf("talloc_init failed\n");
342                 return False;
343         }
344
345         nt_status_support = lp_nt_status_support();
346
347         if (!lp_set_cmdline("nt status support", "yes")) {
348                 printf("Could not set 'nt status support = yes'\n");
349                 goto fail;
350         }
351
352         if (!torture_open_connection(&cli_nt, 0)) {
353                 goto fail;
354         }
355
356         if (!lp_set_cmdline("nt status support", "no")) {
357                 printf("Could not set 'nt status support = yes'\n");
358                 goto fail;
359         }
360
361         if (!torture_open_connection(&cli_dos, 1)) {
362                 goto fail;
363         }
364
365         if (!lp_set_cmdline("nt status support",
366                             nt_status_support ? "yes":"no")) {
367                 printf("Could not reset 'nt status support = yes'");
368                 goto fail;
369         }
370
371         smbcli_deltree(cli_nt->tree, dirname);
372
373         status = smbcli_mkdir(cli_nt->tree, dirname);
374         if (!NT_STATUS_IS_OK(status)) {
375                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
376                 ret = False;
377                 goto done;
378         }
379
380         status = smbcli_chkpath(cli_nt->tree, dirname);
381         CHECK_STATUS(status, NT_STATUS_OK);
382
383         status = smbcli_chkpath(cli_nt->tree,
384                                 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
385         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
386
387         status = smbcli_chkpath(cli_dos->tree,
388                                 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
389         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
390
391         status = smbcli_chkpath(cli_nt->tree,
392                                 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
393                                                 dirname));
394         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
395         status = smbcli_chkpath(cli_dos->tree,
396                                 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
397                                                 dirname));
398         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
399
400         if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
401                 goto fail;
402         }
403         fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
404         if (fnum == -1) {
405                 d_printf("Could not create file %s: %s\n", fpath,
406                          smbcli_errstr(cli_nt->tree));
407                 goto fail;
408         }
409         smbcli_close(cli_nt->tree, fnum);
410
411         if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
412                 goto fail;
413         }
414         fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
415         if (fnum == -1) {
416                 d_printf("Could not create file %s: %s\n", fpath1,
417                          smbcli_errstr(cli_nt->tree));
418                 goto fail;
419         }
420         smbcli_close(cli_nt->tree, fnum);
421
422         /*
423          * Do a whole bunch of error code checks on chkpath
424          */
425
426         status = smbcli_chkpath(cli_nt->tree, fpath);
427         CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
428         status = smbcli_chkpath(cli_dos->tree, fpath);
429         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
430
431         status = smbcli_chkpath(cli_nt->tree, "..");
432         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
433         status = smbcli_chkpath(cli_dos->tree, "..");
434         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
435
436         status = smbcli_chkpath(cli_nt->tree, ".");
437         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
438         status = smbcli_chkpath(cli_dos->tree, ".");
439         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
440
441         status = smbcli_chkpath(cli_nt->tree, "\t");
442         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
443         status = smbcli_chkpath(cli_dos->tree, "\t");
444         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
445
446         status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
447         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
448         status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
449         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
450
451         status = smbcli_chkpath(cli_nt->tree, "<");
452         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
453         status = smbcli_chkpath(cli_dos->tree, "<");
454         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
455
456         status = smbcli_chkpath(cli_nt->tree, "<\\bla");
457         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
458         status = smbcli_chkpath(cli_dos->tree, "<\\bla");
459         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
460
461         /*
462          * .... And the same gang against getatr. Note that the DOS error codes
463          * differ....
464          */
465
466         status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
467         CHECK_STATUS(status, NT_STATUS_OK);
468         status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
469         CHECK_STATUS(status, NT_STATUS_OK);
470
471         status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
472         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
473         status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
474         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
475
476         status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
477         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
478         status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
479         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
480
481         status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
482         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
483         status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
484         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
485
486         status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
487         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
488         status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
489         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
490
491         status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
492         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
493         status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
494         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
495
496         status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
497         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
498         status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
499         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
500
501         /* Try the same set with openX. */
502
503         status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
504         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
505         status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
506         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
507
508         status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
509         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
510         status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
511         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
512
513         status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
514         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
515         status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
516         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
517
518         status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
519         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
520         status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
521         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
522
523         status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
524         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
525         status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
526         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
527
528         status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
529         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
530         status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
531         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
532
533         /* Let's test EEXIST error code mapping. */
534         status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
535         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
536         status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
537         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
538
539         status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
540         if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
541             || !torture_setting_bool(torture, "samba3", false)) {
542                 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
543                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
544         }
545         status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
546         if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
547             || !torture_setting_bool(torture, "samba3", false)) {
548                 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
549                 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
550         }
551
552         status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
553         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
554         status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
555         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
556
557         /* Try the rename test. */
558         {
559                 union smb_rename io;
560                 memset(&io, '\0', sizeof(io));
561                 io.rename.in.pattern1 = fpath1;
562                 io.rename.in.pattern2 = fpath;
563
564                 /* Try with SMBmv rename. */
565                 status = smb_raw_rename(cli_nt->tree, &io);
566                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
567                 status = smb_raw_rename(cli_dos->tree, &io);
568                 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
569
570                 /* Try with NT rename. */
571                 io.generic.level = RAW_RENAME_NTRENAME;
572                 io.ntrename.in.old_name = fpath1;
573                 io.ntrename.in.new_name = fpath;
574                 io.ntrename.in.attrib = 0;
575                 io.ntrename.in.cluster_size = 0;
576                 io.ntrename.in.flags = RENAME_FLAG_RENAME;
577
578                 status = smb_raw_rename(cli_nt->tree, &io);
579                 CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
580                 status = smb_raw_rename(cli_dos->tree, &io);
581                 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
582         }
583
584         goto done;
585
586  fail:
587         ret = False;
588
589  done:
590         if (cli_nt != NULL) {
591                 smbcli_deltree(cli_nt->tree, dirname);
592                 torture_close_connection(cli_nt);
593         }
594         if (cli_dos != NULL) {
595                 torture_close_connection(cli_dos);
596         }
597         talloc_free(mem_ctx);
598
599         return ret;
600 }
601
602 static void count_fn(struct clilist_file_info *info, const char *name,
603                      void *private_data)
604 {
605         int *counter = (int *)private_data;
606         *counter += 1;
607 }
608
609 BOOL torture_samba3_caseinsensitive(struct torture_context *torture)
610 {
611         struct smbcli_state *cli;
612         TALLOC_CTX *mem_ctx;
613         NTSTATUS status;
614         const char *dirname = "insensitive";
615         const char *ucase_dirname = "InSeNsItIvE";
616         const char *fname = "foo";
617         char *fpath;
618         int fnum;
619         int counter = 0;
620         BOOL ret = True;
621
622         if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
623                 d_printf("talloc_init failed\n");
624                 return False;
625         }
626
627         if (!torture_open_connection(&cli, 0)) {
628                 goto done;
629         }
630
631         smbcli_deltree(cli->tree, dirname);
632
633         status = smbcli_mkdir(cli->tree, dirname);
634         if (!NT_STATUS_IS_OK(status)) {
635                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
636                 goto done;
637         }
638
639         if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
640                 goto done;
641         }
642         fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
643         if (fnum == -1) {
644                 d_printf("Could not create file %s: %s\n", fpath,
645                          smbcli_errstr(cli->tree));
646                 goto done;
647         }
648         smbcli_close(cli->tree, fnum);
649
650         smbcli_list(cli->tree, talloc_asprintf(
651                             mem_ctx, "%s\\*", ucase_dirname),
652                     FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN
653                     |FILE_ATTRIBUTE_SYSTEM,
654                     count_fn, (void *)&counter);
655
656         if (counter == 3) {
657                 ret = True;
658         }
659         else {
660                 d_fprintf(stderr, "expected 3 entries, got %d\n", counter);
661                 ret = False;
662         }
663
664  done:
665         talloc_free(mem_ctx);
666         return ret;
667 }