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