s3-selftest: Remove some unnecessary comma
[Samba/gebeck_regimport.git] / source4 / torture / raw / samba3misc.c
blob07669ed28b0131014d84a08329bbe8555821fe3b
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(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)); \
36 ret = false; \
37 } \
38 } while (0)
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";
45 int fnum;
46 NTSTATUS status;
47 bool ret = true;
48 TALLOC_CTX *mem_ctx;
49 ssize_t nread;
50 char buf[16];
51 struct smbcli_tree *tree2;
53 if ((mem_ctx = talloc_init("torture_samba3_checkfsp")) == NULL) {
54 d_printf("talloc_init failed\n");
55 return false;
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");
62 ret = false;
63 goto done;
66 smbcli_deltree(cli->tree, dirname);
68 status = torture_second_tcon(torture, cli->session,
69 torture_setting_string(torture, "share", NULL),
70 &tree2);
71 CHECK_STATUS(status, NT_STATUS_OK);
72 if (!NT_STATUS_IS_OK(status))
73 goto done;
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));
85 ret = false;
86 goto done;
89 /* Open the directory */
91 union smb_open io;
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",
108 nt_errstr(status));
109 ret = false;
110 goto done;
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));
118 if (nread >= 0) {
119 d_printf("smbcli_read on a directory succeeded, expected "
120 "failure\n");
121 ret = false;
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));
130 if (nread >= 0) {
131 d_printf("smbcli_read on a directory succeeded, expected "
132 "failure\n");
133 ret = false;
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);
143 if (fnum == -1) {
144 d_printf("Failed to create %s - %s\n", fname,
145 smbcli_errstr(cli->tree));
146 ret = false;
147 goto done;
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);
155 done:
156 smbcli_deltree(cli->tree, dirname);
157 torture_close_connection(cli);
158 talloc_free(mem_ctx);
160 return ret;
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;
168 TALLOC_CTX *mem_ctx;
169 NTSTATUS status;
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;
180 } else {
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;
195 #if defined(O_SYNC)
196 if ((flags & O_SYNC) == O_SYNC) {
197 accessmode |= OPENX_MODE_WRITE_THRU;
199 #endif
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;
223 return status;
226 static NTSTATUS raw_smbcli_t2open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
228 union smb_open io;
229 unsigned int openfn=0;
230 unsigned int accessmode=0;
231 TALLOC_CTX *mem_ctx;
232 NTSTATUS status;
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;
243 } else {
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;
258 #if defined(O_SYNC)
259 if ((flags & O_SYNC) == O_SYNC) {
260 accessmode |= OPENX_MODE_WRITE_THRU;
262 #endif
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;
293 return status;
296 static NTSTATUS raw_smbcli_ntcreate(struct smbcli_tree *tree, const char *fname, int *fnum)
298 union smb_open io;
299 TALLOC_CTX *mem_ctx;
300 NTSTATUS status;
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;
326 return status;
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";
337 char *fpath;
338 char *fpath1;
339 int fnum;
340 NTSTATUS status;
341 bool ret = true;
342 TALLOC_CTX *mem_ctx;
343 bool nt_status_support;
345 if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) {
346 d_printf("talloc_init failed\n");
347 return false;
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");
354 goto fail;
357 if (!torture_open_connection(&cli_nt, torture, 0)) {
358 goto fail;
361 if (!lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no")) {
362 printf("Could not set 'nt status support = yes'\n");
363 goto fail;
366 if (!torture_open_connection(&cli_dos, torture, 1)) {
367 goto fail;
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'");
373 goto fail;
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));
381 ret = false;
382 goto done;
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",
398 dirname));
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",
402 dirname));
403 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
405 if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
406 goto fail;
408 fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
409 if (fnum == -1) {
410 d_printf("Could not create file %s: %s\n", fpath,
411 smbcli_errstr(cli_nt->tree));
412 goto fail;
414 smbcli_close(cli_nt->tree, fnum);
416 if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
417 goto fail;
419 fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
420 if (fnum == -1) {
421 d_printf("Could not create file %s: %s\n", fpath1,
422 smbcli_errstr(cli_nt->tree));
423 goto fail;
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
468 * differ....
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. */
564 union smb_rename io;
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));
589 goto done;
591 fail:
592 ret = false;
594 done:
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);
604 return ret;
607 static void count_fn(struct clilist_file_info *info, const char *name,
608 void *private_data)
610 int *counter = (int *)private_data;
611 *counter += 1;
614 bool torture_samba3_caseinsensitive(struct torture_context *torture)
616 struct smbcli_state *cli;
617 TALLOC_CTX *mem_ctx;
618 NTSTATUS status;
619 const char *dirname = "insensitive";
620 const char *ucase_dirname = "InSeNsItIvE";
621 const char *fname = "foo";
622 char *fpath;
623 int fnum;
624 int counter = 0;
625 bool ret = false;
627 if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
628 d_printf("talloc_init failed\n");
629 return false;
632 if (!torture_open_connection(&cli, torture, 0)) {
633 goto done;
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)) {
641 goto done;
644 if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
645 goto done;
647 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
648 if (fnum == -1) {
649 torture_result(torture, TORTURE_FAIL,
650 "Could not create file %s: %s", fpath,
651 smbcli_errstr(cli->tree));
652 goto done;
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);
662 if (counter == 3) {
663 ret = true;
665 else {
666 torture_result(torture, TORTURE_FAIL,
667 "expected 3 entries, got %d", counter);
668 ret = false;
671 done:
672 talloc_free(mem_ctx);
673 return ret;
676 static void close_locked_file(struct tevent_context *ev,
677 struct tevent_timer *te,
678 struct timeval now,
679 void *private_data)
681 int *pfd = (int *)private_data;
683 TALLOC_FREE(te);
685 if (*pfd != -1) {
686 close(*pfd);
687 *pfd = -1;
691 struct lock_result_state {
692 NTSTATUS status;
693 bool done;
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);
702 state->done = true;
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;
716 NTSTATUS status;
717 bool ret = true;
718 const char *dirname = "posixlock";
719 const char *fname = "locked";
720 const char *fpath;
721 const char *localdir;
722 const char *localname;
723 int fnum = -1;
725 int fd = -1;
726 struct flock posix_lock;
728 union smb_lock io;
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)) {
736 ret = false;
737 goto done;
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",
745 nt_errstr(status));
746 ret = false;
747 goto done;
750 if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) {
751 torture_warning(tctx, "talloc failed\n");
752 ret = false;
753 goto done;
755 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
756 if (fnum == -1) {
757 torture_warning(tctx, "Could not create file %s: %s\n", fpath,
758 smbcli_errstr(cli->tree));
759 ret = false;
760 goto done;
763 if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) {
764 torture_warning(tctx, "Need 'localdir' setting\n");
765 ret = false;
766 goto done;
769 if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname,
770 fname))) {
771 torture_warning(tctx, "talloc failed\n");
772 ret = false;
773 goto done;
777 * Lock a byte range from posix
780 fd = open(localname, O_RDWR);
781 if (fd == -1) {
782 torture_warning(tctx, "open(%s) failed: %s\n",
783 localname, strerror(errno));
784 goto done;
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));
794 ret = false;
795 goto done;
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);
817 ret = true;
818 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
820 if (!ret) {
821 goto done;
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);
832 if (req == NULL) {
833 torture_warning(tctx, "smb_raw_lock_send failed\n");
834 ret = false;
835 goto done;
838 lock_result.done = false;
839 req->async.fn = receive_lock_result;
840 req->async.private_data = &lock_result;
842 te = tevent_add_timer(tctx->ev,
843 tctx, timeval_current_ofs(1, 0),
844 close_locked_file, &fd);
845 if (te == NULL) {
846 torture_warning(tctx, "tevent_add_timer failed\n");
847 ret = false;
848 goto done;
851 while ((fd != -1) || (!lock_result.done)) {
852 if (tevent_loop_once(tctx->ev) == -1) {
853 torture_warning(tctx, "tevent_loop_once failed: %s\n",
854 strerror(errno));
855 ret = false;
856 goto done;
860 CHECK_STATUS(lock_result.status, NT_STATUS_OK);
862 done:
863 if (fnum != -1) {
864 smbcli_close(cli->tree, fnum);
866 if (fd != -1) {
867 close(fd);
869 smbcli_deltree(cli->tree, dirname);
870 return ret;
873 bool torture_samba3_rootdirfid(struct torture_context *tctx)
875 struct smbcli_state *cli;
876 NTSTATUS status;
877 uint16_t dnum;
878 union smb_open io;
879 const char *fname = "testfile";
880 bool ret = false;
882 if (!torture_open_connection(&cli, tctx, 0)) {
883 ret = false;
884 goto done;
887 smbcli_unlink(cli->tree, fname);
889 ZERO_STRUCT(io);
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",
908 nt_errstr(status));
909 ret = false;
910 goto done;
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));
932 ret = false;
933 goto done;
936 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
937 smbcli_close(cli->tree, dnum);
938 smbcli_unlink(cli->tree, fname);
940 ret = true;
941 done:
942 return ret;
945 bool torture_samba3_oplock_logoff(struct torture_context *tctx)
947 struct smbcli_state *cli;
948 NTSTATUS status;
949 uint16_t fnum1;
950 union smb_open io;
951 const char *fname = "testfile";
952 bool ret = false;
953 struct smbcli_request *req;
954 struct smb_echo echo_req;
956 if (!torture_open_connection(&cli, tctx, 0)) {
957 ret = false;
958 goto done;
961 smbcli_unlink(cli->tree, fname);
963 ZERO_STRUCT(io);
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));
980 ret = false;
981 goto done;
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);
990 if (req == NULL) {
991 d_printf("smb_raw_open_send failed\n");
992 ret = false;
993 goto done;
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));
1006 ret = false;
1007 goto done;
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",
1017 nt_errstr(status));
1018 ret = false;
1019 goto done;
1022 ret = true;
1023 done:
1024 return ret;