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/>.
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"
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)); \
39 bool torture_samba3_checkfsp(struct torture_context
*torture
)
41 struct smbcli_state
*cli
;
42 const char *fname
= "test.txt";
43 const char *dirname
= "testdir";
50 struct smbcli_tree
*tree2
;
52 if ((mem_ctx
= talloc_init("torture_samba3_checkfsp")) == NULL
) {
53 d_printf("talloc_init failed\n");
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");
65 smbcli_deltree(cli
->tree
, dirname
);
67 status
= torture_second_tcon(torture
, cli
->session
,
68 torture_setting_string(torture
, "share", NULL
),
70 CHECK_STATUS(status
, NT_STATUS_OK
);
71 if (!NT_STATUS_IS_OK(status
))
74 /* Try a read on an invalid FID */
76 nread
= smbcli_read(cli
->tree
, 4711, buf
, 0, sizeof(buf
));
77 CHECK_STATUS(smbcli_nt_error(cli
->tree
), NT_STATUS_INVALID_HANDLE
);
79 /* Try a read on a directory handle */
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
));
88 /* Open the directory */
91 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
92 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
93 io
.ntcreatex
.in
.root_fid
.fnum
= 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
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
103 io
.ntcreatex
.in
.fname
= dirname
;
104 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
105 if (!NT_STATUS_IS_OK(status
)) {
106 d_printf("smb_open on the directory failed: %s\n",
111 fnum
= io
.ntcreatex
.out
.file
.fnum
;
114 /* Try a read on the directory */
116 nread
= smbcli_read(cli
->tree
, fnum
, buf
, 0, sizeof(buf
));
118 d_printf("smbcli_read on a directory succeeded, expected "
123 CHECK_STATUS(smbcli_nt_error(cli
->tree
),
124 NT_STATUS_INVALID_DEVICE_REQUEST
);
126 /* Same test on the second tcon */
128 nread
= smbcli_read(tree2
, fnum
, buf
, 0, sizeof(buf
));
130 d_printf("smbcli_read on a directory succeeded, expected "
135 CHECK_STATUS(smbcli_nt_error(tree2
), NT_STATUS_INVALID_HANDLE
);
137 smbcli_close(cli
->tree
, fnum
);
139 /* Try a normal file read on a second tcon */
141 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
143 d_printf("Failed to create %s - %s\n", fname
,
144 smbcli_errstr(cli
->tree
));
149 nread
= smbcli_read(tree2
, fnum
, buf
, 0, sizeof(buf
));
150 CHECK_STATUS(smbcli_nt_error(tree2
), NT_STATUS_INVALID_HANDLE
);
152 smbcli_close(cli
->tree
, fnum
);
155 smbcli_deltree(cli
->tree
, dirname
);
156 torture_close_connection(cli
);
157 talloc_free(mem_ctx
);
162 static NTSTATUS
raw_smbcli_open(struct smbcli_tree
*tree
, const char *fname
, int flags
, int share_mode
, int *fnum
)
164 union smb_open open_parms
;
165 unsigned int openfn
=0;
166 unsigned int accessmode
=0;
170 mem_ctx
= talloc_init("raw_open");
171 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
173 if (flags
& O_CREAT
) {
174 openfn
|= OPENX_OPEN_FUNC_CREATE
;
176 if (!(flags
& O_EXCL
)) {
177 if (flags
& O_TRUNC
) {
178 openfn
|= OPENX_OPEN_FUNC_TRUNC
;
180 openfn
|= OPENX_OPEN_FUNC_OPEN
;
184 accessmode
= (share_mode
<<OPENX_MODE_DENY_SHIFT
);
186 if ((flags
& O_ACCMODE
) == O_RDWR
) {
187 accessmode
|= OPENX_MODE_ACCESS_RDWR
;
188 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
189 accessmode
|= OPENX_MODE_ACCESS_WRITE
;
190 } else if ((flags
& O_ACCMODE
) == O_RDONLY
) {
191 accessmode
|= OPENX_MODE_ACCESS_READ
;
195 if ((flags
& O_SYNC
) == O_SYNC
) {
196 accessmode
|= OPENX_MODE_WRITE_THRU
;
200 if (share_mode
== DENY_FCB
) {
201 accessmode
= OPENX_MODE_ACCESS_FCB
| OPENX_MODE_DENY_FCB
;
204 open_parms
.openx
.level
= RAW_OPEN_OPENX
;
205 open_parms
.openx
.in
.flags
= 0;
206 open_parms
.openx
.in
.open_mode
= accessmode
;
207 open_parms
.openx
.in
.search_attrs
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
208 open_parms
.openx
.in
.file_attrs
= 0;
209 open_parms
.openx
.in
.write_time
= 0;
210 open_parms
.openx
.in
.open_func
= openfn
;
211 open_parms
.openx
.in
.size
= 0;
212 open_parms
.openx
.in
.timeout
= 0;
213 open_parms
.openx
.in
.fname
= fname
;
215 status
= smb_raw_open(tree
, mem_ctx
, &open_parms
);
216 talloc_free(mem_ctx
);
218 if (fnum
&& NT_STATUS_IS_OK(status
)) {
219 *fnum
= open_parms
.openx
.out
.file
.fnum
;
225 static NTSTATUS
raw_smbcli_t2open(struct smbcli_tree
*tree
, const char *fname
, int flags
, int share_mode
, int *fnum
)
228 unsigned int openfn
=0;
229 unsigned int accessmode
=0;
233 mem_ctx
= talloc_init("raw_t2open");
234 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
236 if (flags
& O_CREAT
) {
237 openfn
|= OPENX_OPEN_FUNC_CREATE
;
239 if (!(flags
& O_EXCL
)) {
240 if (flags
& O_TRUNC
) {
241 openfn
|= OPENX_OPEN_FUNC_TRUNC
;
243 openfn
|= OPENX_OPEN_FUNC_OPEN
;
247 accessmode
= (share_mode
<<OPENX_MODE_DENY_SHIFT
);
249 if ((flags
& O_ACCMODE
) == O_RDWR
) {
250 accessmode
|= OPENX_MODE_ACCESS_RDWR
;
251 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
252 accessmode
|= OPENX_MODE_ACCESS_WRITE
;
253 } else if ((flags
& O_ACCMODE
) == O_RDONLY
) {
254 accessmode
|= OPENX_MODE_ACCESS_READ
;
258 if ((flags
& O_SYNC
) == O_SYNC
) {
259 accessmode
|= OPENX_MODE_WRITE_THRU
;
263 if (share_mode
== DENY_FCB
) {
264 accessmode
= OPENX_MODE_ACCESS_FCB
| OPENX_MODE_DENY_FCB
;
267 memset(&io
, '\0', sizeof(io
));
268 io
.t2open
.level
= RAW_OPEN_T2OPEN
;
269 io
.t2open
.in
.flags
= 0;
270 io
.t2open
.in
.open_mode
= accessmode
;
271 io
.t2open
.in
.search_attrs
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
272 io
.t2open
.in
.file_attrs
= 0;
273 io
.t2open
.in
.write_time
= 0;
274 io
.t2open
.in
.open_func
= openfn
;
275 io
.t2open
.in
.size
= 0;
276 io
.t2open
.in
.timeout
= 0;
277 io
.t2open
.in
.fname
= fname
;
279 io
.t2open
.in
.num_eas
= 1;
280 io
.t2open
.in
.eas
= talloc_array(mem_ctx
, struct ea_struct
, io
.t2open
.in
.num_eas
);
281 io
.t2open
.in
.eas
[0].flags
= 0;
282 io
.t2open
.in
.eas
[0].name
.s
= ".CLASSINFO";
283 io
.t2open
.in
.eas
[0].value
= data_blob_talloc(mem_ctx
, "first value", 11);
285 status
= smb_raw_open(tree
, mem_ctx
, &io
);
286 talloc_free(mem_ctx
);
288 if (fnum
&& NT_STATUS_IS_OK(status
)) {
289 *fnum
= io
.openx
.out
.file
.fnum
;
295 static NTSTATUS
raw_smbcli_ntcreate(struct smbcli_tree
*tree
, const char *fname
, int *fnum
)
301 mem_ctx
= talloc_init("raw_t2open");
302 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
304 memset(&io
, '\0', sizeof(io
));
305 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
306 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
307 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
308 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
309 io
.ntcreatex
.in
.alloc_size
= 0;
310 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
311 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
312 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
313 io
.ntcreatex
.in
.create_options
= 0;
314 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
315 io
.ntcreatex
.in
.security_flags
= 0;
316 io
.ntcreatex
.in
.fname
= fname
;
318 status
= smb_raw_open(tree
, mem_ctx
, &io
);
319 talloc_free(mem_ctx
);
321 if (fnum
&& NT_STATUS_IS_OK(status
)) {
322 *fnum
= io
.openx
.out
.file
.fnum
;
329 bool torture_samba3_badpath(struct torture_context
*torture
)
331 struct smbcli_state
*cli_nt
;
332 struct smbcli_state
*cli_dos
;
333 const char *fname
= "test.txt";
334 const char *fname1
= "test1.txt";
335 const char *dirname
= "testdir";
342 bool nt_status_support
;
344 if (!(mem_ctx
= talloc_init("torture_samba3_badpath"))) {
345 d_printf("talloc_init failed\n");
349 nt_status_support
= lpcfg_nt_status_support(torture
->lp_ctx
);
351 if (!lpcfg_set_cmdline(torture
->lp_ctx
, "nt status support", "yes")) {
352 printf("Could not set 'nt status support = yes'\n");
356 if (!torture_open_connection(&cli_nt
, torture
, 0)) {
360 if (!lpcfg_set_cmdline(torture
->lp_ctx
, "nt status support", "no")) {
361 printf("Could not set 'nt status support = yes'\n");
365 if (!torture_open_connection(&cli_dos
, torture
, 1)) {
369 if (!lpcfg_set_cmdline(torture
->lp_ctx
, "nt status support",
370 nt_status_support
? "yes":"no")) {
371 printf("Could not reset 'nt status support = yes'");
375 smbcli_deltree(cli_nt
->tree
, dirname
);
377 status
= smbcli_mkdir(cli_nt
->tree
, dirname
);
378 if (!NT_STATUS_IS_OK(status
)) {
379 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status
));
384 status
= smbcli_chkpath(cli_nt
->tree
, dirname
);
385 CHECK_STATUS(status
, NT_STATUS_OK
);
387 status
= smbcli_chkpath(cli_nt
->tree
,
388 talloc_asprintf(mem_ctx
, "%s\\bla", dirname
));
389 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
391 status
= smbcli_chkpath(cli_dos
->tree
,
392 talloc_asprintf(mem_ctx
, "%s\\bla", dirname
));
393 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
395 status
= smbcli_chkpath(cli_nt
->tree
,
396 talloc_asprintf(mem_ctx
, "%s\\bla\\blub",
398 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
399 status
= smbcli_chkpath(cli_dos
->tree
,
400 talloc_asprintf(mem_ctx
, "%s\\bla\\blub",
402 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
404 if (!(fpath
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname
))) {
407 fnum
= smbcli_open(cli_nt
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
409 d_printf("Could not create file %s: %s\n", fpath
,
410 smbcli_errstr(cli_nt
->tree
));
413 smbcli_close(cli_nt
->tree
, fnum
);
415 if (!(fpath1
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname1
))) {
418 fnum
= smbcli_open(cli_nt
->tree
, fpath1
, O_RDWR
| O_CREAT
, DENY_NONE
);
420 d_printf("Could not create file %s: %s\n", fpath1
,
421 smbcli_errstr(cli_nt
->tree
));
424 smbcli_close(cli_nt
->tree
, fnum
);
427 * Do a whole bunch of error code checks on chkpath
430 status
= smbcli_chkpath(cli_nt
->tree
, fpath
);
431 CHECK_STATUS(status
, NT_STATUS_NOT_A_DIRECTORY
);
432 status
= smbcli_chkpath(cli_dos
->tree
, fpath
);
433 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
435 status
= smbcli_chkpath(cli_nt
->tree
, "..");
436 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
437 status
= smbcli_chkpath(cli_dos
->tree
, "..");
438 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
440 status
= smbcli_chkpath(cli_nt
->tree
, ".");
441 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
442 status
= smbcli_chkpath(cli_dos
->tree
, ".");
443 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
445 status
= smbcli_chkpath(cli_nt
->tree
, "\t");
446 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
447 status
= smbcli_chkpath(cli_dos
->tree
, "\t");
448 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
450 status
= smbcli_chkpath(cli_nt
->tree
, "\t\\bla");
451 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
452 status
= smbcli_chkpath(cli_dos
->tree
, "\t\\bla");
453 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
455 status
= smbcli_chkpath(cli_nt
->tree
, "<");
456 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
457 status
= smbcli_chkpath(cli_dos
->tree
, "<");
458 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
460 status
= smbcli_chkpath(cli_nt
->tree
, "<\\bla");
461 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
462 status
= smbcli_chkpath(cli_dos
->tree
, "<\\bla");
463 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
466 * .... And the same gang against getatr. Note that the DOS error codes
470 status
= smbcli_getatr(cli_nt
->tree
, fpath
, NULL
, NULL
, NULL
);
471 CHECK_STATUS(status
, NT_STATUS_OK
);
472 status
= smbcli_getatr(cli_dos
->tree
, fpath
, NULL
, NULL
, NULL
);
473 CHECK_STATUS(status
, NT_STATUS_OK
);
475 status
= smbcli_getatr(cli_nt
->tree
, "..", NULL
, NULL
, NULL
);
476 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
477 status
= smbcli_getatr(cli_dos
->tree
, "..", NULL
, NULL
, NULL
);
478 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
480 status
= smbcli_getatr(cli_nt
->tree
, ".", NULL
, NULL
, NULL
);
481 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
482 status
= smbcli_getatr(cli_dos
->tree
, ".", NULL
, NULL
, NULL
);
483 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
485 status
= smbcli_getatr(cli_nt
->tree
, "\t", NULL
, NULL
, NULL
);
486 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
487 status
= smbcli_getatr(cli_dos
->tree
, "\t", NULL
, NULL
, NULL
);
488 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
490 status
= smbcli_getatr(cli_nt
->tree
, "\t\\bla", NULL
, NULL
, NULL
);
491 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
492 status
= smbcli_getatr(cli_dos
->tree
, "\t\\bla", NULL
, NULL
, NULL
);
493 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
495 status
= smbcli_getatr(cli_nt
->tree
, "<", NULL
, NULL
, NULL
);
496 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
497 status
= smbcli_getatr(cli_dos
->tree
, "<", NULL
, NULL
, NULL
);
498 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
500 status
= smbcli_getatr(cli_nt
->tree
, "<\\bla", NULL
, NULL
, NULL
);
501 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
502 status
= smbcli_getatr(cli_dos
->tree
, "<\\bla", NULL
, NULL
, NULL
);
503 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
505 /* Try the same set with openX. */
507 status
= raw_smbcli_open(cli_nt
->tree
, "..", O_RDONLY
, DENY_NONE
, NULL
);
508 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
509 status
= raw_smbcli_open(cli_dos
->tree
, "..", O_RDONLY
, DENY_NONE
, NULL
);
510 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
512 status
= raw_smbcli_open(cli_nt
->tree
, ".", O_RDONLY
, DENY_NONE
, NULL
);
513 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
514 status
= raw_smbcli_open(cli_dos
->tree
, ".", O_RDONLY
, DENY_NONE
, NULL
);
515 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
517 status
= raw_smbcli_open(cli_nt
->tree
, "\t", O_RDONLY
, DENY_NONE
, NULL
);
518 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
519 status
= raw_smbcli_open(cli_dos
->tree
, "\t", O_RDONLY
, DENY_NONE
, NULL
);
520 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
522 status
= raw_smbcli_open(cli_nt
->tree
, "\t\\bla", O_RDONLY
, DENY_NONE
, NULL
);
523 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
524 status
= raw_smbcli_open(cli_dos
->tree
, "\t\\bla", O_RDONLY
, DENY_NONE
, NULL
);
525 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
527 status
= raw_smbcli_open(cli_nt
->tree
, "<", O_RDONLY
, DENY_NONE
, NULL
);
528 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
529 status
= raw_smbcli_open(cli_dos
->tree
, "<", O_RDONLY
, DENY_NONE
, NULL
);
530 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
532 status
= raw_smbcli_open(cli_nt
->tree
, "<\\bla", O_RDONLY
, DENY_NONE
, NULL
);
533 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
534 status
= raw_smbcli_open(cli_dos
->tree
, "<\\bla", O_RDONLY
, DENY_NONE
, NULL
);
535 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
537 /* Let's test EEXIST error code mapping. */
538 status
= raw_smbcli_open(cli_nt
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
539 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
540 status
= raw_smbcli_open(cli_dos
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
541 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
543 status
= raw_smbcli_t2open(cli_nt
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
544 if (!NT_STATUS_EQUAL(status
, NT_STATUS_EAS_NOT_SUPPORTED
)
545 || !torture_setting_bool(torture
, "samba3", false)) {
546 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
547 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
549 status
= raw_smbcli_t2open(cli_dos
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
550 if (!NT_STATUS_EQUAL(status
, NT_STATUS_DOS(ERRDOS
,ERReasnotsupported
))
551 || !torture_setting_bool(torture
, "samba3", false)) {
552 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
553 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
556 status
= raw_smbcli_ntcreate(cli_nt
->tree
, fpath
, NULL
);
557 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
558 status
= raw_smbcli_ntcreate(cli_dos
->tree
, fpath
, NULL
);
559 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
561 /* Try the rename test. */
564 memset(&io
, '\0', sizeof(io
));
565 io
.rename
.in
.pattern1
= fpath1
;
566 io
.rename
.in
.pattern2
= fpath
;
568 /* Try with SMBmv rename. */
569 status
= smb_raw_rename(cli_nt
->tree
, &io
);
570 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
571 status
= smb_raw_rename(cli_dos
->tree
, &io
);
572 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRrename
));
574 /* Try with NT rename. */
575 io
.generic
.level
= RAW_RENAME_NTRENAME
;
576 io
.ntrename
.in
.old_name
= fpath1
;
577 io
.ntrename
.in
.new_name
= fpath
;
578 io
.ntrename
.in
.attrib
= 0;
579 io
.ntrename
.in
.cluster_size
= 0;
580 io
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
582 status
= smb_raw_rename(cli_nt
->tree
, &io
);
583 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
584 status
= smb_raw_rename(cli_dos
->tree
, &io
);
585 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRrename
));
594 if (cli_nt
!= NULL
) {
595 smbcli_deltree(cli_nt
->tree
, dirname
);
596 torture_close_connection(cli_nt
);
598 if (cli_dos
!= NULL
) {
599 torture_close_connection(cli_dos
);
601 talloc_free(mem_ctx
);
606 static void count_fn(struct clilist_file_info
*info
, const char *name
,
609 int *counter
= (int *)private_data
;
613 bool torture_samba3_caseinsensitive(struct torture_context
*torture
)
615 struct smbcli_state
*cli
;
618 const char *dirname
= "insensitive";
619 const char *ucase_dirname
= "InSeNsItIvE";
620 const char *fname
= "foo";
626 if (!(mem_ctx
= talloc_init("torture_samba3_caseinsensitive"))) {
627 d_printf("talloc_init failed\n");
631 if (!torture_open_connection(&cli
, torture
, 0)) {
635 smbcli_deltree(cli
->tree
, dirname
);
637 status
= smbcli_mkdir(cli
->tree
, dirname
);
638 torture_assert_ntstatus_ok(torture
, status
, "smbcli_mkdir failed");
639 if (!NT_STATUS_IS_OK(status
)) {
643 if (!(fpath
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname
))) {
646 fnum
= smbcli_open(cli
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
648 torture_result(torture
, TORTURE_FAIL
,
649 "Could not create file %s: %s", fpath
,
650 smbcli_errstr(cli
->tree
));
653 smbcli_close(cli
->tree
, fnum
);
655 smbcli_list(cli
->tree
, talloc_asprintf(
656 mem_ctx
, "%s\\*", ucase_dirname
),
657 FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_HIDDEN
658 |FILE_ATTRIBUTE_SYSTEM
,
659 count_fn
, (void *)&counter
);
665 torture_result(torture
, TORTURE_FAIL
,
666 "expected 3 entries, got %d", counter
);
671 talloc_free(mem_ctx
);
675 static void close_locked_file(struct tevent_context
*ev
,
676 struct tevent_timer
*te
,
680 int *pfd
= (int *)private_data
;
690 struct lock_result_state
{
695 static void receive_lock_result(struct smbcli_request
*req
)
697 struct lock_result_state
*state
=
698 (struct lock_result_state
*)req
->async
.private_data
;
700 state
->status
= smbcli_request_simple_recv(req
);
705 * Check that Samba3 correctly deals with conflicting posix byte range locks
706 * on an underlying file
708 * Note: This test depends on "posix locking = yes".
709 * Note: To run this test, use "--option=torture:localdir=<LOCALDIR>"
712 bool torture_samba3_posixtimedlock(struct torture_context
*tctx
)
714 struct smbcli_state
*cli
;
717 const char *dirname
= "posixlock";
718 const char *fname
= "locked";
720 const char *localdir
;
721 const char *localname
;
725 struct flock posix_lock
;
728 struct smb_lock_entry lock_entry
;
729 struct smbcli_request
*req
;
730 struct lock_result_state lock_result
;
732 struct tevent_timer
*te
;
734 if (!torture_open_connection(&cli
, tctx
, 0)) {
739 smbcli_deltree(cli
->tree
, dirname
);
741 status
= smbcli_mkdir(cli
->tree
, dirname
);
742 if (!NT_STATUS_IS_OK(status
)) {
743 torture_warning(tctx
, "smbcli_mkdir failed: %s\n",
749 if (!(fpath
= talloc_asprintf(tctx
, "%s\\%s", dirname
, fname
))) {
750 torture_warning(tctx
, "talloc failed\n");
754 fnum
= smbcli_open(cli
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
756 torture_warning(tctx
, "Could not create file %s: %s\n", fpath
,
757 smbcli_errstr(cli
->tree
));
762 if (!(localdir
= torture_setting_string(tctx
, "localdir", NULL
))) {
763 torture_warning(tctx
, "Need 'localdir' setting\n");
768 if (!(localname
= talloc_asprintf(tctx
, "%s/%s/%s", localdir
, dirname
,
770 torture_warning(tctx
, "talloc failed\n");
776 * Lock a byte range from posix
779 fd
= open(localname
, O_RDWR
);
781 torture_warning(tctx
, "open(%s) failed: %s\n",
782 localname
, strerror(errno
));
786 posix_lock
.l_type
= F_WRLCK
;
787 posix_lock
.l_whence
= SEEK_SET
;
788 posix_lock
.l_start
= 0;
789 posix_lock
.l_len
= 1;
791 if (fcntl(fd
, F_SETLK
, &posix_lock
) == -1) {
792 torture_warning(tctx
, "fcntl failed: %s\n", strerror(errno
));
798 * Try a cifs brlock without timeout to see if posix locking = yes
801 io
.lockx
.in
.ulock_cnt
= 0;
802 io
.lockx
.in
.lock_cnt
= 1;
804 lock_entry
.count
= 1;
805 lock_entry
.offset
= 0;
806 lock_entry
.pid
= cli
->tree
->session
->pid
;
808 io
.lockx
.level
= RAW_LOCK_LOCKX
;
809 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
810 io
.lockx
.in
.timeout
= 0;
811 io
.lockx
.in
.locks
= &lock_entry
;
812 io
.lockx
.in
.file
.fnum
= fnum
;
814 status
= smb_raw_lock(cli
->tree
, &io
);
817 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
824 * Now fire off a timed brlock, unlock the posix lock and see if the
825 * timed lock gets through.
828 io
.lockx
.in
.timeout
= 5000;
830 req
= smb_raw_lock_send(cli
->tree
, &io
);
832 torture_warning(tctx
, "smb_raw_lock_send failed\n");
837 lock_result
.done
= false;
838 req
->async
.fn
= receive_lock_result
;
839 req
->async
.private_data
= &lock_result
;
841 te
= tevent_add_timer(req
->transport
->socket
->event
.ctx
,
842 tctx
, timeval_current_ofs(1, 0),
843 close_locked_file
, &fd
);
845 torture_warning(tctx
, "tevent_add_timer failed\n");
850 while ((fd
!= -1) || (!lock_result
.done
)) {
851 if (tevent_loop_once(req
->transport
->socket
->event
.ctx
)
853 torture_warning(tctx
, "tevent_loop_once failed: %s\n",
860 CHECK_STATUS(lock_result
.status
, NT_STATUS_OK
);
864 smbcli_close(cli
->tree
, fnum
);
869 smbcli_deltree(cli
->tree
, dirname
);
873 bool torture_samba3_rootdirfid(struct torture_context
*tctx
)
875 struct smbcli_state
*cli
;
879 const char *fname
= "testfile";
882 if (!torture_open_connection(&cli
, tctx
, 0)) {
887 smbcli_unlink(cli
->tree
, fname
);
890 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
891 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
892 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
893 io
.ntcreatex
.in
.security_flags
= 0;
894 io
.ntcreatex
.in
.access_mask
=
895 SEC_STD_SYNCHRONIZE
| SEC_FILE_EXECUTE
;
896 io
.ntcreatex
.in
.alloc_size
= 0;
897 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
898 io
.ntcreatex
.in
.share_access
=
899 NTCREATEX_SHARE_ACCESS_READ
900 | NTCREATEX_SHARE_ACCESS_READ
;
901 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
902 io
.ntcreatex
.in
.create_options
= 0;
903 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
904 io
.ntcreatex
.in
.fname
= "\\";
905 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
906 if (!NT_STATUS_IS_OK(status
)) {
907 d_printf("smb_open on the directory failed: %s\n",
912 dnum
= io
.ntcreatex
.out
.file
.fnum
;
914 io
.ntcreatex
.in
.flags
=
915 NTCREATEX_FLAGS_REQUEST_OPLOCK
916 | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
917 io
.ntcreatex
.in
.root_fid
.fnum
= dnum
;
918 io
.ntcreatex
.in
.security_flags
= 0;
919 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
920 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
921 io
.ntcreatex
.in
.alloc_size
= 0;
922 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
923 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
924 io
.ntcreatex
.in
.create_options
= 0;
925 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
926 io
.ntcreatex
.in
.fname
= fname
;
928 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
929 if (!NT_STATUS_IS_OK(status
)) {
930 d_printf("smb_open on the file %s failed: %s\n",
931 fname
, nt_errstr(status
));
936 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
937 smbcli_close(cli
->tree
, dnum
);
938 smbcli_unlink(cli
->tree
, fname
);
945 bool torture_samba3_oplock_logoff(struct torture_context
*tctx
)
947 struct smbcli_state
*cli
;
951 const char *fname
= "testfile";
953 struct smbcli_request
*req
;
954 struct smb_echo echo_req
;
956 if (!torture_open_connection(&cli
, tctx
, 0)) {
961 smbcli_unlink(cli
->tree
, fname
);
964 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
965 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
966 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
967 io
.ntcreatex
.in
.security_flags
= 0;
968 io
.ntcreatex
.in
.access_mask
=
969 SEC_STD_SYNCHRONIZE
| SEC_FILE_EXECUTE
;
970 io
.ntcreatex
.in
.alloc_size
= 0;
971 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
972 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
973 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
974 io
.ntcreatex
.in
.create_options
= 0;
975 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
976 io
.ntcreatex
.in
.fname
= "testfile";
977 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
978 if (!NT_STATUS_IS_OK(status
)) {
979 d_printf("first smb_open failed: %s\n", nt_errstr(status
));
983 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
986 * Create a conflicting open, causing the one-second delay
989 req
= smb_raw_open_send(cli
->tree
, &io
);
991 d_printf("smb_raw_open_send failed\n");
997 * Pull the VUID from under that request. As of Nov 3, 2008 all Samba3
998 * versions (3.0, 3.2 and master) would spin sending ERRinvuid errors
999 * as long as the client is still connected.
1002 status
= smb_raw_ulogoff(cli
->session
);
1004 if (!NT_STATUS_IS_OK(status
)) {
1005 d_printf("ulogoff failed: %s\n", nt_errstr(status
));
1010 echo_req
.in
.repeat_count
= 1;
1011 echo_req
.in
.size
= 1;
1012 echo_req
.in
.data
= discard_const_p(uint8_t, "");
1014 status
= smb_raw_echo(cli
->session
->transport
, &echo_req
);
1015 if (!NT_STATUS_IS_OK(status
)) {
1016 d_printf("smb_raw_echo returned %s\n",