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(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)); \
40 bool torture_samba3_checkfsp(struct torture_context
*torture
, struct smbcli_state
*cli
)
42 const char *fname
= "test.txt";
43 const char *dirname
= "testdir";
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
),
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 */
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",
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
));
99 torture_result(torture
, TORTURE_FAIL
, "smbcli_read on a directory succeeded, expected "
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
));
111 torture_result(torture
, TORTURE_FAIL
, "smbcli_read on a directory succeeded, expected "
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
);
124 torture_result(torture
, TORTURE_FAIL
, "Failed to create %s - %s\n", fname
,
125 smbcli_errstr(cli
->tree
));
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
);
136 smbcli_deltree(cli
->tree
, dirname
);
137 talloc_free(mem_ctx
);
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;
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
;
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
;
175 if ((flags
& O_SYNC
) == O_SYNC
) {
176 accessmode
|= OPENX_MODE_WRITE_THRU
;
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
;
205 static NTSTATUS
raw_smbcli_t2open(struct smbcli_tree
*tree
, const char *fname
, int flags
, int share_mode
, int *fnum
)
208 unsigned int openfn
=0;
209 unsigned int accessmode
=0;
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
;
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
;
238 if ((flags
& O_SYNC
) == O_SYNC
) {
239 accessmode
|= OPENX_MODE_WRITE_THRU
;
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
;
275 static NTSTATUS
raw_smbcli_ntcreate(struct smbcli_tree
*tree
, const char *fname
, int *fnum
)
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
;
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";
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",
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",
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
);
367 torture_result(torture
, TORTURE_FAIL
, "Could not create file %s: %s\n", fpath
,
368 smbcli_errstr(cli_nt
->tree
));
371 smbcli_close(cli_nt
->tree
, fnum
);
373 if (!(fpath1
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname1
))) {
376 fnum
= smbcli_open(cli_nt
->tree
, fpath1
, O_RDWR
| O_CREAT
, DENY_NONE
);
378 torture_result(torture
, TORTURE_FAIL
, "Could not create file %s: %s\n", fpath1
,
379 smbcli_errstr(cli_nt
->tree
));
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
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. */
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
));
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
);
564 static void count_fn(struct clilist_file_info
*info
, const char *name
,
567 int *counter
= (int *)private_data
;
571 bool torture_samba3_caseinsensitive(struct torture_context
*torture
, struct smbcli_state
*cli
)
574 const char *dirname
= "insensitive";
575 const char *ucase_dirname
= "InSeNsItIvE";
576 const char *fname
= "foo";
582 if (!(mem_ctx
= talloc_init("torture_samba3_caseinsensitive"))) {
583 torture_result(torture
, TORTURE_FAIL
, "talloc_init failed\n");
587 torture_assert(torture
, torture_setup_dir(cli
, dirname
), "creating test directory");
589 if (!(fpath
= talloc_asprintf(mem_ctx
, "%s\\%s", dirname
, fname
))) {
592 fnum
= smbcli_open(cli
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
594 torture_result(torture
, TORTURE_FAIL
,
595 "Could not create file %s: %s", fpath
,
596 smbcli_errstr(cli
->tree
));
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
);
611 torture_result(torture
, TORTURE_FAIL
,
612 "expected 3 entries, got %d", counter
);
617 talloc_free(mem_ctx
);
621 static void close_locked_file(struct tevent_context
*ev
,
622 struct tevent_timer
*te
,
626 int *pfd
= (int *)private_data
;
636 struct lock_result_state
{
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
);
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
)
662 const char *dirname
= "posixlock";
663 const char *fname
= "locked";
665 const char *localdir
;
666 const char *localname
;
670 struct flock posix_lock
;
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");
686 fnum
= smbcli_open(cli
->tree
, fpath
, O_RDWR
| O_CREAT
, DENY_NONE
);
688 torture_warning(tctx
, "Could not create file %s: %s\n", fpath
,
689 smbcli_errstr(cli
->tree
));
694 if (!(localdir
= torture_setting_string(tctx
, "localdir", NULL
))) {
695 torture_warning(tctx
, "Need 'localdir' setting\n");
700 if (!(localname
= talloc_asprintf(tctx
, "%s/%s/%s", localdir
, dirname
,
702 torture_warning(tctx
, "talloc failed\n");
708 * Lock a byte range from posix
711 fd
= open(localname
, O_RDWR
);
713 torture_warning(tctx
, "open(%s) failed: %s\n",
714 localname
, strerror(errno
));
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
));
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
);
749 CHECK_STATUS(tctx
, status
, NT_STATUS_FILE_LOCK_CONFLICT
);
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
);
764 torture_warning(tctx
, "smb_raw_lock_send failed\n");
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
);
777 torture_warning(tctx
, "tevent_add_timer failed\n");
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",
791 CHECK_STATUS(tctx
, lock_result
.status
, NT_STATUS_OK
);
795 smbcli_close(cli
->tree
, fnum
);
800 smbcli_deltree(cli
->tree
, dirname
);
804 bool torture_samba3_rootdirfid(struct torture_context
*tctx
, struct smbcli_state
*cli
)
808 const char *fname
= "testfile";
811 smbcli_unlink(cli
->tree
, fname
);
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
),
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
),
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
);
862 bool torture_samba3_oplock_logoff(struct torture_context
*tctx
, struct smbcli_state
*cli
)
866 const char *fname
= "testfile";
868 struct smbcli_request
*req
;
869 struct smb_echo echo_req
;
871 smbcli_unlink(cli
->tree
, fname
);
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
),
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
),
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
),
915 ret
, done
, "smb_raw_echo failed");