s3:torture:delete: fix a comment
[Samba/gebeck_regimport.git] / source4 / torture / raw / samba3misc.c
blob200438588e4b4322081674455d0ae9d4772ace90
1 /*
2 Unix SMB/CIFS implementation.
3 Test some misc Samba3 code paths
4 Copyright (C) Volker Lendecke 2006
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.
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.
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/>.
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 #include "torture/raw/proto.h"
32 #define CHECK_STATUS(torture, status, correct) do { \
33 if (!NT_STATUS_EQUAL(status, correct)) { \
34 torture_result(torture, TORTURE_FAIL, "%s: Incorrect status %s - should be %s\n", \
35 __location__, nt_errstr(status), nt_errstr(correct)); \
36 ret = false; \
37 } \
38 } while (0)
40 bool torture_samba3_checkfsp(struct torture_context *torture, 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;
52 torture_assert(torture, mem_ctx = talloc_init("torture_samba3_checkfsp"), "talloc_init failed\n");
54 torture_assert_ntstatus_equal(torture, torture_second_tcon(torture, cli->session,
55 torture_setting_string(torture, "share", NULL),
56 &tree2),
57 NT_STATUS_OK,
58 "creating second tcon");
60 /* Try a read on an invalid FID */
62 nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
63 CHECK_STATUS(torture, smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);
65 /* Try a read on a directory handle */
67 torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory");
69 /* Open the directory */
71 union smb_open io;
72 io.generic.level = RAW_OPEN_NTCREATEX;
73 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
74 io.ntcreatex.in.root_fid.fnum = 0;
75 io.ntcreatex.in.security_flags = 0;
76 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
77 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
78 io.ntcreatex.in.alloc_size = 0;
79 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
80 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
81 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
82 io.ntcreatex.in.create_options = 0;
83 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
84 io.ntcreatex.in.fname = dirname;
85 status = smb_raw_open(cli->tree, mem_ctx, &io);
86 if (!NT_STATUS_IS_OK(status)) {
87 torture_result(torture, TORTURE_FAIL, "smb_open on the directory failed: %s\n",
88 nt_errstr(status));
89 ret = false;
90 goto done;
92 fnum = io.ntcreatex.out.file.fnum;
95 /* Try a read on the directory */
97 nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
98 if (nread >= 0) {
99 torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected "
100 "failure\n");
101 ret = false;
104 CHECK_STATUS(torture, smbcli_nt_error(cli->tree),
105 NT_STATUS_INVALID_DEVICE_REQUEST);
107 /* Same test on the second tcon */
109 nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
110 if (nread >= 0) {
111 torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected "
112 "failure\n");
113 ret = false;
116 CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
118 smbcli_close(cli->tree, fnum);
120 /* Try a normal file read on a second tcon */
122 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
123 if (fnum == -1) {
124 torture_result(torture, TORTURE_FAIL, "Failed to create %s - %s\n", fname,
125 smbcli_errstr(cli->tree));
126 ret = false;
127 goto done;
130 nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
131 CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
133 smbcli_close(cli->tree, fnum);
135 done:
136 smbcli_deltree(cli->tree, dirname);
137 talloc_free(mem_ctx);
139 return ret;
142 static NTSTATUS raw_smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
144 union smb_open open_parms;
145 unsigned int openfn=0;
146 unsigned int accessmode=0;
147 TALLOC_CTX *mem_ctx;
148 NTSTATUS status;
150 mem_ctx = talloc_init("raw_open");
151 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
153 if (flags & O_CREAT) {
154 openfn |= OPENX_OPEN_FUNC_CREATE;
156 if (!(flags & O_EXCL)) {
157 if (flags & O_TRUNC) {
158 openfn |= OPENX_OPEN_FUNC_TRUNC;
159 } else {
160 openfn |= OPENX_OPEN_FUNC_OPEN;
164 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
166 if ((flags & O_ACCMODE) == O_RDWR) {
167 accessmode |= OPENX_MODE_ACCESS_RDWR;
168 } else if ((flags & O_ACCMODE) == O_WRONLY) {
169 accessmode |= OPENX_MODE_ACCESS_WRITE;
170 } else if ((flags & O_ACCMODE) == O_RDONLY) {
171 accessmode |= OPENX_MODE_ACCESS_READ;
174 #if defined(O_SYNC)
175 if ((flags & O_SYNC) == O_SYNC) {
176 accessmode |= OPENX_MODE_WRITE_THRU;
178 #endif
180 if (share_mode == DENY_FCB) {
181 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
184 open_parms.openx.level = RAW_OPEN_OPENX;
185 open_parms.openx.in.flags = 0;
186 open_parms.openx.in.open_mode = accessmode;
187 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
188 open_parms.openx.in.file_attrs = 0;
189 open_parms.openx.in.write_time = 0;
190 open_parms.openx.in.open_func = openfn;
191 open_parms.openx.in.size = 0;
192 open_parms.openx.in.timeout = 0;
193 open_parms.openx.in.fname = fname;
195 status = smb_raw_open(tree, mem_ctx, &open_parms);
196 talloc_free(mem_ctx);
198 if (fnum && NT_STATUS_IS_OK(status)) {
199 *fnum = open_parms.openx.out.file.fnum;
202 return status;
205 static NTSTATUS raw_smbcli_t2open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
207 union smb_open io;
208 unsigned int openfn=0;
209 unsigned int accessmode=0;
210 TALLOC_CTX *mem_ctx;
211 NTSTATUS status;
213 mem_ctx = talloc_init("raw_t2open");
214 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
216 if (flags & O_CREAT) {
217 openfn |= OPENX_OPEN_FUNC_CREATE;
219 if (!(flags & O_EXCL)) {
220 if (flags & O_TRUNC) {
221 openfn |= OPENX_OPEN_FUNC_TRUNC;
222 } else {
223 openfn |= OPENX_OPEN_FUNC_OPEN;
227 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
229 if ((flags & O_ACCMODE) == O_RDWR) {
230 accessmode |= OPENX_MODE_ACCESS_RDWR;
231 } else if ((flags & O_ACCMODE) == O_WRONLY) {
232 accessmode |= OPENX_MODE_ACCESS_WRITE;
233 } else if ((flags & O_ACCMODE) == O_RDONLY) {
234 accessmode |= OPENX_MODE_ACCESS_READ;
237 #if defined(O_SYNC)
238 if ((flags & O_SYNC) == O_SYNC) {
239 accessmode |= OPENX_MODE_WRITE_THRU;
241 #endif
243 if (share_mode == DENY_FCB) {
244 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
247 memset(&io, '\0', sizeof(io));
248 io.t2open.level = RAW_OPEN_T2OPEN;
249 io.t2open.in.flags = 0;
250 io.t2open.in.open_mode = accessmode;
251 io.t2open.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
252 io.t2open.in.file_attrs = 0;
253 io.t2open.in.write_time = 0;
254 io.t2open.in.open_func = openfn;
255 io.t2open.in.size = 0;
256 io.t2open.in.timeout = 0;
257 io.t2open.in.fname = fname;
259 io.t2open.in.num_eas = 1;
260 io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
261 io.t2open.in.eas[0].flags = 0;
262 io.t2open.in.eas[0].name.s = ".CLASSINFO";
263 io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
265 status = smb_raw_open(tree, mem_ctx, &io);
266 talloc_free(mem_ctx);
268 if (fnum && NT_STATUS_IS_OK(status)) {
269 *fnum = io.openx.out.file.fnum;
272 return status;
275 static NTSTATUS raw_smbcli_ntcreate(struct smbcli_tree *tree, const char *fname, int *fnum)
277 union smb_open io;
278 TALLOC_CTX *mem_ctx;
279 NTSTATUS status;
281 mem_ctx = talloc_init("raw_t2open");
282 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
284 memset(&io, '\0', sizeof(io));
285 io.generic.level = RAW_OPEN_NTCREATEX;
286 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
287 io.ntcreatex.in.root_fid.fnum = 0;
288 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
289 io.ntcreatex.in.alloc_size = 0;
290 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
291 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
292 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
293 io.ntcreatex.in.create_options = 0;
294 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
295 io.ntcreatex.in.security_flags = 0;
296 io.ntcreatex.in.fname = fname;
298 status = smb_raw_open(tree, mem_ctx, &io);
299 talloc_free(mem_ctx);
301 if (fnum && NT_STATUS_IS_OK(status)) {
302 *fnum = io.openx.out.file.fnum;
305 return status;
309 bool torture_samba3_badpath(struct torture_context *torture)
311 struct smbcli_state *cli_nt;
312 struct smbcli_state *cli_dos;
313 const char *fname = "test.txt";
314 const char *fname1 = "test1.txt";
315 const char *dirname = "testdir";
316 char *fpath;
317 char *fpath1;
318 int fnum;
319 NTSTATUS status;
320 bool ret = true;
321 TALLOC_CTX *mem_ctx;
322 bool nt_status_support;
324 torture_assert(torture, mem_ctx = talloc_init("torture_samba3_badpath"), "talloc_init failed");
326 nt_status_support = lpcfg_nt_status_support(torture->lp_ctx);
328 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n");
330 torture_assert_goto(torture, torture_open_connection(&cli_nt, torture, 0), ret, fail, "Could not open NTSTATUS connection\n");
332 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n");
334 torture_assert_goto(torture, torture_open_connection(&cli_dos, torture, 1), ret, fail, "Could not open DOS connection\n");
336 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support",
337 nt_status_support ? "yes":"no"),
338 ret, fail, "Could not set 'nt status support' back to where it was\n");
340 torture_assert(torture, torture_setup_dir(cli_nt, dirname), "creating test directory");
342 status = smbcli_chkpath(cli_nt->tree, dirname);
343 CHECK_STATUS(torture, status, NT_STATUS_OK);
345 status = smbcli_chkpath(cli_nt->tree,
346 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
347 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
349 status = smbcli_chkpath(cli_dos->tree,
350 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
351 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
353 status = smbcli_chkpath(cli_nt->tree,
354 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
355 dirname));
356 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
357 status = smbcli_chkpath(cli_dos->tree,
358 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
359 dirname));
360 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
362 torture_assert_goto(torture, fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname),
363 ret, fail, "Could not allocate fpath\n");
365 fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
366 if (fnum == -1) {
367 torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath,
368 smbcli_errstr(cli_nt->tree));
369 goto fail;
371 smbcli_close(cli_nt->tree, fnum);
373 if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
374 goto fail;
376 fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
377 if (fnum == -1) {
378 torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath1,
379 smbcli_errstr(cli_nt->tree));
380 goto fail;
382 smbcli_close(cli_nt->tree, fnum);
385 * Do a whole bunch of error code checks on chkpath
388 status = smbcli_chkpath(cli_nt->tree, fpath);
389 CHECK_STATUS(torture, status, NT_STATUS_NOT_A_DIRECTORY);
390 status = smbcli_chkpath(cli_dos->tree, fpath);
391 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
393 status = smbcli_chkpath(cli_nt->tree, "..");
394 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
395 status = smbcli_chkpath(cli_dos->tree, "..");
396 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
398 status = smbcli_chkpath(cli_nt->tree, ".");
399 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
400 status = smbcli_chkpath(cli_dos->tree, ".");
401 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
403 status = smbcli_chkpath(cli_nt->tree, "\t");
404 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
405 status = smbcli_chkpath(cli_dos->tree, "\t");
406 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
408 status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
409 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
410 status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
411 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
413 status = smbcli_chkpath(cli_nt->tree, "<");
414 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
415 status = smbcli_chkpath(cli_dos->tree, "<");
416 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
418 status = smbcli_chkpath(cli_nt->tree, "<\\bla");
419 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
420 status = smbcli_chkpath(cli_dos->tree, "<\\bla");
421 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
424 * .... And the same gang against getatr. Note that the DOS error codes
425 * differ....
428 status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
429 CHECK_STATUS(torture, status, NT_STATUS_OK);
430 status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
431 CHECK_STATUS(torture, status, NT_STATUS_OK);
433 status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
434 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
435 status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
436 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
438 status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
439 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
440 status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
441 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
443 status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
444 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
445 status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
446 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
448 status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
449 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
450 status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
451 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
453 status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
454 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
455 status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
456 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
458 status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
459 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
460 status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
461 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
463 /* Try the same set with openX. */
465 status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
466 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
467 status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
468 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
470 status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
471 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
472 status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
473 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
475 status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
476 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
477 status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
478 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
480 status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
481 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
482 status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
483 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
485 status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
486 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
487 status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
488 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
490 status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
491 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
492 status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
493 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
495 /* Let's test EEXIST error code mapping. */
496 status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
497 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
498 status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
499 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
501 status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
502 if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
503 || !torture_setting_bool(torture, "samba3", false)) {
504 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
505 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
507 status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
508 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
509 || !torture_setting_bool(torture, "samba3", false)) {
510 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
511 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
514 status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
515 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
516 status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
517 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
519 /* Try the rename test. */
521 union smb_rename io;
522 memset(&io, '\0', sizeof(io));
523 io.rename.in.pattern1 = fpath1;
524 io.rename.in.pattern2 = fpath;
526 /* Try with SMBmv rename. */
527 status = smb_raw_rename(cli_nt->tree, &io);
528 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
529 status = smb_raw_rename(cli_dos->tree, &io);
530 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename));
532 /* Try with NT rename. */
533 io.generic.level = RAW_RENAME_NTRENAME;
534 io.ntrename.in.old_name = fpath1;
535 io.ntrename.in.new_name = fpath;
536 io.ntrename.in.attrib = 0;
537 io.ntrename.in.cluster_size = 0;
538 io.ntrename.in.flags = RENAME_FLAG_RENAME;
540 status = smb_raw_rename(cli_nt->tree, &io);
541 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
542 status = smb_raw_rename(cli_dos->tree, &io);
543 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename));
546 goto done;
548 fail:
549 ret = false;
551 done:
552 if (cli_nt != NULL) {
553 smbcli_deltree(cli_nt->tree, dirname);
554 torture_close_connection(cli_nt);
556 if (cli_dos != NULL) {
557 torture_close_connection(cli_dos);
559 talloc_free(mem_ctx);
561 return ret;
564 static void count_fn(struct clilist_file_info *info, const char *name,
565 void *private_data)
567 int *counter = (int *)private_data;
568 *counter += 1;
571 bool torture_samba3_caseinsensitive(struct torture_context *torture, struct smbcli_state *cli)
573 TALLOC_CTX *mem_ctx;
574 const char *dirname = "insensitive";
575 const char *ucase_dirname = "InSeNsItIvE";
576 const char *fname = "foo";
577 char *fpath;
578 int fnum;
579 int counter = 0;
580 bool ret = false;
582 if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
583 torture_result(torture, TORTURE_FAIL, "talloc_init failed\n");
584 return false;
587 torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory");
589 if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
590 goto done;
592 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
593 if (fnum == -1) {
594 torture_result(torture, TORTURE_FAIL,
595 "Could not create file %s: %s", fpath,
596 smbcli_errstr(cli->tree));
597 goto done;
599 smbcli_close(cli->tree, fnum);
601 smbcli_list(cli->tree, talloc_asprintf(
602 mem_ctx, "%s\\*", ucase_dirname),
603 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN
604 |FILE_ATTRIBUTE_SYSTEM,
605 count_fn, (void *)&counter);
607 if (counter == 3) {
608 ret = true;
610 else {
611 torture_result(torture, TORTURE_FAIL,
612 "expected 3 entries, got %d", counter);
613 ret = false;
616 done:
617 talloc_free(mem_ctx);
618 return ret;
621 static void close_locked_file(struct tevent_context *ev,
622 struct tevent_timer *te,
623 struct timeval now,
624 void *private_data)
626 int *pfd = (int *)private_data;
628 TALLOC_FREE(te);
630 if (*pfd != -1) {
631 close(*pfd);
632 *pfd = -1;
636 struct lock_result_state {
637 NTSTATUS status;
638 bool done;
641 static void receive_lock_result(struct smbcli_request *req)
643 struct lock_result_state *state =
644 (struct lock_result_state *)req->async.private_data;
646 state->status = smbcli_request_simple_recv(req);
647 state->done = true;
651 * Check that Samba3 correctly deals with conflicting posix byte range locks
652 * on an underlying file
654 * Note: This test depends on "posix locking = yes".
655 * Note: To run this test, use "--option=torture:localdir=<LOCALDIR>"
658 bool torture_samba3_posixtimedlock(struct torture_context *tctx, struct smbcli_state *cli)
660 NTSTATUS status;
661 bool ret = true;
662 const char *dirname = "posixlock";
663 const char *fname = "locked";
664 const char *fpath;
665 const char *localdir;
666 const char *localname;
667 int fnum = -1;
669 int fd = -1;
670 struct flock posix_lock;
672 union smb_lock io;
673 struct smb_lock_entry lock_entry;
674 struct smbcli_request *req;
675 struct lock_result_state lock_result;
677 struct tevent_timer *te;
679 torture_assert(tctx, torture_setup_dir(cli, dirname), "creating test directory");
681 if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) {
682 torture_warning(tctx, "talloc failed\n");
683 ret = false;
684 goto done;
686 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
687 if (fnum == -1) {
688 torture_warning(tctx, "Could not create file %s: %s\n", fpath,
689 smbcli_errstr(cli->tree));
690 ret = false;
691 goto done;
694 if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) {
695 torture_warning(tctx, "Need 'localdir' setting\n");
696 ret = false;
697 goto done;
700 if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname,
701 fname))) {
702 torture_warning(tctx, "talloc failed\n");
703 ret = false;
704 goto done;
708 * Lock a byte range from posix
711 fd = open(localname, O_RDWR);
712 if (fd == -1) {
713 torture_warning(tctx, "open(%s) failed: %s\n",
714 localname, strerror(errno));
715 goto done;
718 posix_lock.l_type = F_WRLCK;
719 posix_lock.l_whence = SEEK_SET;
720 posix_lock.l_start = 0;
721 posix_lock.l_len = 1;
723 if (fcntl(fd, F_SETLK, &posix_lock) == -1) {
724 torture_warning(tctx, "fcntl failed: %s\n", strerror(errno));
725 ret = false;
726 goto done;
730 * Try a cifs brlock without timeout to see if posix locking = yes
733 io.lockx.in.ulock_cnt = 0;
734 io.lockx.in.lock_cnt = 1;
736 lock_entry.count = 1;
737 lock_entry.offset = 0;
738 lock_entry.pid = cli->tree->session->pid;
740 io.lockx.level = RAW_LOCK_LOCKX;
741 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
742 io.lockx.in.timeout = 0;
743 io.lockx.in.locks = &lock_entry;
744 io.lockx.in.file.fnum = fnum;
746 status = smb_raw_lock(cli->tree, &io);
748 ret = true;
749 CHECK_STATUS(tctx, status, NT_STATUS_FILE_LOCK_CONFLICT);
751 if (!ret) {
752 goto done;
756 * Now fire off a timed brlock, unlock the posix lock and see if the
757 * timed lock gets through.
760 io.lockx.in.timeout = 5000;
762 req = smb_raw_lock_send(cli->tree, &io);
763 if (req == NULL) {
764 torture_warning(tctx, "smb_raw_lock_send failed\n");
765 ret = false;
766 goto done;
769 lock_result.done = false;
770 req->async.fn = receive_lock_result;
771 req->async.private_data = &lock_result;
773 te = tevent_add_timer(tctx->ev,
774 tctx, timeval_current_ofs(1, 0),
775 close_locked_file, &fd);
776 if (te == NULL) {
777 torture_warning(tctx, "tevent_add_timer failed\n");
778 ret = false;
779 goto done;
782 while ((fd != -1) || (!lock_result.done)) {
783 if (tevent_loop_once(tctx->ev) == -1) {
784 torture_warning(tctx, "tevent_loop_once failed: %s\n",
785 strerror(errno));
786 ret = false;
787 goto done;
791 CHECK_STATUS(tctx, lock_result.status, NT_STATUS_OK);
793 done:
794 if (fnum != -1) {
795 smbcli_close(cli->tree, fnum);
797 if (fd != -1) {
798 close(fd);
800 smbcli_deltree(cli->tree, dirname);
801 return ret;
804 bool torture_samba3_rootdirfid(struct torture_context *tctx, struct smbcli_state *cli)
806 uint16_t dnum;
807 union smb_open io;
808 const char *fname = "testfile";
809 bool ret = false;
811 smbcli_unlink(cli->tree, fname);
813 ZERO_STRUCT(io);
814 io.generic.level = RAW_OPEN_NTCREATEX;
815 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
816 io.ntcreatex.in.root_fid.fnum = 0;
817 io.ntcreatex.in.security_flags = 0;
818 io.ntcreatex.in.access_mask =
819 SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE;
820 io.ntcreatex.in.alloc_size = 0;
821 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
822 io.ntcreatex.in.share_access =
823 NTCREATEX_SHARE_ACCESS_READ
824 | NTCREATEX_SHARE_ACCESS_READ;
825 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
826 io.ntcreatex.in.create_options = 0;
827 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
828 io.ntcreatex.in.fname = "\\";
829 torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io),
830 NT_STATUS_OK,
831 ret, done, "smb_open on the directory failed: %s\n");
833 dnum = io.ntcreatex.out.file.fnum;
835 io.ntcreatex.in.flags =
836 NTCREATEX_FLAGS_REQUEST_OPLOCK
837 | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
838 io.ntcreatex.in.root_fid.fnum = dnum;
839 io.ntcreatex.in.security_flags = 0;
840 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
841 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
842 io.ntcreatex.in.alloc_size = 0;
843 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
844 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
845 io.ntcreatex.in.create_options = 0;
846 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
847 io.ntcreatex.in.fname = fname;
849 torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io),
850 NT_STATUS_OK,
851 ret, done, "smb_open on the file failed");
853 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
854 smbcli_close(cli->tree, dnum);
855 smbcli_unlink(cli->tree, fname);
857 ret = true;
858 done:
859 return ret;
862 bool torture_samba3_oplock_logoff(struct torture_context *tctx, struct smbcli_state *cli)
864 uint16_t fnum1;
865 union smb_open io;
866 const char *fname = "testfile";
867 bool ret = false;
868 struct smbcli_request *req;
869 struct smb_echo echo_req;
871 smbcli_unlink(cli->tree, fname);
873 ZERO_STRUCT(io);
874 io.generic.level = RAW_OPEN_NTCREATEX;
875 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
876 io.ntcreatex.in.root_fid.fnum = 0;
877 io.ntcreatex.in.security_flags = 0;
878 io.ntcreatex.in.access_mask =
879 SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE;
880 io.ntcreatex.in.alloc_size = 0;
881 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
882 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
883 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
884 io.ntcreatex.in.create_options = 0;
885 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
886 io.ntcreatex.in.fname = "testfile";
887 torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io),
888 NT_STATUS_OK,
889 ret, done, "first smb_open on the file failed");
890 fnum1 = io.ntcreatex.out.file.fnum;
893 * Create a conflicting open, causing the one-second delay
896 torture_assert_goto(tctx, req = smb_raw_open_send(cli->tree, &io),
897 ret, done, "smb_raw_open_send on the file failed");
900 * Pull the VUID from under that request. As of Nov 3, 2008 all Samba3
901 * versions (3.0, 3.2 and master) would spin sending ERRinvuid errors
902 * as long as the client is still connected.
905 torture_assert_ntstatus_equal_goto(tctx, smb_raw_ulogoff(cli->session),
906 NT_STATUS_OK,
907 ret, done, "ulogoff failed failed");
909 echo_req.in.repeat_count = 1;
910 echo_req.in.size = 1;
911 echo_req.in.data = discard_const_p(uint8_t, "");
913 torture_assert_ntstatus_equal_goto(tctx, smb_raw_echo(cli->session->transport, &echo_req),
914 NT_STATUS_OK,
915 ret, done, "smb_raw_echo failed");
917 ret = true;
918 done:
919 return ret;