Add samba3.samba3badnameblob test to check regressions in bug #9215.
[Samba/gebeck_regimport.git] / source4 / torture / raw / samba3misc.c
bloba818c6bb48413b5fb27337feb153fc88ef32ad68
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"
33 The next 2 functions are stolen from source4/libcli/raw/rawfile.c
34 but allow us to send a raw data blob instead of an OpenX name.
37 #define SETUP_REQUEST(cmd, wct, buflen) do { \
38 req = smbcli_request_setup(tree, cmd, wct, buflen); \
39 if (!req) return NULL; \
40 } while (0)
42 static struct smbcli_request *smb_raw_openX_name_blob_send(struct smbcli_tree *tree,
43 union smb_open *parms,
44 const DATA_BLOB *pname_blob)
46 struct smbcli_request *req = NULL;
48 if (parms->generic.level != RAW_OPEN_OPENX) {
49 return NULL;
52 SETUP_REQUEST(SMBopenX, 15, 0);
53 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
54 SSVAL(req->out.vwv, VWV(1), 0);
55 SSVAL(req->out.vwv, VWV(2), parms->openx.in.flags);
56 SSVAL(req->out.vwv, VWV(3), parms->openx.in.open_mode);
57 SSVAL(req->out.vwv, VWV(4), parms->openx.in.search_attrs);
58 SSVAL(req->out.vwv, VWV(5), parms->openx.in.file_attrs);
59 raw_push_dos_date3(tree->session->transport,
60 req->out.vwv, VWV(6), parms->openx.in.write_time);
61 SSVAL(req->out.vwv, VWV(8), parms->openx.in.open_func);
62 SIVAL(req->out.vwv, VWV(9), parms->openx.in.size);
63 SIVAL(req->out.vwv, VWV(11),parms->openx.in.timeout);
64 SIVAL(req->out.vwv, VWV(13),0); /* reserved */
65 smbcli_req_append_blob(req, pname_blob);
67 if (!smbcli_request_send(req)) {
68 smbcli_request_destroy(req);
69 return NULL;
72 return req;
75 static NTSTATUS smb_raw_openX_name_blob(struct smbcli_tree *tree,
76 TALLOC_CTX *mem_ctx,
77 union smb_open *parms,
78 const DATA_BLOB *pname_blob)
80 struct smbcli_request *req = smb_raw_openX_name_blob_send(tree, parms, pname_blob);
81 return smb_raw_open_recv(req, mem_ctx, parms);
84 static NTSTATUS raw_smbcli_openX_name_blob(struct smbcli_tree *tree,
85 const DATA_BLOB *pname_blob,
86 int flags,
87 int share_mode,
88 int *fnum)
90 union smb_open open_parms;
91 unsigned int openfn=0;
92 unsigned int accessmode=0;
93 TALLOC_CTX *mem_ctx;
94 NTSTATUS status;
96 mem_ctx = talloc_init("raw_openX_name_blob");
97 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
99 if (flags & O_CREAT) {
100 openfn |= OPENX_OPEN_FUNC_CREATE;
102 if (!(flags & O_EXCL)) {
103 if (flags & O_TRUNC) {
104 openfn |= OPENX_OPEN_FUNC_TRUNC;
105 } else {
106 openfn |= OPENX_OPEN_FUNC_OPEN;
110 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
112 if ((flags & O_ACCMODE) == O_RDWR) {
113 accessmode |= OPENX_MODE_ACCESS_RDWR;
114 } else if ((flags & O_ACCMODE) == O_WRONLY) {
115 accessmode |= OPENX_MODE_ACCESS_WRITE;
116 } else if ((flags & O_ACCMODE) == O_RDONLY) {
117 accessmode |= OPENX_MODE_ACCESS_READ;
120 #if defined(O_SYNC)
121 if ((flags & O_SYNC) == O_SYNC) {
122 accessmode |= OPENX_MODE_WRITE_THRU;
124 #endif
126 if (share_mode == DENY_FCB) {
127 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
130 open_parms.openx.level = RAW_OPEN_OPENX;
131 open_parms.openx.in.flags = 0;
132 open_parms.openx.in.open_mode = accessmode;
133 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
134 open_parms.openx.in.file_attrs = 0;
135 open_parms.openx.in.write_time = 0;
136 open_parms.openx.in.open_func = openfn;
137 open_parms.openx.in.size = 0;
138 open_parms.openx.in.timeout = 0;
139 open_parms.openx.in.fname = NULL;
141 status = smb_raw_openX_name_blob(tree, mem_ctx, &open_parms, pname_blob);
142 talloc_free(mem_ctx);
144 if (fnum && NT_STATUS_IS_OK(status)) {
145 *fnum = open_parms.openx.out.file.fnum;
148 return status;
152 #define CHECK_STATUS(torture, status, correct) do { \
153 if (!NT_STATUS_EQUAL(status, correct)) { \
154 torture_result(torture, TORTURE_FAIL, "%s: Incorrect status %s - should be %s\n", \
155 __location__, nt_errstr(status), nt_errstr(correct)); \
156 ret = false; \
158 } while (0)
160 bool torture_samba3_checkfsp(struct torture_context *torture, struct smbcli_state *cli)
162 const char *fname = "test.txt";
163 const char *dirname = "testdir";
164 int fnum;
165 NTSTATUS status;
166 bool ret = true;
167 TALLOC_CTX *mem_ctx;
168 ssize_t nread;
169 char buf[16];
170 struct smbcli_tree *tree2;
172 torture_assert(torture, mem_ctx = talloc_init("torture_samba3_checkfsp"), "talloc_init failed\n");
174 torture_assert_ntstatus_equal(torture, torture_second_tcon(torture, cli->session,
175 torture_setting_string(torture, "share", NULL),
176 &tree2),
177 NT_STATUS_OK,
178 "creating second tcon");
180 /* Try a read on an invalid FID */
182 nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
183 CHECK_STATUS(torture, smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);
185 /* Try a read on a directory handle */
187 torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory");
189 /* Open the directory */
191 union smb_open io;
192 io.generic.level = RAW_OPEN_NTCREATEX;
193 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
194 io.ntcreatex.in.root_fid.fnum = 0;
195 io.ntcreatex.in.security_flags = 0;
196 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
197 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
198 io.ntcreatex.in.alloc_size = 0;
199 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
200 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
201 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
202 io.ntcreatex.in.create_options = 0;
203 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
204 io.ntcreatex.in.fname = dirname;
205 status = smb_raw_open(cli->tree, mem_ctx, &io);
206 if (!NT_STATUS_IS_OK(status)) {
207 torture_result(torture, TORTURE_FAIL, "smb_open on the directory failed: %s\n",
208 nt_errstr(status));
209 ret = false;
210 goto done;
212 fnum = io.ntcreatex.out.file.fnum;
215 /* Try a read on the directory */
217 nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
218 if (nread >= 0) {
219 torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected "
220 "failure\n");
221 ret = false;
224 CHECK_STATUS(torture, smbcli_nt_error(cli->tree),
225 NT_STATUS_INVALID_DEVICE_REQUEST);
227 /* Same test on the second tcon */
229 nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
230 if (nread >= 0) {
231 torture_result(torture, TORTURE_FAIL, "smbcli_read on a directory succeeded, expected "
232 "failure\n");
233 ret = false;
236 CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
238 smbcli_close(cli->tree, fnum);
240 /* Try a normal file read on a second tcon */
242 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
243 if (fnum == -1) {
244 torture_result(torture, TORTURE_FAIL, "Failed to create %s - %s\n", fname,
245 smbcli_errstr(cli->tree));
246 ret = false;
247 goto done;
250 nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
251 CHECK_STATUS(torture, smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);
253 smbcli_close(cli->tree, fnum);
255 done:
256 smbcli_deltree(cli->tree, dirname);
257 talloc_free(mem_ctx);
259 return ret;
262 static NTSTATUS raw_smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
264 union smb_open open_parms;
265 unsigned int openfn=0;
266 unsigned int accessmode=0;
267 TALLOC_CTX *mem_ctx;
268 NTSTATUS status;
270 mem_ctx = talloc_init("raw_open");
271 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
273 if (flags & O_CREAT) {
274 openfn |= OPENX_OPEN_FUNC_CREATE;
276 if (!(flags & O_EXCL)) {
277 if (flags & O_TRUNC) {
278 openfn |= OPENX_OPEN_FUNC_TRUNC;
279 } else {
280 openfn |= OPENX_OPEN_FUNC_OPEN;
284 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
286 if ((flags & O_ACCMODE) == O_RDWR) {
287 accessmode |= OPENX_MODE_ACCESS_RDWR;
288 } else if ((flags & O_ACCMODE) == O_WRONLY) {
289 accessmode |= OPENX_MODE_ACCESS_WRITE;
290 } else if ((flags & O_ACCMODE) == O_RDONLY) {
291 accessmode |= OPENX_MODE_ACCESS_READ;
294 #if defined(O_SYNC)
295 if ((flags & O_SYNC) == O_SYNC) {
296 accessmode |= OPENX_MODE_WRITE_THRU;
298 #endif
300 if (share_mode == DENY_FCB) {
301 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
304 open_parms.openx.level = RAW_OPEN_OPENX;
305 open_parms.openx.in.flags = 0;
306 open_parms.openx.in.open_mode = accessmode;
307 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
308 open_parms.openx.in.file_attrs = 0;
309 open_parms.openx.in.write_time = 0;
310 open_parms.openx.in.open_func = openfn;
311 open_parms.openx.in.size = 0;
312 open_parms.openx.in.timeout = 0;
313 open_parms.openx.in.fname = fname;
315 status = smb_raw_open(tree, mem_ctx, &open_parms);
316 talloc_free(mem_ctx);
318 if (fnum && NT_STATUS_IS_OK(status)) {
319 *fnum = open_parms.openx.out.file.fnum;
322 return status;
325 static NTSTATUS raw_smbcli_t2open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
327 union smb_open io;
328 unsigned int openfn=0;
329 unsigned int accessmode=0;
330 TALLOC_CTX *mem_ctx;
331 NTSTATUS status;
333 mem_ctx = talloc_init("raw_t2open");
334 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
336 if (flags & O_CREAT) {
337 openfn |= OPENX_OPEN_FUNC_CREATE;
339 if (!(flags & O_EXCL)) {
340 if (flags & O_TRUNC) {
341 openfn |= OPENX_OPEN_FUNC_TRUNC;
342 } else {
343 openfn |= OPENX_OPEN_FUNC_OPEN;
347 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
349 if ((flags & O_ACCMODE) == O_RDWR) {
350 accessmode |= OPENX_MODE_ACCESS_RDWR;
351 } else if ((flags & O_ACCMODE) == O_WRONLY) {
352 accessmode |= OPENX_MODE_ACCESS_WRITE;
353 } else if ((flags & O_ACCMODE) == O_RDONLY) {
354 accessmode |= OPENX_MODE_ACCESS_READ;
357 #if defined(O_SYNC)
358 if ((flags & O_SYNC) == O_SYNC) {
359 accessmode |= OPENX_MODE_WRITE_THRU;
361 #endif
363 if (share_mode == DENY_FCB) {
364 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
367 memset(&io, '\0', sizeof(io));
368 io.t2open.level = RAW_OPEN_T2OPEN;
369 io.t2open.in.flags = 0;
370 io.t2open.in.open_mode = accessmode;
371 io.t2open.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
372 io.t2open.in.file_attrs = 0;
373 io.t2open.in.write_time = 0;
374 io.t2open.in.open_func = openfn;
375 io.t2open.in.size = 0;
376 io.t2open.in.timeout = 0;
377 io.t2open.in.fname = fname;
379 io.t2open.in.num_eas = 1;
380 io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
381 io.t2open.in.eas[0].flags = 0;
382 io.t2open.in.eas[0].name.s = ".CLASSINFO";
383 io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);
385 status = smb_raw_open(tree, mem_ctx, &io);
386 talloc_free(mem_ctx);
388 if (fnum && NT_STATUS_IS_OK(status)) {
389 *fnum = io.openx.out.file.fnum;
392 return status;
395 static NTSTATUS raw_smbcli_ntcreate(struct smbcli_tree *tree, const char *fname, int *fnum)
397 union smb_open io;
398 TALLOC_CTX *mem_ctx;
399 NTSTATUS status;
401 mem_ctx = talloc_init("raw_t2open");
402 if (!mem_ctx) return NT_STATUS_NO_MEMORY;
404 memset(&io, '\0', sizeof(io));
405 io.generic.level = RAW_OPEN_NTCREATEX;
406 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
407 io.ntcreatex.in.root_fid.fnum = 0;
408 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
409 io.ntcreatex.in.alloc_size = 0;
410 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
411 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
412 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
413 io.ntcreatex.in.create_options = 0;
414 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
415 io.ntcreatex.in.security_flags = 0;
416 io.ntcreatex.in.fname = fname;
418 status = smb_raw_open(tree, mem_ctx, &io);
419 talloc_free(mem_ctx);
421 if (fnum && NT_STATUS_IS_OK(status)) {
422 *fnum = io.openx.out.file.fnum;
425 return status;
429 bool torture_samba3_badpath(struct torture_context *torture)
431 struct smbcli_state *cli_nt;
432 struct smbcli_state *cli_dos;
433 const char *fname = "test.txt";
434 const char *fname1 = "test1.txt";
435 const char *dirname = "testdir";
436 char *fpath;
437 char *fpath1;
438 int fnum;
439 NTSTATUS status;
440 bool ret = true;
441 TALLOC_CTX *mem_ctx;
442 bool nt_status_support;
444 torture_assert(torture, mem_ctx = talloc_init("torture_samba3_badpath"), "talloc_init failed");
446 nt_status_support = lpcfg_nt_status_support(torture->lp_ctx);
448 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n");
450 torture_assert_goto(torture, torture_open_connection(&cli_nt, torture, 0), ret, fail, "Could not open NTSTATUS connection\n");
452 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n");
454 torture_assert_goto(torture, torture_open_connection(&cli_dos, torture, 1), ret, fail, "Could not open DOS connection\n");
456 torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support",
457 nt_status_support ? "yes":"no"),
458 ret, fail, "Could not set 'nt status support' back to where it was\n");
460 torture_assert(torture, torture_setup_dir(cli_nt, dirname), "creating test directory");
462 status = smbcli_chkpath(cli_nt->tree, dirname);
463 CHECK_STATUS(torture, status, NT_STATUS_OK);
465 status = smbcli_chkpath(cli_nt->tree,
466 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
467 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_NOT_FOUND);
469 status = smbcli_chkpath(cli_dos->tree,
470 talloc_asprintf(mem_ctx, "%s\\bla", dirname));
471 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
473 status = smbcli_chkpath(cli_nt->tree,
474 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
475 dirname));
476 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
477 status = smbcli_chkpath(cli_dos->tree,
478 talloc_asprintf(mem_ctx, "%s\\bla\\blub",
479 dirname));
480 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
482 torture_assert_goto(torture, fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname),
483 ret, fail, "Could not allocate fpath\n");
485 fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
486 if (fnum == -1) {
487 torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath,
488 smbcli_errstr(cli_nt->tree));
489 goto fail;
491 smbcli_close(cli_nt->tree, fnum);
493 if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
494 goto fail;
496 fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
497 if (fnum == -1) {
498 torture_result(torture, TORTURE_FAIL, "Could not create file %s: %s\n", fpath1,
499 smbcli_errstr(cli_nt->tree));
500 goto fail;
502 smbcli_close(cli_nt->tree, fnum);
505 * Do a whole bunch of error code checks on chkpath
508 status = smbcli_chkpath(cli_nt->tree, fpath);
509 CHECK_STATUS(torture, status, NT_STATUS_NOT_A_DIRECTORY);
510 status = smbcli_chkpath(cli_dos->tree, fpath);
511 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
513 status = smbcli_chkpath(cli_nt->tree, "..");
514 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
515 status = smbcli_chkpath(cli_dos->tree, "..");
516 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
518 status = smbcli_chkpath(cli_nt->tree, ".");
519 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
520 status = smbcli_chkpath(cli_dos->tree, ".");
521 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
523 status = smbcli_chkpath(cli_nt->tree, "\t");
524 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
525 status = smbcli_chkpath(cli_dos->tree, "\t");
526 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
528 status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
529 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
530 status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
531 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
533 status = smbcli_chkpath(cli_nt->tree, "<");
534 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
535 status = smbcli_chkpath(cli_dos->tree, "<");
536 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
538 status = smbcli_chkpath(cli_nt->tree, "<\\bla");
539 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
540 status = smbcli_chkpath(cli_dos->tree, "<\\bla");
541 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRbadpath));
544 * .... And the same gang against getatr. Note that the DOS error codes
545 * differ....
548 status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
549 CHECK_STATUS(torture, status, NT_STATUS_OK);
550 status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
551 CHECK_STATUS(torture, status, NT_STATUS_OK);
553 status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
554 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
555 status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
556 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
558 status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
559 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
560 status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
561 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
563 status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
564 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
565 status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
566 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
568 status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
569 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
570 status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
571 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
573 status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
574 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
575 status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
576 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
578 status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
579 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
580 status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
581 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
583 /* Try the same set with openX. */
585 status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
586 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
587 status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
588 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));
590 status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
591 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
592 status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
593 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
595 status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
596 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
597 status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
598 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
600 status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
601 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
602 status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
603 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
605 status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
606 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
607 status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
608 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
610 status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
611 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_INVALID);
612 status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
613 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));
615 /* Let's test EEXIST error code mapping. */
616 status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
617 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
618 status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
619 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
621 status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
622 if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
623 || !torture_setting_bool(torture, "samba3", false)) {
624 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
625 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
627 status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
628 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
629 || !torture_setting_bool(torture, "samba3", false)) {
630 /* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
631 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
634 status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
635 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
636 status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
637 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
639 /* Try the rename test. */
641 union smb_rename io;
642 memset(&io, '\0', sizeof(io));
643 io.rename.in.pattern1 = fpath1;
644 io.rename.in.pattern2 = fpath;
646 /* Try with SMBmv rename. */
647 status = smb_raw_rename(cli_nt->tree, &io);
648 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
649 status = smb_raw_rename(cli_dos->tree, &io);
650 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename));
652 /* Try with NT rename. */
653 io.generic.level = RAW_RENAME_NTRENAME;
654 io.ntrename.in.old_name = fpath1;
655 io.ntrename.in.new_name = fpath;
656 io.ntrename.in.attrib = 0;
657 io.ntrename.in.cluster_size = 0;
658 io.ntrename.in.flags = RENAME_FLAG_RENAME;
660 status = smb_raw_rename(cli_nt->tree, &io);
661 CHECK_STATUS(torture, status, NT_STATUS_OBJECT_NAME_COLLISION);
662 status = smb_raw_rename(cli_dos->tree, &io);
663 CHECK_STATUS(torture, status, NT_STATUS_DOS(ERRDOS,ERRrename));
666 goto done;
668 fail:
669 ret = false;
671 done:
672 if (cli_nt != NULL) {
673 smbcli_deltree(cli_nt->tree, dirname);
674 torture_close_connection(cli_nt);
676 if (cli_dos != NULL) {
677 torture_close_connection(cli_dos);
679 talloc_free(mem_ctx);
681 return ret;
684 static void count_fn(struct clilist_file_info *info, const char *name,
685 void *private_data)
687 int *counter = (int *)private_data;
688 *counter += 1;
691 bool torture_samba3_caseinsensitive(struct torture_context *torture, struct smbcli_state *cli)
693 TALLOC_CTX *mem_ctx;
694 const char *dirname = "insensitive";
695 const char *ucase_dirname = "InSeNsItIvE";
696 const char *fname = "foo";
697 char *fpath;
698 int fnum;
699 int counter = 0;
700 bool ret = false;
702 if (!(mem_ctx = talloc_init("torture_samba3_caseinsensitive"))) {
703 torture_result(torture, TORTURE_FAIL, "talloc_init failed\n");
704 return false;
707 torture_assert(torture, torture_setup_dir(cli, dirname), "creating test directory");
709 if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
710 goto done;
712 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
713 if (fnum == -1) {
714 torture_result(torture, TORTURE_FAIL,
715 "Could not create file %s: %s", fpath,
716 smbcli_errstr(cli->tree));
717 goto done;
719 smbcli_close(cli->tree, fnum);
721 smbcli_list(cli->tree, talloc_asprintf(
722 mem_ctx, "%s\\*", ucase_dirname),
723 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN
724 |FILE_ATTRIBUTE_SYSTEM,
725 count_fn, (void *)&counter);
727 if (counter == 3) {
728 ret = true;
730 else {
731 torture_result(torture, TORTURE_FAIL,
732 "expected 3 entries, got %d", counter);
733 ret = false;
736 done:
737 talloc_free(mem_ctx);
738 return ret;
741 static void close_locked_file(struct tevent_context *ev,
742 struct tevent_timer *te,
743 struct timeval now,
744 void *private_data)
746 int *pfd = (int *)private_data;
748 TALLOC_FREE(te);
750 if (*pfd != -1) {
751 close(*pfd);
752 *pfd = -1;
756 struct lock_result_state {
757 NTSTATUS status;
758 bool done;
761 static void receive_lock_result(struct smbcli_request *req)
763 struct lock_result_state *state =
764 (struct lock_result_state *)req->async.private_data;
766 state->status = smbcli_request_simple_recv(req);
767 state->done = true;
771 * Check that Samba3 correctly deals with conflicting posix byte range locks
772 * on an underlying file
774 * Note: This test depends on "posix locking = yes".
775 * Note: To run this test, use "--option=torture:localdir=<LOCALDIR>"
778 bool torture_samba3_posixtimedlock(struct torture_context *tctx, struct smbcli_state *cli)
780 NTSTATUS status;
781 bool ret = true;
782 const char *dirname = "posixlock";
783 const char *fname = "locked";
784 const char *fpath;
785 const char *localdir;
786 const char *localname;
787 int fnum = -1;
789 int fd = -1;
790 struct flock posix_lock;
792 union smb_lock io;
793 struct smb_lock_entry lock_entry;
794 struct smbcli_request *req;
795 struct lock_result_state lock_result;
797 struct tevent_timer *te;
799 torture_assert(tctx, torture_setup_dir(cli, dirname), "creating test directory");
801 if (!(fpath = talloc_asprintf(tctx, "%s\\%s", dirname, fname))) {
802 torture_warning(tctx, "talloc failed\n");
803 ret = false;
804 goto done;
806 fnum = smbcli_open(cli->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
807 if (fnum == -1) {
808 torture_warning(tctx, "Could not create file %s: %s\n", fpath,
809 smbcli_errstr(cli->tree));
810 ret = false;
811 goto done;
814 if (!(localdir = torture_setting_string(tctx, "localdir", NULL))) {
815 torture_warning(tctx, "Need 'localdir' setting\n");
816 ret = false;
817 goto done;
820 if (!(localname = talloc_asprintf(tctx, "%s/%s/%s", localdir, dirname,
821 fname))) {
822 torture_warning(tctx, "talloc failed\n");
823 ret = false;
824 goto done;
828 * Lock a byte range from posix
831 fd = open(localname, O_RDWR);
832 if (fd == -1) {
833 torture_warning(tctx, "open(%s) failed: %s\n",
834 localname, strerror(errno));
835 goto done;
838 posix_lock.l_type = F_WRLCK;
839 posix_lock.l_whence = SEEK_SET;
840 posix_lock.l_start = 0;
841 posix_lock.l_len = 1;
843 if (fcntl(fd, F_SETLK, &posix_lock) == -1) {
844 torture_warning(tctx, "fcntl failed: %s\n", strerror(errno));
845 ret = false;
846 goto done;
850 * Try a cifs brlock without timeout to see if posix locking = yes
853 io.lockx.in.ulock_cnt = 0;
854 io.lockx.in.lock_cnt = 1;
856 lock_entry.count = 1;
857 lock_entry.offset = 0;
858 lock_entry.pid = cli->tree->session->pid;
860 io.lockx.level = RAW_LOCK_LOCKX;
861 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
862 io.lockx.in.timeout = 0;
863 io.lockx.in.locks = &lock_entry;
864 io.lockx.in.file.fnum = fnum;
866 status = smb_raw_lock(cli->tree, &io);
868 ret = true;
869 CHECK_STATUS(tctx, status, NT_STATUS_FILE_LOCK_CONFLICT);
871 if (!ret) {
872 goto done;
876 * Now fire off a timed brlock, unlock the posix lock and see if the
877 * timed lock gets through.
880 io.lockx.in.timeout = 5000;
882 req = smb_raw_lock_send(cli->tree, &io);
883 if (req == NULL) {
884 torture_warning(tctx, "smb_raw_lock_send failed\n");
885 ret = false;
886 goto done;
889 lock_result.done = false;
890 req->async.fn = receive_lock_result;
891 req->async.private_data = &lock_result;
893 te = tevent_add_timer(tctx->ev,
894 tctx, timeval_current_ofs(1, 0),
895 close_locked_file, &fd);
896 if (te == NULL) {
897 torture_warning(tctx, "tevent_add_timer failed\n");
898 ret = false;
899 goto done;
902 while ((fd != -1) || (!lock_result.done)) {
903 if (tevent_loop_once(tctx->ev) == -1) {
904 torture_warning(tctx, "tevent_loop_once failed: %s\n",
905 strerror(errno));
906 ret = false;
907 goto done;
911 CHECK_STATUS(tctx, lock_result.status, NT_STATUS_OK);
913 done:
914 if (fnum != -1) {
915 smbcli_close(cli->tree, fnum);
917 if (fd != -1) {
918 close(fd);
920 smbcli_deltree(cli->tree, dirname);
921 return ret;
924 bool torture_samba3_rootdirfid(struct torture_context *tctx, struct smbcli_state *cli)
926 uint16_t dnum;
927 union smb_open io;
928 const char *fname = "testfile";
929 bool ret = false;
931 smbcli_unlink(cli->tree, fname);
933 ZERO_STRUCT(io);
934 io.generic.level = RAW_OPEN_NTCREATEX;
935 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
936 io.ntcreatex.in.root_fid.fnum = 0;
937 io.ntcreatex.in.security_flags = 0;
938 io.ntcreatex.in.access_mask =
939 SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE;
940 io.ntcreatex.in.alloc_size = 0;
941 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
942 io.ntcreatex.in.share_access =
943 NTCREATEX_SHARE_ACCESS_READ
944 | NTCREATEX_SHARE_ACCESS_READ;
945 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
946 io.ntcreatex.in.create_options = 0;
947 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
948 io.ntcreatex.in.fname = "\\";
949 torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io),
950 NT_STATUS_OK,
951 ret, done, "smb_open on the directory failed: %s\n");
953 dnum = io.ntcreatex.out.file.fnum;
955 io.ntcreatex.in.flags =
956 NTCREATEX_FLAGS_REQUEST_OPLOCK
957 | NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
958 io.ntcreatex.in.root_fid.fnum = dnum;
959 io.ntcreatex.in.security_flags = 0;
960 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
961 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
962 io.ntcreatex.in.alloc_size = 0;
963 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
964 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
965 io.ntcreatex.in.create_options = 0;
966 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
967 io.ntcreatex.in.fname = fname;
969 torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io),
970 NT_STATUS_OK,
971 ret, done, "smb_open on the file failed");
973 smbcli_close(cli->tree, io.ntcreatex.out.file.fnum);
974 smbcli_close(cli->tree, dnum);
975 smbcli_unlink(cli->tree, fname);
977 ret = true;
978 done:
979 return ret;
982 bool torture_samba3_oplock_logoff(struct torture_context *tctx, struct smbcli_state *cli)
984 uint16_t fnum1;
985 union smb_open io;
986 const char *fname = "testfile";
987 bool ret = false;
988 struct smbcli_request *req;
989 struct smb_echo echo_req;
991 smbcli_unlink(cli->tree, fname);
993 ZERO_STRUCT(io);
994 io.generic.level = RAW_OPEN_NTCREATEX;
995 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
996 io.ntcreatex.in.root_fid.fnum = 0;
997 io.ntcreatex.in.security_flags = 0;
998 io.ntcreatex.in.access_mask =
999 SEC_STD_SYNCHRONIZE | SEC_FILE_EXECUTE;
1000 io.ntcreatex.in.alloc_size = 0;
1001 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
1002 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1003 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
1004 io.ntcreatex.in.create_options = 0;
1005 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1006 io.ntcreatex.in.fname = "testfile";
1007 torture_assert_ntstatus_equal_goto(tctx, smb_raw_open(cli->tree, tctx, &io),
1008 NT_STATUS_OK,
1009 ret, done, "first smb_open on the file failed");
1010 fnum1 = io.ntcreatex.out.file.fnum;
1013 * Create a conflicting open, causing the one-second delay
1016 torture_assert_goto(tctx, req = smb_raw_open_send(cli->tree, &io),
1017 ret, done, "smb_raw_open_send on the file failed");
1020 * Pull the VUID from under that request. As of Nov 3, 2008 all Samba3
1021 * versions (3.0, 3.2 and master) would spin sending ERRinvuid errors
1022 * as long as the client is still connected.
1025 torture_assert_ntstatus_equal_goto(tctx, smb_raw_ulogoff(cli->session),
1026 NT_STATUS_OK,
1027 ret, done, "ulogoff failed failed");
1029 echo_req.in.repeat_count = 1;
1030 echo_req.in.size = 1;
1031 echo_req.in.data = discard_const_p(uint8_t, "");
1033 torture_assert_ntstatus_equal_goto(tctx, smb_raw_echo(cli->session->transport, &echo_req),
1034 NT_STATUS_OK,
1035 ret, done, "smb_raw_echo failed");
1037 ret = true;
1038 done:
1039 return ret;
1042 bool torture_samba3_check_openX_badname(struct torture_context *tctx, struct smbcli_state *cli)
1044 NTSTATUS status;
1045 bool ret = false;
1046 int fnum = -1;
1047 DATA_BLOB name_blob = data_blob_talloc(cli->tree, NULL, 65535);
1049 if (name_blob.data == NULL) {
1050 return false;
1052 memset(name_blob.data, 0xcc, 65535);
1053 status = raw_smbcli_openX_name_blob(cli->tree, &name_blob, O_RDWR, DENY_NONE, &fnum);
1054 CHECK_STATUS(tctx, status, NT_STATUS_OBJECT_NAME_INVALID);
1055 ret = true;
1057 return ret;