r23792: convert Samba4 to GPLv3
[bbaumbach/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
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         }
187
188 #if defined(O_SYNC)
189         if ((flags & O_SYNC) == O_SYNC) {
190                 accessmode |= OPENX_MODE_WRITE_THRU;
191         }
192 #endif
193
194         if (share_mode == DENY_FCB) {
195                 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
196         }
197
198         open_parms.openx.level = RAW_OPEN_OPENX;
199         open_parms.openx.in.flags = 0;
200         open_parms.openx.in.open_mode = accessmode;
201         open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
202         open_parms.openx.in.file_attrs = 0;
203         open_parms.openx.in.write_time = 0;
204         open_parms.openx.in.open_func = openfn;
205         open_parms.openx.in.size = 0;
206         open_parms.openx.in.timeout = 0;
207         open_parms.openx.in.fname = fname;
208
209         status = smb_raw_open(tree, mem_ctx, &open_parms);
210         talloc_free(mem_ctx);
211
212         if (fnum && NT_STATUS_IS_OK(status)) {
213                 *fnum = open_parms.openx.out.file.fnum;
214         }
215
216         return status;
217 }
218
219 BOOL torture_samba3_badpath(struct torture_context *torture)
220 {
221         struct smbcli_state *cli_nt;
222         struct smbcli_state *cli_dos;
223         const char *fname = "test.txt";
224         const char *dirname = "testdir";
225         char *fpath;
226         int fnum;
227         NTSTATUS status;
228         BOOL ret = True;
229         TALLOC_CTX *mem_ctx;
230         BOOL nt_status_support;
231
232         if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) {
233                 d_printf("talloc_init failed\n");
234                 return False;
235         }
236
237         nt_status_support = lp_nt_status_support();
238
239         if (!lp_set_cmdline("nt status support", "yes")) {
240                 printf("Could not set 'nt status support = yes'\n");
241                 goto fail;
242         }
243
244         if (!torture_open_connection(&cli_nt, 0)) {
245                 goto fail;
246         }
247
248         if (!lp_set_cmdline("nt status support", "no")) {
249                 printf("Could not set 'nt status support = yes'\n");
250                 goto fail;
251         }
252
253         if (!torture_open_connection(&cli_dos, 1)) {
254                 goto fail;
255         }
256
257         if (!lp_set_cmdline("nt status support",
258                             nt_status_support ? "yes":"no")) {
259                 printf("Could not reset 'nt status support = yes'");
260                 goto fail;
261         }
262
263         smbcli_deltree(cli_nt->tree, dirname);
264
265         status = smbcli_mkdir(cli_nt->tree, dirname);
266         if (!NT_STATUS_IS_OK(status)) {
267                 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
268                 ret = False;
269                 goto done;
270         }
271
272         status = smbcli_chkpath(cli_nt->tree, dirname);
273         CHECK_STATUS(status, NT_STATUS_OK);
274
275         status = smbcli_chkpath(cli_nt->tree,
276                                 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
277         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
278
279         status = smbcli_chkpath(cli_dos->tree,
280                                 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
281         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
282
283         status = smbcli_chkpath(cli_nt->tree,
284                                 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
285                                                 dirname));
286         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
287         status = smbcli_chkpath(cli_dos->tree,
288                                 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
289                                                 dirname));
290         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
291
292         if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
293                 goto fail;
294         }
295         fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
296         if (fnum == -1) {
297                 d_printf("Could not create file %s: %s\n", fpath,
298                          smbcli_errstr(cli_nt->tree));
299                 goto fail;
300         }
301         smbcli_close(cli_nt->tree, fnum);
302
303         /*
304          * Do a whole bunch of error code checks on chkpath
305          */
306
307         status = smbcli_chkpath(cli_nt->tree, fpath);
308         CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
309         status = smbcli_chkpath(cli_dos->tree, fpath);
310         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
311
312         status = smbcli_chkpath(cli_nt->tree, "..");
313         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
314         status = smbcli_chkpath(cli_dos->tree, "..");
315         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
316
317         status = smbcli_chkpath(cli_nt->tree, ".");
318         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
319         status = smbcli_chkpath(cli_dos->tree, ".");
320         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
321
322         status = smbcli_chkpath(cli_nt->tree, "\t");
323         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
324         status = smbcli_chkpath(cli_dos->tree, "\t");
325         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
326
327         status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
328         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
329         status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
330         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
331
332         status = smbcli_chkpath(cli_nt->tree, "<");
333         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
334         status = smbcli_chkpath(cli_dos->tree, "<");
335         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
336
337         status = smbcli_chkpath(cli_nt->tree, "<\\bla");
338         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
339         status = smbcli_chkpath(cli_dos->tree, "<\\bla");
340         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
341
342         /*
343          * .... And the same gang against getatr. Note that the DOS error codes
344          * differ....
345          */
346
347         status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
348         CHECK_STATUS(status, NT_STATUS_OK);
349         status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
350         CHECK_STATUS(status, NT_STATUS_OK);
351
352         status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
353         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
354         status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
355         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
356
357         status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
358         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
359         status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
360         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
361
362         status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
363         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
364         status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
365         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
366
367         status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
368         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
369         status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
370         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
371
372         status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
373         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
374         status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
375         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
376
377         status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
378         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
379         status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
380         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
381
382         /* Try the same set with openX. */
383
384         status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
385         CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
386         status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
387         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
388
389         status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
390         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
391         status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
392         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
393
394         status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
395         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
396         status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
397         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
398
399         status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
400         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
401         status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
402         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
403
404         status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
405         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
406         status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
407         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
408
409         status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
410         CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
411         status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
412         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
413
414         goto done;
415
416  fail:
417         ret = False;
418
419  done:
420         if (cli_nt != NULL) {
421                 smbcli_deltree(cli_nt->tree, dirname);
422                 torture_close_connection(cli_nt);
423         }
424         if (cli_dos != NULL) {
425                 torture_close_connection(cli_dos);
426         }
427         talloc_free(mem_ctx);
428
429         return ret;
430 }