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"
30 #include "torture/raw/proto.h"
32 #define CHECK_STATUS(status, correct) do { \
33 if (!NT_STATUS_EQUAL(status, correct)) { \
34 printf("(%s) Incorrect status %s - should be %s\n", \
35 __location__, nt_errstr(status), nt_errstr(correct)); \
40 bool torture_samba3_checkfsp(struct torture_context
*torture
)
42 struct smbcli_state
*cli
;
43 const char *fname
= "test.txt";
44 const char *dirname
= "testdir";
51 struct smbcli_tree
*tree2
;
53 if ((mem_ctx
= talloc_init("torture_samba3_checkfsp")) == NULL
) {
54 d_printf("talloc_init failed\n");
58 if (!torture_open_connection_share(
59 torture
, &cli
, torture
, torture_setting_string(torture
, "host", NULL
),
60 torture_setting_string(torture
, "share", NULL
), torture
->ev
)) {
61 d_printf("torture_open_connection_share failed\n");
66 smbcli_deltree(cli
->tree
, dirname
);
68 status
= torture_second_tcon(torture
, cli
->session
,
69 torture_setting_string(torture
, "share", NULL
),
71 CHECK_STATUS(status
, NT_STATUS_OK
);
72 if (!NT_STATUS_IS_OK(status
))
75 /* Try a read on an invalid FID */
77 nread
= smbcli_read(cli
->tree
, 4711, buf
, 0, sizeof(buf
));
78 CHECK_STATUS(smbcli_nt_error(cli
->tree
), NT_STATUS_INVALID_HANDLE
);
80 /* Try a read on a directory handle */
82 status
= smbcli_mkdir(cli
->tree
, dirname
);
83 if (!NT_STATUS_IS_OK(status
)) {
84 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status
));
89 /* Open the directory */
92 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
93 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
94 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
95 io
.ntcreatex
.in
.security_flags
= 0;
96 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
97 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
98 io
.ntcreatex
.in
.alloc_size
= 0;
99 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
100 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
101 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
102 io
.ntcreatex
.in
.create_options
= 0;
103 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
104 io
.ntcreatex
.in
.fname
= dirname
;
105 status
= smb_raw_open(cli
->tree
, mem_ctx
, &io
);
106 if (!NT_STATUS_IS_OK(status
)) {
107 d_printf("smb_open on the directory failed: %s\n",
112 fnum
= io
.ntcreatex
.out
.file
.fnum
;
115 /* Try a read on the directory */
117 nread
= smbcli_read(cli
->tree
, fnum
, buf
, 0, sizeof(buf
));
119 d_printf("smbcli_read on a directory succeeded, expected "
124 CHECK_STATUS(smbcli_nt_error(cli
->tree
),
125 NT_STATUS_INVALID_DEVICE_REQUEST
);
127 /* Same test on the second tcon */
129 nread
= smbcli_read(tree2
, fnum
, buf
, 0, sizeof(buf
));
131 d_printf("smbcli_read on a directory succeeded, expected "
136 CHECK_STATUS(smbcli_nt_error(tree2
), NT_STATUS_INVALID_HANDLE
);
138 smbcli_close(cli
->tree
, fnum
);
140 /* Try a normal file read on a second tcon */
142 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
144 d_printf("Failed to create %s - %s\n", fname
,
145 smbcli_errstr(cli
->tree
));
150 nread
= smbcli_read(tree2
, fnum
, buf
, 0, sizeof(buf
));
151 CHECK_STATUS(smbcli_nt_error(tree2
), NT_STATUS_INVALID_HANDLE
);
153 smbcli_close(cli
->tree
, fnum
);
156 smbcli_deltree(cli
->tree
, dirname
);
157 torture_close_connection(cli
);
158 talloc_free(mem_ctx
);
163 static NTSTATUS
raw_smbcli_open(struct smbcli_tree
*tree
, const char *fname
, int flags
, int share_mode
, int *fnum
)
165 union smb_open open_parms
;
166 unsigned int openfn
=0;
167 unsigned int accessmode
=0;
171 mem_ctx
= talloc_init("raw_open");
172 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
174 if (flags
& O_CREAT
) {
175 openfn
|= OPENX_OPEN_FUNC_CREATE
;
177 if (!(flags
& O_EXCL
)) {
178 if (flags
& O_TRUNC
) {
179 openfn
|= OPENX_OPEN_FUNC_TRUNC
;
181 openfn
|= OPENX_OPEN_FUNC_OPEN
;
185 accessmode
= (share_mode
<<OPENX_MODE_DENY_SHIFT
);
187 if ((flags
& O_ACCMODE
) == O_RDWR
) {
188 accessmode
|= OPENX_MODE_ACCESS_RDWR
;
189 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
190 accessmode
|= OPENX_MODE_ACCESS_WRITE
;
191 } else if ((flags
& O_ACCMODE
) == O_RDONLY
) {
192 accessmode
|= OPENX_MODE_ACCESS_READ
;
196 if ((flags
& O_SYNC
) == O_SYNC
) {
197 accessmode
|= OPENX_MODE_WRITE_THRU
;
201 if (share_mode
== DENY_FCB
) {
202 accessmode
= OPENX_MODE_ACCESS_FCB
| OPENX_MODE_DENY_FCB
;
205 open_parms
.openx
.level
= RAW_OPEN_OPENX
;
206 open_parms
.openx
.in
.flags
= 0;
207 open_parms
.openx
.in
.open_mode
= accessmode
;
208 open_parms
.openx
.in
.search_attrs
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
209 open_parms
.openx
.in
.file_attrs
= 0;
210 open_parms
.openx
.in
.write_time
= 0;
211 open_parms
.openx
.in
.open_func
= openfn
;
212 open_parms
.openx
.in
.size
= 0;
213 open_parms
.openx
.in
.timeout
= 0;
214 open_parms
.openx
.in
.fname
= fname
;
216 status
= smb_raw_open(tree
, mem_ctx
, &open_parms
);
217 talloc_free(mem_ctx
);
219 if (fnum
&& NT_STATUS_IS_OK(status
)) {
220 *fnum
= open_parms
.openx
.out
.file
.fnum
;
226 static NTSTATUS
raw_smbcli_t2open(struct smbcli_tree
*tree
, const char *fname
, int flags
, int share_mode
, int *fnum
)
229 unsigned int openfn
=0;
230 unsigned int accessmode
=0;
234 mem_ctx
= talloc_init("raw_t2open");
235 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
237 if (flags
& O_CREAT
) {
238 openfn
|= OPENX_OPEN_FUNC_CREATE
;
240 if (!(flags
& O_EXCL
)) {
241 if (flags
& O_TRUNC
) {
242 openfn
|= OPENX_OPEN_FUNC_TRUNC
;
244 openfn
|= OPENX_OPEN_FUNC_OPEN
;
248 accessmode
= (share_mode
<<OPENX_MODE_DENY_SHIFT
);
250 if ((flags
& O_ACCMODE
) == O_RDWR
) {
251 accessmode
|= OPENX_MODE_ACCESS_RDWR
;
252 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
253 accessmode
|= OPENX_MODE_ACCESS_WRITE
;
254 } else if ((flags
& O_ACCMODE
) == O_RDONLY
) {
255 accessmode
|= OPENX_MODE_ACCESS_READ
;
259 if ((flags
& O_SYNC
) == O_SYNC
) {
260 accessmode
|= OPENX_MODE_WRITE_THRU
;
264 if (share_mode
== DENY_FCB
) {
265 accessmode
= OPENX_MODE_ACCESS_FCB
| OPENX_MODE_DENY_FCB
;
268 memset(&io
, '\0', sizeof(io
));
269 io
.t2open
.level
= RAW_OPEN_T2OPEN
;
270 io
.t2open
.in
.flags
= 0;
271 io
.t2open
.in
.open_mode
= accessmode
;
272 io
.t2open
.in
.search_attrs
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
273 io
.t2open
.in
.file_attrs
= 0;
274 io
.t2open
.in
.write_time
= 0;
275 io
.t2open
.in
.open_func
= openfn
;
276 io
.t2open
.in
.size
= 0;
277 io
.t2open
.in
.timeout
= 0;
278 io
.t2open
.in
.fname
= fname
;
280 io
.t2open
.in
.num_eas
= 1;
281 io
.t2open
.in
.eas
= talloc_array(mem_ctx
, struct ea_struct
, io
.t2open
.in
.num_eas
);
282 io
.t2open
.in
.eas
[0].flags
= 0;
283 io
.t2open
.in
.eas
[0].name
.s
= ".CLASSINFO";
284 io
.t2open
.in
.eas
[0].value
= data_blob_talloc(mem_ctx
, "first value", 11);
286 status
= smb_raw_open(tree
, mem_ctx
, &io
);
287 talloc_free(mem_ctx
);
289 if (fnum
&& NT_STATUS_IS_OK(status
)) {
290 *fnum
= io
.openx
.out
.file
.fnum
;
296 static NTSTATUS
raw_smbcli_ntcreate(struct smbcli_tree
*tree
, const char *fname
, int *fnum
)
302 mem_ctx
= talloc_init("raw_t2open");
303 if (!mem_ctx
) return NT_STATUS_NO_MEMORY
;
305 memset(&io
, '\0', sizeof(io
));
306 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
307 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
308 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
309 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
310 io
.ntcreatex
.in
.alloc_size
= 0;
311 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
312 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
313 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
314 io
.ntcreatex
.in
.create_options
= 0;
315 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
316 io
.ntcreatex
.in
.security_flags
= 0;
317 io
.ntcreatex
.in
.fname
= fname
;
319 status
= smb_raw_open(tree
, mem_ctx
, &io
);
320 talloc_free(mem_ctx
);
322 if (fnum
&& NT_STATUS_IS_OK(status
)) {
323 *fnum
= io
.openx
.out
.file
.fnum
;
330 bool torture_samba3_badpath(struct torture_context
*torture
)
332 struct smbcli_state
*cli_nt
;
333 struct smbcli_state
*cli_dos
;
334 const char *fname
= "test.txt";
335 const char *fname1
= "test1.txt";
336 const char *dirname
= "testdir";
343 bool nt_status_support
;
345 if (!(mem_ctx
= talloc_init("torture_samba3_badpath"))) {
346 d_printf("talloc_init failed\n");
350 nt_status_support
= lpcfg_nt_status_support(torture
->lp_ctx
);
352 if (!lpcfg_set_cmdline(torture
->lp_ctx
, "nt status support", "yes")) {
353 printf("Could not set 'nt status support = yes'\n");
357 if (!torture_open_connection(&cli_nt
, torture
, 0)) {
361 if (!lpcfg_set_cmdline(torture
->lp_ctx
, "nt status support", "no")) {
362 printf("Could not set 'nt status support = yes'\n");
366 if (!torture_open_connection(&cli_dos
, torture
, 1)) {
370 if (!lpcfg_set_cmdline(torture
->lp_ctx
, "nt status support",
371 nt_status_support
? "yes":"no")) {
372 printf("Could not reset 'nt status support = yes'");
376 smbcli_deltree(cli_nt
->tree
, dirname
);
378 status
= smbcli_mkdir(cli_nt
->tree
, dirname
);
379 if (!NT_STATUS_IS_OK(status
)) {
380 d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status
));
385 status
= smbcli_chkpath(cli_nt
->tree
, dirname
);
386 CHECK_STATUS(status
, NT_STATUS_OK
);
388 status
= smbcli_chkpath(cli_nt
->tree
,
389 talloc_asprintf(mem_ctx
, "%s\\bla", dirname
));
390 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
392 status
= smbcli_chkpath(cli_dos
->tree
,
393 talloc_asprintf(mem_ctx
, "%s\\bla", dirname
));
394 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
396 status
= smbcli_chkpath(cli_nt
->tree
,
397 talloc_asprintf(mem_ctx
, "%s\\bla\\blub",
399 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
);
400 status
= smbcli_chkpath(cli_dos
->tree
,
401 talloc_asprintf(mem_ctx
, "%s\\bla\\blub",
403 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
405 if (!(fpath
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname
))) {
408 fnum
= smbcli_open(cli_nt
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
410 d_printf("Could not create file %s: %s\n", fpath
,
411 smbcli_errstr(cli_nt
->tree
));
414 smbcli_close(cli_nt
->tree
, fnum
);
416 if (!(fpath1
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname1
))) {
419 fnum
= smbcli_open(cli_nt
->tree
, fpath1
, O_RDWR
| O_CREAT
, DENY_NONE
);
421 d_printf("Could not create file %s: %s\n", fpath1
,
422 smbcli_errstr(cli_nt
->tree
));
425 smbcli_close(cli_nt
->tree
, fnum
);
428 * Do a whole bunch of error code checks on chkpath
431 status
= smbcli_chkpath(cli_nt
->tree
, fpath
);
432 CHECK_STATUS(status
, NT_STATUS_NOT_A_DIRECTORY
);
433 status
= smbcli_chkpath(cli_dos
->tree
, fpath
);
434 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
436 status
= smbcli_chkpath(cli_nt
->tree
, "..");
437 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
438 status
= smbcli_chkpath(cli_dos
->tree
, "..");
439 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
441 status
= smbcli_chkpath(cli_nt
->tree
, ".");
442 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
443 status
= smbcli_chkpath(cli_dos
->tree
, ".");
444 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
446 status
= smbcli_chkpath(cli_nt
->tree
, "\t");
447 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
448 status
= smbcli_chkpath(cli_dos
->tree
, "\t");
449 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
451 status
= smbcli_chkpath(cli_nt
->tree
, "\t\\bla");
452 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
453 status
= smbcli_chkpath(cli_dos
->tree
, "\t\\bla");
454 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
456 status
= smbcli_chkpath(cli_nt
->tree
, "<");
457 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
458 status
= smbcli_chkpath(cli_dos
->tree
, "<");
459 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
461 status
= smbcli_chkpath(cli_nt
->tree
, "<\\bla");
462 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
463 status
= smbcli_chkpath(cli_dos
->tree
, "<\\bla");
464 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRbadpath
));
467 * .... And the same gang against getatr. Note that the DOS error codes
471 status
= smbcli_getatr(cli_nt
->tree
, fpath
, NULL
, NULL
, NULL
);
472 CHECK_STATUS(status
, NT_STATUS_OK
);
473 status
= smbcli_getatr(cli_dos
->tree
, fpath
, NULL
, NULL
, NULL
);
474 CHECK_STATUS(status
, NT_STATUS_OK
);
476 status
= smbcli_getatr(cli_nt
->tree
, "..", NULL
, NULL
, NULL
);
477 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
478 status
= smbcli_getatr(cli_dos
->tree
, "..", NULL
, NULL
, NULL
);
479 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
481 status
= smbcli_getatr(cli_nt
->tree
, ".", NULL
, NULL
, NULL
);
482 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
483 status
= smbcli_getatr(cli_dos
->tree
, ".", NULL
, NULL
, NULL
);
484 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
486 status
= smbcli_getatr(cli_nt
->tree
, "\t", NULL
, NULL
, NULL
);
487 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
488 status
= smbcli_getatr(cli_dos
->tree
, "\t", NULL
, NULL
, NULL
);
489 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
491 status
= smbcli_getatr(cli_nt
->tree
, "\t\\bla", NULL
, NULL
, NULL
);
492 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
493 status
= smbcli_getatr(cli_dos
->tree
, "\t\\bla", NULL
, NULL
, NULL
);
494 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
496 status
= smbcli_getatr(cli_nt
->tree
, "<", NULL
, NULL
, NULL
);
497 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
498 status
= smbcli_getatr(cli_dos
->tree
, "<", NULL
, NULL
, NULL
);
499 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
501 status
= smbcli_getatr(cli_nt
->tree
, "<\\bla", NULL
, NULL
, NULL
);
502 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
503 status
= smbcli_getatr(cli_dos
->tree
, "<\\bla", NULL
, NULL
, NULL
);
504 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
506 /* Try the same set with openX. */
508 status
= raw_smbcli_open(cli_nt
->tree
, "..", O_RDONLY
, DENY_NONE
, NULL
);
509 CHECK_STATUS(status
, NT_STATUS_OBJECT_PATH_SYNTAX_BAD
);
510 status
= raw_smbcli_open(cli_dos
->tree
, "..", O_RDONLY
, DENY_NONE
, NULL
);
511 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidpath
));
513 status
= raw_smbcli_open(cli_nt
->tree
, ".", O_RDONLY
, DENY_NONE
, NULL
);
514 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
515 status
= raw_smbcli_open(cli_dos
->tree
, ".", O_RDONLY
, DENY_NONE
, NULL
);
516 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
518 status
= raw_smbcli_open(cli_nt
->tree
, "\t", O_RDONLY
, DENY_NONE
, NULL
);
519 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
520 status
= raw_smbcli_open(cli_dos
->tree
, "\t", O_RDONLY
, DENY_NONE
, NULL
);
521 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
523 status
= raw_smbcli_open(cli_nt
->tree
, "\t\\bla", O_RDONLY
, DENY_NONE
, NULL
);
524 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
525 status
= raw_smbcli_open(cli_dos
->tree
, "\t\\bla", O_RDONLY
, DENY_NONE
, NULL
);
526 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
528 status
= raw_smbcli_open(cli_nt
->tree
, "<", O_RDONLY
, DENY_NONE
, NULL
);
529 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
530 status
= raw_smbcli_open(cli_dos
->tree
, "<", O_RDONLY
, DENY_NONE
, NULL
);
531 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
533 status
= raw_smbcli_open(cli_nt
->tree
, "<\\bla", O_RDONLY
, DENY_NONE
, NULL
);
534 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_INVALID
);
535 status
= raw_smbcli_open(cli_dos
->tree
, "<\\bla", O_RDONLY
, DENY_NONE
, NULL
);
536 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRinvalidname
));
538 /* Let's test EEXIST error code mapping. */
539 status
= raw_smbcli_open(cli_nt
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
540 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
541 status
= raw_smbcli_open(cli_dos
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
542 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
544 status
= raw_smbcli_t2open(cli_nt
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
545 if (!NT_STATUS_EQUAL(status
, NT_STATUS_EAS_NOT_SUPPORTED
)
546 || !torture_setting_bool(torture
, "samba3", false)) {
547 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
548 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
550 status
= raw_smbcli_t2open(cli_dos
->tree
, fpath
, O_RDONLY
| O_CREAT
| O_EXCL
, DENY_NONE
, NULL
);
551 if (!NT_STATUS_EQUAL(status
, NT_STATUS_DOS(ERRDOS
,ERReasnotsupported
))
552 || !torture_setting_bool(torture
, "samba3", false)) {
553 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
554 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
557 status
= raw_smbcli_ntcreate(cli_nt
->tree
, fpath
, NULL
);
558 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
559 status
= raw_smbcli_ntcreate(cli_dos
->tree
, fpath
, NULL
);
560 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRfilexists
));
562 /* Try the rename test. */
565 memset(&io
, '\0', sizeof(io
));
566 io
.rename
.in
.pattern1
= fpath1
;
567 io
.rename
.in
.pattern2
= fpath
;
569 /* Try with SMBmv rename. */
570 status
= smb_raw_rename(cli_nt
->tree
, &io
);
571 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
572 status
= smb_raw_rename(cli_dos
->tree
, &io
);
573 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRrename
));
575 /* Try with NT rename. */
576 io
.generic
.level
= RAW_RENAME_NTRENAME
;
577 io
.ntrename
.in
.old_name
= fpath1
;
578 io
.ntrename
.in
.new_name
= fpath
;
579 io
.ntrename
.in
.attrib
= 0;
580 io
.ntrename
.in
.cluster_size
= 0;
581 io
.ntrename
.in
.flags
= RENAME_FLAG_RENAME
;
583 status
= smb_raw_rename(cli_nt
->tree
, &io
);
584 CHECK_STATUS(status
, NT_STATUS_OBJECT_NAME_COLLISION
);
585 status
= smb_raw_rename(cli_dos
->tree
, &io
);
586 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
,ERRrename
));
595 if (cli_nt
!= NULL
) {
596 smbcli_deltree(cli_nt
->tree
, dirname
);
597 torture_close_connection(cli_nt
);
599 if (cli_dos
!= NULL
) {
600 torture_close_connection(cli_dos
);
602 talloc_free(mem_ctx
);
607 static void count_fn(struct clilist_file_info
*info
, const char *name
,
610 int *counter
= (int *)private_data
;
614 bool torture_samba3_caseinsensitive(struct torture_context
*torture
)
616 struct smbcli_state
*cli
;
619 const char *dirname
= "insensitive";
620 const char *ucase_dirname
= "InSeNsItIvE";
621 const char *fname
= "foo";
627 if (!(mem_ctx
= talloc_init("torture_samba3_caseinsensitive"))) {
628 d_printf("talloc_init failed\n");
632 if (!torture_open_connection(&cli
, torture
, 0)) {
636 smbcli_deltree(cli
->tree
, dirname
);
638 status
= smbcli_mkdir(cli
->tree
, dirname
);
639 torture_assert_ntstatus_ok(torture
, status
, "smbcli_mkdir failed");
640 if (!NT_STATUS_IS_OK(status
)) {
644 if (!(fpath
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname
))) {
647 fnum
= smbcli_open(cli
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
649 torture_result(torture
, TORTURE_FAIL
,
650 "Could not create file %s: %s", fpath
,
651 smbcli_errstr(cli
->tree
));
654 smbcli_close(cli
->tree
, fnum
);
656 smbcli_list(cli
->tree
, talloc_asprintf(
657 mem_ctx
, "%s\\*", ucase_dirname
),
658 FILE_ATTRIBUTE_DIRECTORY
|FILE_ATTRIBUTE_HIDDEN
659 |FILE_ATTRIBUTE_SYSTEM
,
660 count_fn
, (void *)&counter
);
666 torture_result(torture
, TORTURE_FAIL
,
667 "expected 3 entries, got %d", counter
);
672 talloc_free(mem_ctx
);
676 static void close_locked_file(struct tevent_context
*ev
,
677 struct tevent_timer
*te
,
681 int *pfd
= (int *)private_data
;
691 struct lock_result_state
{
696 static void receive_lock_result(struct smbcli_request
*req
)
698 struct lock_result_state
*state
=
699 (struct lock_result_state
*)req
->async
.private_data
;
701 state
->status
= smbcli_request_simple_recv(req
);
706 * Check that Samba3 correctly deals with conflicting posix byte range locks
707 * on an underlying file
709 * Note: This test depends on "posix locking = yes".
710 * Note: To run this test, use "--option=torture:localdir=<LOCALDIR>"
713 bool torture_samba3_posixtimedlock(struct torture_context
*tctx
)
715 struct smbcli_state
*cli
;
718 const char *dirname
= "posixlock";
719 const char *fname
= "locked";
721 const char *localdir
;
722 const char *localname
;
726 struct flock posix_lock
;
729 struct smb_lock_entry lock_entry
;
730 struct smbcli_request
*req
;
731 struct lock_result_state lock_result
;
733 struct tevent_timer
*te
;
735 if (!torture_open_connection(&cli
, tctx
, 0)) {
740 smbcli_deltree(cli
->tree
, dirname
);
742 status
= smbcli_mkdir(cli
->tree
, dirname
);
743 if (!NT_STATUS_IS_OK(status
)) {
744 torture_warning(tctx
, "smbcli_mkdir failed: %s\n",
750 if (!(fpath
= talloc_asprintf(tctx
, "%s\\%s", dirname
, fname
))) {
751 torture_warning(tctx
, "talloc failed\n");
755 fnum
= smbcli_open(cli
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
757 torture_warning(tctx
, "Could not create file %s: %s\n", fpath
,
758 smbcli_errstr(cli
->tree
));
763 if (!(localdir
= torture_setting_string(tctx
, "localdir", NULL
))) {
764 torture_warning(tctx
, "Need 'localdir' setting\n");
769 if (!(localname
= talloc_asprintf(tctx
, "%s/%s/%s", localdir
, dirname
,
771 torture_warning(tctx
, "talloc failed\n");
777 * Lock a byte range from posix
780 fd
= open(localname
, O_RDWR
);
782 torture_warning(tctx
, "open(%s) failed: %s\n",
783 localname
, strerror(errno
));
787 posix_lock
.l_type
= F_WRLCK
;
788 posix_lock
.l_whence
= SEEK_SET
;
789 posix_lock
.l_start
= 0;
790 posix_lock
.l_len
= 1;
792 if (fcntl(fd
, F_SETLK
, &posix_lock
) == -1) {
793 torture_warning(tctx
, "fcntl failed: %s\n", strerror(errno
));
799 * Try a cifs brlock without timeout to see if posix locking = yes
802 io
.lockx
.in
.ulock_cnt
= 0;
803 io
.lockx
.in
.lock_cnt
= 1;
805 lock_entry
.count
= 1;
806 lock_entry
.offset
= 0;
807 lock_entry
.pid
= cli
->tree
->session
->pid
;
809 io
.lockx
.level
= RAW_LOCK_LOCKX
;
810 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
811 io
.lockx
.in
.timeout
= 0;
812 io
.lockx
.in
.locks
= &lock_entry
;
813 io
.lockx
.in
.file
.fnum
= fnum
;
815 status
= smb_raw_lock(cli
->tree
, &io
);
818 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
825 * Now fire off a timed brlock, unlock the posix lock and see if the
826 * timed lock gets through.
829 io
.lockx
.in
.timeout
= 5000;
831 req
= smb_raw_lock_send(cli
->tree
, &io
);
833 torture_warning(tctx
, "smb_raw_lock_send failed\n");
838 lock_result
.done
= false;
839 req
->async
.fn
= receive_lock_result
;
840 req
->async
.private_data
= &lock_result
;
842 te
= tevent_add_timer(req
->transport
->socket
->event
.ctx
,
843 tctx
, timeval_current_ofs(1, 0),
844 close_locked_file
, &fd
);
846 torture_warning(tctx
, "tevent_add_timer failed\n");
851 while ((fd
!= -1) || (!lock_result
.done
)) {
852 if (tevent_loop_once(req
->transport
->socket
->event
.ctx
)
854 torture_warning(tctx
, "tevent_loop_once failed: %s\n",
861 CHECK_STATUS(lock_result
.status
, NT_STATUS_OK
);
865 smbcli_close(cli
->tree
, fnum
);
870 smbcli_deltree(cli
->tree
, dirname
);
874 bool torture_samba3_rootdirfid(struct torture_context
*tctx
)
876 struct smbcli_state
*cli
;
880 const char *fname
= "testfile";
883 if (!torture_open_connection(&cli
, tctx
, 0)) {
888 smbcli_unlink(cli
->tree
, fname
);
891 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
892 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
893 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
894 io
.ntcreatex
.in
.security_flags
= 0;
895 io
.ntcreatex
.in
.access_mask
=
896 SEC_STD_SYNCHRONIZE
| SEC_FILE_EXECUTE
;
897 io
.ntcreatex
.in
.alloc_size
= 0;
898 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_DIRECTORY
;
899 io
.ntcreatex
.in
.share_access
=
900 NTCREATEX_SHARE_ACCESS_READ
901 | NTCREATEX_SHARE_ACCESS_READ
;
902 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
903 io
.ntcreatex
.in
.create_options
= 0;
904 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
905 io
.ntcreatex
.in
.fname
= "\\";
906 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
907 if (!NT_STATUS_IS_OK(status
)) {
908 d_printf("smb_open on the directory failed: %s\n",
913 dnum
= io
.ntcreatex
.out
.file
.fnum
;
915 io
.ntcreatex
.in
.flags
=
916 NTCREATEX_FLAGS_REQUEST_OPLOCK
917 | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK
;
918 io
.ntcreatex
.in
.root_fid
.fnum
= dnum
;
919 io
.ntcreatex
.in
.security_flags
= 0;
920 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OVERWRITE_IF
;
921 io
.ntcreatex
.in
.access_mask
= SEC_RIGHTS_FILE_ALL
;
922 io
.ntcreatex
.in
.alloc_size
= 0;
923 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
924 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
925 io
.ntcreatex
.in
.create_options
= 0;
926 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
927 io
.ntcreatex
.in
.fname
= fname
;
929 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
930 if (!NT_STATUS_IS_OK(status
)) {
931 d_printf("smb_open on the file %s failed: %s\n",
932 fname
, nt_errstr(status
));
937 smbcli_close(cli
->tree
, io
.ntcreatex
.out
.file
.fnum
);
938 smbcli_close(cli
->tree
, dnum
);
939 smbcli_unlink(cli
->tree
, fname
);
946 bool torture_samba3_oplock_logoff(struct torture_context
*tctx
)
948 struct smbcli_state
*cli
;
952 const char *fname
= "testfile";
954 struct smbcli_request
*req
;
955 struct smb_echo echo_req
;
957 if (!torture_open_connection(&cli
, tctx
, 0)) {
962 smbcli_unlink(cli
->tree
, fname
);
965 io
.generic
.level
= RAW_OPEN_NTCREATEX
;
966 io
.ntcreatex
.in
.flags
= NTCREATEX_FLAGS_EXTENDED
;
967 io
.ntcreatex
.in
.root_fid
.fnum
= 0;
968 io
.ntcreatex
.in
.security_flags
= 0;
969 io
.ntcreatex
.in
.access_mask
=
970 SEC_STD_SYNCHRONIZE
| SEC_FILE_EXECUTE
;
971 io
.ntcreatex
.in
.alloc_size
= 0;
972 io
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
973 io
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_NONE
;
974 io
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN_IF
;
975 io
.ntcreatex
.in
.create_options
= 0;
976 io
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
977 io
.ntcreatex
.in
.fname
= "testfile";
978 status
= smb_raw_open(cli
->tree
, tctx
, &io
);
979 if (!NT_STATUS_IS_OK(status
)) {
980 d_printf("first smb_open failed: %s\n", nt_errstr(status
));
984 fnum1
= io
.ntcreatex
.out
.file
.fnum
;
987 * Create a conflicting open, causing the one-second delay
990 req
= smb_raw_open_send(cli
->tree
, &io
);
992 d_printf("smb_raw_open_send failed\n");
998 * Pull the VUID from under that request. As of Nov 3, 2008 all Samba3
999 * versions (3.0, 3.2 and master) would spin sending ERRinvuid errors
1000 * as long as the client is still connected.
1003 status
= smb_raw_ulogoff(cli
->session
);
1005 if (!NT_STATUS_IS_OK(status
)) {
1006 d_printf("ulogoff failed: %s\n", nt_errstr(status
));
1011 echo_req
.in
.repeat_count
= 1;
1012 echo_req
.in
.size
= 1;
1013 echo_req
.in
.data
= discard_const_p(uint8_t, "");
1015 status
= smb_raw_echo(cli
->session
->transport
, &echo_req
);
1016 if (!NT_STATUS_IS_OK(status
)) {
1017 d_printf("smb_raw_echo returned %s\n",