r16907: Add an index parameter to torture_open_connection. Next step is to enable the
[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 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.h"
28
29 #define CHECK_STATUS(status, correct) do { \
30         if (!NT_STATUS_EQUAL(status, correct)) { \
31                 printf("(%s) Incorrect status %s - should be %s\n", \
32                        __location__, nt_errstr(status), nt_errstr(correct)); \
33                 ret = False; \
34         } \
35 } while (0)
36
37 BOOL torture_samba3_checkfsp(struct torture_context *torture)
38 {
39         struct smbcli_state *cli;
40         const char *fname = "test.txt";
41         const char *dirname = "testdir";
42         int fnum;
43         NTSTATUS status;
44         BOOL ret = True;
45         TALLOC_CTX *mem_ctx;
46         ssize_t nread;
47         char buf[16];
48         struct smbcli_tree *tree2;
49
50         if ((mem_ctx = talloc_init("torture_samba3_checkfsp")) == NULL) {
51                 d_printf("talloc_init failed\n");
52                 return False;
53         }
54
55         if (!torture_open_connection_share(
56                     torture, &cli, lp_parm_string(-1, "torture", "host"),
57                     lp_parm_string(-1, "torture", "share"), NULL)) {
58                 d_printf("torture_open_connection_share failed\n");
59                 ret = False;
60                 goto done;
61         }
62
63         smbcli_deltree(cli->tree, dirname);
64
65         status = torture_second_tcon(torture, cli->session,
66                                      lp_parm_string(-1, "torture", "share"),
67                                      &tree2);
68         CHECK_STATUS(status, NT_STATUS_OK);
69         if (!NT_STATUS_IS_OK(status))
70                 goto done;
71
72         /* Try a read on an invalid FID */
73
74         nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
75         CHECK_STATUS(smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);
76
77         /* Try a read on a directory handle */
78
79         status = smbcli_mkdir(cli->tree, dirname);
80         if (!NT_STATUS_IS_OK(status)) {
81                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
82                 ret = False;
83                 goto done;
84         }
85
86         /* Open the directory */
87         {
88                 union smb_open io;
89                 io.generic.level = RAW_OPEN_NTCREATEX;
90                 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
91                 io.ntcreatex.in.root_fid = 0;
92                 io.ntcreatex.in.security_flags = 0;
93                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
94                 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
95                 io.ntcreatex.in.alloc_size = 0;
96                 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
97                 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
98                 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
99                 io.ntcreatex.in.create_options = 0;
100                 io.ntcreatex.in.fname = dirname;
101                 status = smb_raw_open(cli->tree, mem_ctx, &io);
102                 if (!NT_STATUS_IS_OK(status)) {
103                         d_printf("smb_open on the directory failed: %s\n",
104                                  nt_errstr(status));
105                         ret = False;
106                         goto done;
107                 }
108                 fnum = io.ntcreatex.out.file.fnum;
109         }
110
111         /* Try a read on the directory */
112
113         nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
114         if (nread >= 0) {
115                 d_printf("smbcli_read on a directory succeeded, expected "
116                          "failure\n");
117                 ret = False;
118         }
119
120         CHECK_STATUS(smbcli_nt_error(cli->tree),
121                      NT_STATUS_INVALID_DEVICE_REQUEST);
122
123         /* Same test on the second tcon */
124
125         nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
126         if (nread >= 0) {
127                 d_printf("smbcli_read on a directory succeeded, expected "
128                          "failure\n");
129                 ret = False;
130         }
131
132         CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
133
134         smbcli_close(cli->tree, fnum);
135
136         /* Try a normal file read on a second tcon */
137
138         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
139         if (fnum == -1) {
140                 d_printf("Failed to create %s - %s\n", fname,
141                          smbcli_errstr(cli->tree));
142                 ret = False;
143                 goto done;
144         }
145
146         nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
147         CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
148
149         smbcli_close(cli->tree, fnum);
150
151  done:
152         smbcli_deltree(cli->tree, dirname);
153         torture_close_connection(cli);
154         talloc_free(mem_ctx);
155
156         return ret;
157 }
158
159 static NTSTATUS raw_smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
160 {
161         union smb_open open_parms;
162         uint_t openfn=0;
163         uint_t accessmode=0;
164         TALLOC_CTX *mem_ctx;
165         NTSTATUS status;
166
167         mem_ctx = talloc_init("raw_open");
168         if (!mem_ctx) return NT_STATUS_NO_MEMORY;
169
170         if (flags & O_CREAT) {
171                 openfn |= OPENX_OPEN_FUNC_CREATE;
172         }
173         if (!(flags & O_EXCL)) {
174                 if (flags & O_TRUNC) {
175                         openfn |= OPENX_OPEN_FUNC_TRUNC;
176                 } else {
177                         openfn |= OPENX_OPEN_FUNC_OPEN;
178                 }
179         }
180
181         accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
182
183         if ((flags & O_ACCMODE) == O_RDWR) {
184                 accessmode |= OPENX_MODE_ACCESS_RDWR;
185         } else if ((flags & O_ACCMODE) == O_WRONLY) {
186                 accessmode |= OPENX_MODE_ACCESS_WRITE;
187         }
188
189 #if defined(O_SYNC)
190         if ((flags & O_SYNC) == O_SYNC) {
191                 accessmode |= OPENX_MODE_WRITE_THRU;
192         }
193 #endif
194
195         if (share_mode == DENY_FCB) {
196                 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
197         }
198
199         open_parms.openx.level = RAW_OPEN_OPENX;
200         open_parms.openx.in.flags = 0;
201         open_parms.openx.in.open_mode = accessmode;
202         open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
203         open_parms.openx.in.file_attrs = 0;
204         open_parms.openx.in.write_time = 0;
205         open_parms.openx.in.open_func = openfn;
206         open_parms.openx.in.size = 0;
207         open_parms.openx.in.timeout = 0;
208         open_parms.openx.in.fname = fname;
209
210         status = smb_raw_open(tree, mem_ctx, &open_parms);
211         talloc_free(mem_ctx);
212
213         if (fnum && NT_STATUS_IS_OK(status)) {
214                 *fnum = open_parms.openx.out.file.fnum;
215         }
216
217         return status;
218 }
219
220 BOOL torture_samba3_badpath(struct torture_context *torture)
221 {
222         struct smbcli_state *cli_nt;
223         struct smbcli_state *cli_dos;
224         const char *fname = "test.txt";
225         const char *dirname = "testdir";
226         char *fpath;
227         int fnum;
228         NTSTATUS status;
229         BOOL ret = True;
230         TALLOC_CTX *mem_ctx;
231         BOOL nt_status_support;
232
233         if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) {
234                 d_printf("talloc_init failed\n");
235                 return False;
236         }
237
238         nt_status_support = lp_nt_status_support();
239
240         if (!lp_set_cmdline("nt status support", "yes")) {
241                 printf("Could not set 'nt status support = yes'\n");
242                 goto fail;
243         }
244
245         if (!torture_open_connection(&cli_nt, 0)) {
246                 goto fail;
247         }
248
249         if (!lp_set_cmdline("nt status support", "no")) {
250                 printf("Could not set 'nt status support = yes'\n");
251                 goto fail;
252         }
253
254         if (!torture_open_connection(&cli_dos, 1)) {
255                 goto fail;
256         }
257
258         if (!lp_set_cmdline("nt status support",
259                             nt_status_support ? "yes":"no")) {
260                 printf("Could not reset 'nt status support = yes'");
261                 goto fail;
262         }
263
264         smbcli_deltree(cli_nt->tree, dirname);
265
266         status = smbcli_mkdir(cli_nt->tree, dirname);
267         if (!NT_STATUS_IS_OK(status)) {
268                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
269                 ret = False;
270                 goto done;
271         }
272
273         status = smbcli_chkpath(cli_nt->tree, dirname);
274         CHECK_STATUS(status, NT_STATUS_OK);
275
276         status = smbcli_chkpath(cli_nt->tree,
277                                 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
278         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
279
280         status = smbcli_chkpath(cli_dos->tree,
281                                 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
282         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
283
284         status = smbcli_chkpath(cli_nt->tree,
285                                 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
286                                                 dirname));
287         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
288         status = smbcli_chkpath(cli_dos->tree,
289                                 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
290                                                 dirname));
291         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
292
293         if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
294                 goto fail;
295         }
296         fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
297         if (fnum == -1) {
298                 d_printf("Could not create file %s: %s\n", fpath,
299                          smbcli_errstr(cli_nt->tree));
300                 goto fail;
301         }
302         smbcli_close(cli_nt->tree, fnum);
303
304         /*
305          * Do a whole bunch of error code checks on chkpath
306          */
307
308         status = smbcli_chkpath(cli_nt->tree, fpath);
309         CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
310         status = smbcli_chkpath(cli_dos->tree, fpath);
311         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
312
313         status = smbcli_chkpath(cli_nt->tree, "..");
314         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
315         status = smbcli_chkpath(cli_dos->tree, "..");
316         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
317
318         status = smbcli_chkpath(cli_nt->tree, ".");
319         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
320         status = smbcli_chkpath(cli_dos->tree, ".");
321         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
322
323         status = smbcli_chkpath(cli_nt->tree, "\t");
324         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
325         status = smbcli_chkpath(cli_dos->tree, "\t");
326         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
327
328         status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
329         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
330         status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
331         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
332
333         status = smbcli_chkpath(cli_nt->tree, "<");
334         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
335         status = smbcli_chkpath(cli_dos->tree, "<");
336         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
337
338         status = smbcli_chkpath(cli_nt->tree, "<\\bla");
339         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
340         status = smbcli_chkpath(cli_dos->tree, "<\\bla");
341         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
342
343         /*
344          * .... And the same gang against getatr. Note that the DOS error codes
345          * differ....
346          */
347
348         status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
349         CHECK_STATUS(status, NT_STATUS_OK);
350         status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
351         CHECK_STATUS(status, NT_STATUS_OK);
352
353         status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
354         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
355         status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
356         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
357
358         status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
359         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
360         status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
361         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
362
363         status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
364         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
365         status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
366         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
367
368         status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
369         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
370         status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
371         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
372
373         status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
374         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
375         status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
376         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
377
378         status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
379         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
380         status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
381         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
382
383         /* Try the same set with openX. */
384
385         status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
386         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
387         status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
388         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
389
390         status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
391         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
392         status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
393         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
394
395         status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
396         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
397         status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
398         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
399
400         status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
401         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
402         status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
403         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
404
405         status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
406         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
407         status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
408         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
409
410         status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
411         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
412         status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
413         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
414
415         goto done;
416
417  fail:
418         ret = False;
419
420  done:
421         if (cli_nt != NULL) {
422                 smbcli_deltree(cli_nt->tree, dirname);
423                 torture_close_connection(cli_nt);
424         }
425         if (cli_dos != NULL) {
426                 torture_close_connection(cli_dos);
427         }
428         talloc_free(mem_ctx);
429
430         return ret;
431 }