2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "torture/smbtorture.h"
23 #include "torture/basic/proto.h"
24 #include "libcli/libcli.h"
25 #include "libcli/raw/raw_proto.h"
26 #include "torture/util.h"
27 #include "system/filesys.h"
28 #include "system/time.h"
29 #include "libcli/resolve/resolve.h"
30 #include "lib/events/events.h"
31 #include "param/param.h"
34 #define CHECK_MAX_FAILURES(label) do { if (++failures >= torture_failures) goto label; } while (0)
37 static struct smbcli_state *open_nbt_connection(struct torture_context *tctx)
39 struct nbt_name called, calling;
40 struct smbcli_state *cli;
41 const char *host = torture_setting_string(tctx, "host", NULL);
42 struct smbcli_options options;
44 make_nbt_name_client(&calling, lp_netbios_name(tctx->lp_ctx));
46 nbt_choose_called_name(NULL, &called, host, NBT_NAME_SERVER);
48 cli = smbcli_state_init(NULL);
50 torture_comment(tctx, "Failed initialize smbcli_struct to connect with %s\n", host);
54 lp_smbcli_options(tctx->lp_ctx, &options);
56 if (!smbcli_socket_connect(cli, host, lp_smb_ports(tctx->lp_ctx), tctx->ev,
57 lp_resolve_context(tctx->lp_ctx), &options,
58 lp_iconv_convenience(tctx->lp_ctx),
59 lp_socket_options(tctx->lp_ctx))) {
60 torture_comment(tctx, "Failed to connect with %s\n", host);
64 if (!smbcli_transport_establish(cli, &calling, &called)) {
65 torture_comment(tctx, "%s rejected the session\n",host);
76 static bool tcon_devtest(struct torture_context *tctx,
77 struct smbcli_state *cli,
78 const char *myshare, const char *devtype,
79 NTSTATUS expected_error)
82 const char *password = torture_setting_string(tctx, "password", NULL);
84 status = NT_STATUS_IS_OK(smbcli_tconX(cli, myshare, devtype,
87 torture_comment(tctx, "Trying share %s with devtype %s\n", myshare, devtype);
89 if (NT_STATUS_IS_OK(expected_error)) {
91 torture_fail(tctx, talloc_asprintf(tctx,
92 "tconX to share %s with type %s "
93 "should have succeeded but failed",
99 torture_fail(tctx, talloc_asprintf(tctx,
100 "tconx to share %s with type %s "
101 "should have failed but succeeded",
104 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),
107 torture_fail(tctx, "Returned unexpected error");
117 test whether fnums and tids open on one VC are available on another (a major
120 static bool run_fdpasstest(struct torture_context *tctx,
121 struct smbcli_state *cli1,
122 struct smbcli_state *cli2)
124 const char *fname = "\\fdpass.tst";
128 smbcli_unlink(cli1->tree, fname);
130 torture_comment(tctx, "Opening a file on connection 1\n");
132 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
133 torture_assert(tctx, fnum1 != -1,
134 talloc_asprintf(tctx,
135 "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree)));
137 torture_comment(tctx, "writing to file on connection 1\n");
140 smbcli_write(cli1->tree, fnum1, 0, "hello world\n", 0, 13) == 13,
141 talloc_asprintf(tctx,
142 "write failed (%s)\n", smbcli_errstr(cli1->tree)));
144 oldtid = cli2->tree->tid;
145 cli2->session->vuid = cli1->session->vuid;
146 cli2->tree->tid = cli1->tree->tid;
147 cli2->session->pid = cli1->session->pid;
149 torture_comment(tctx, "reading from file on connection 2\n");
151 torture_assert(tctx, smbcli_read(cli2->tree, fnum1, buf, 0, 13) != 13,
152 talloc_asprintf(tctx,
153 "read succeeded! nasty security hole [%s]\n", buf));
155 smbcli_close(cli1->tree, fnum1);
156 smbcli_unlink(cli1->tree, fname);
158 cli2->tree->tid = oldtid;
164 This checks how the getatr calls works
166 static bool run_attrtest(struct torture_context *tctx,
167 struct smbcli_state *cli)
171 const char *fname = "\\attrib123456789.tst";
174 smbcli_unlink(cli->tree, fname);
175 fnum = smbcli_open(cli->tree, fname,
176 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
177 smbcli_close(cli->tree, fnum);
179 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
180 torture_comment(tctx, "getatr failed (%s)\n", smbcli_errstr(cli->tree));
184 torture_comment(tctx, "New file time is %s", ctime(&t));
186 if (abs(t - time(NULL)) > 60*60*24*10) {
187 torture_comment(tctx, "ERROR: SMBgetatr bug. time is %s",
193 t2 = t-60*60*24; /* 1 day ago */
195 torture_comment(tctx, "Setting file time to %s", ctime(&t2));
197 if (NT_STATUS_IS_ERR(smbcli_setatr(cli->tree, fname, 0, t2))) {
198 torture_comment(tctx, "setatr failed (%s)\n", smbcli_errstr(cli->tree));
202 if (NT_STATUS_IS_ERR(smbcli_getatr(cli->tree, fname, NULL, NULL, &t))) {
203 torture_comment(tctx, "getatr failed (%s)\n", smbcli_errstr(cli->tree));
207 torture_comment(tctx, "Retrieved file time as %s", ctime(&t));
210 torture_comment(tctx, "ERROR: getatr/setatr bug. times are\n%s",
212 torture_comment(tctx, "%s", ctime(&t2));
216 smbcli_unlink(cli->tree, fname);
222 This checks a couple of trans2 calls
224 static bool run_trans2test(struct torture_context *tctx,
225 struct smbcli_state *cli)
229 time_t c_time, a_time, m_time, w_time, m_time2;
230 const char *fname = "\\trans2.tst";
231 const char *dname = "\\trans2";
232 const char *fname2 = "\\trans2\\trans2.tst";
236 smbcli_unlink(cli->tree, fname);
238 torture_comment(tctx, "Testing qfileinfo\n");
240 fnum = smbcli_open(cli->tree, fname,
241 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
242 if (NT_STATUS_IS_ERR(smbcli_qfileinfo(cli->tree, fnum, NULL, &size, &c_time, &a_time, &m_time,
244 torture_comment(tctx, "ERROR: qfileinfo failed (%s)\n", smbcli_errstr(cli->tree));
248 torture_comment(tctx, "Testing NAME_INFO\n");
250 if (NT_STATUS_IS_ERR(smbcli_qfilename(cli->tree, fnum, &pname))) {
251 torture_comment(tctx, "ERROR: qfilename failed (%s)\n", smbcli_errstr(cli->tree));
255 if (!pname || strcmp(pname, fname)) {
256 torture_comment(tctx, "qfilename gave different name? [%s] [%s]\n",
261 smbcli_close(cli->tree, fnum);
262 smbcli_unlink(cli->tree, fname);
264 fnum = smbcli_open(cli->tree, fname,
265 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
267 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
270 smbcli_close(cli->tree, fnum);
272 torture_comment(tctx, "Checking for sticky create times\n");
274 if (NT_STATUS_IS_ERR(smbcli_qpathinfo(cli->tree, fname, &c_time, &a_time, &m_time, &size, NULL))) {
275 torture_comment(tctx, "ERROR: qpathinfo failed (%s)\n", smbcli_errstr(cli->tree));
278 if (c_time != m_time) {
279 torture_comment(tctx, "create time=%s", ctime(&c_time));
280 torture_comment(tctx, "modify time=%s", ctime(&m_time));
281 torture_comment(tctx, "This system appears to have sticky create times\n");
283 if (a_time % (60*60) == 0) {
284 torture_comment(tctx, "access time=%s", ctime(&a_time));
285 torture_comment(tctx, "This system appears to set a midnight access time\n");
289 if (abs(m_time - time(NULL)) > 60*60*24*7) {
290 torture_comment(tctx, "ERROR: totally incorrect times - maybe word reversed? mtime=%s", ctime(&m_time));
296 smbcli_unlink(cli->tree, fname);
297 fnum = smbcli_open(cli->tree, fname,
298 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
299 smbcli_close(cli->tree, fnum);
300 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, fname, &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
301 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
304 if (w_time < 60*60*24*2) {
305 torture_comment(tctx, "write time=%s", ctime(&w_time));
306 torture_comment(tctx, "This system appears to set a initial 0 write time\n");
311 smbcli_unlink(cli->tree, fname);
314 /* check if the server updates the directory modification time
315 when creating a new file */
316 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
317 torture_comment(tctx, "ERROR: mkdir failed (%s)\n", smbcli_errstr(cli->tree));
321 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time, &w_time, &size, NULL, NULL))) {
322 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
326 fnum = smbcli_open(cli->tree, fname2,
327 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
328 smbcli_write(cli->tree, fnum, 0, &fnum, 0, sizeof(fnum));
329 smbcli_close(cli->tree, fnum);
330 if (NT_STATUS_IS_ERR(smbcli_qpathinfo2(cli->tree, "\\trans2\\", &c_time, &a_time, &m_time2, &w_time, &size, NULL, NULL))) {
331 torture_comment(tctx, "ERROR: qpathinfo2 failed (%s)\n", smbcli_errstr(cli->tree));
334 if (m_time2 == m_time) {
335 torture_comment(tctx, "This system does not update directory modification times\n");
339 smbcli_unlink(cli->tree, fname2);
340 smbcli_rmdir(cli->tree, dname);
345 /* send smb negprot commands, not reading the response */
346 static bool run_negprot_nowait(struct torture_context *tctx)
349 struct smbcli_state *cli, *cli2;
352 torture_comment(tctx, "starting negprot nowait test\n");
354 cli = open_nbt_connection(tctx);
359 torture_comment(tctx, "Filling send buffer\n");
361 for (i=0;i<100;i++) {
362 struct smbcli_request *req;
363 req = smb_raw_negotiate_send(cli->transport, lp_unicode(tctx->lp_ctx), PROTOCOL_NT1);
364 event_loop_once(cli->transport->socket->event.ctx);
365 if (req->state == SMBCLI_REQUEST_ERROR) {
367 torture_comment(tctx, "Failed to fill pipe packet[%d] - %s (ignored)\n", i+1, nt_errstr(req->status));
370 torture_comment(tctx, "Failed to fill pipe - %s \n", nt_errstr(req->status));
371 torture_close_connection(cli);
377 torture_comment(tctx, "Opening secondary connection\n");
378 if (!torture_open_connection(&cli2, tctx, 1)) {
379 torture_comment(tctx, "Failed to open secondary connection\n");
383 if (!torture_close_connection(cli2)) {
384 torture_comment(tctx, "Failed to close secondary connection\n");
388 torture_close_connection(cli);
394 this checks to see if a secondary tconx can use open files from an
397 static bool run_tcon_test(struct torture_context *tctx, struct smbcli_state *cli)
399 const char *fname = "\\tcontest.tmp";
401 uint16_t cnum1, cnum2, cnum3;
402 uint16_t vuid1, vuid2;
405 struct smbcli_tree *tree1;
406 const char *host = torture_setting_string(tctx, "host", NULL);
407 const char *share = torture_setting_string(tctx, "share", NULL);
408 const char *password = torture_setting_string(tctx, "password", NULL);
410 if (smbcli_deltree(cli->tree, fname) == -1) {
411 torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
414 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
416 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
420 cnum1 = cli->tree->tid;
421 vuid1 = cli->session->vuid;
423 memset(buf, 0, 4); /* init buf so valgrind won't complain */
424 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) != 4) {
425 torture_comment(tctx, "initial write failed (%s)\n", smbcli_errstr(cli->tree));
429 tree1 = cli->tree; /* save old tree connection */
430 if (NT_STATUS_IS_ERR(smbcli_tconX(cli, share, "?????", password))) {
431 torture_comment(tctx, "%s refused 2nd tree connect (%s)\n", host,
432 smbcli_errstr(cli->tree));
437 cnum2 = cli->tree->tid;
438 cnum3 = MAX(cnum1, cnum2) + 1; /* any invalid number */
439 vuid2 = cli->session->vuid + 1;
441 /* try a write with the wrong tid */
442 cli->tree->tid = cnum2;
444 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
445 torture_comment(tctx, "* server allows write with wrong TID\n");
448 torture_comment(tctx, "server fails write with wrong TID : %s\n", smbcli_errstr(cli->tree));
452 /* try a write with an invalid tid */
453 cli->tree->tid = cnum3;
455 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
456 torture_comment(tctx, "* server allows write with invalid TID\n");
459 torture_comment(tctx, "server fails write with invalid TID : %s\n", smbcli_errstr(cli->tree));
462 /* try a write with an invalid vuid */
463 cli->session->vuid = vuid2;
464 cli->tree->tid = cnum1;
466 if (smbcli_write(cli->tree, fnum1, 0, buf, 130, 4) == 4) {
467 torture_comment(tctx, "* server allows write with invalid VUID\n");
470 torture_comment(tctx, "server fails write with invalid VUID : %s\n", smbcli_errstr(cli->tree));
473 cli->session->vuid = vuid1;
474 cli->tree->tid = cnum1;
476 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
477 torture_comment(tctx, "close failed (%s)\n", smbcli_errstr(cli->tree));
481 cli->tree->tid = cnum2;
483 if (NT_STATUS_IS_ERR(smbcli_tdis(cli))) {
484 torture_comment(tctx, "secondary tdis failed (%s)\n", smbcli_errstr(cli->tree));
488 cli->tree = tree1; /* restore initial tree */
489 cli->tree->tid = cnum1;
491 smbcli_unlink(tree1, fname);
497 checks for correct tconX support
499 static bool run_tcon_devtype_test(struct torture_context *tctx,
500 struct smbcli_state *cli1)
502 const char *share = torture_setting_string(tctx, "share", NULL);
504 if (!tcon_devtest(tctx, cli1, "IPC$", "A:", NT_STATUS_BAD_DEVICE_TYPE))
507 if (!tcon_devtest(tctx, cli1, "IPC$", "?????", NT_STATUS_OK))
510 if (!tcon_devtest(tctx, cli1, "IPC$", "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
513 if (!tcon_devtest(tctx, cli1, "IPC$", "IPC", NT_STATUS_OK))
516 if (!tcon_devtest(tctx, cli1, "IPC$", "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
519 if (!tcon_devtest(tctx, cli1, share, "A:", NT_STATUS_OK))
522 if (!tcon_devtest(tctx, cli1, share, "?????", NT_STATUS_OK))
525 if (!tcon_devtest(tctx, cli1, share, "LPT:", NT_STATUS_BAD_DEVICE_TYPE))
528 if (!tcon_devtest(tctx, cli1, share, "IPC", NT_STATUS_BAD_DEVICE_TYPE))
531 if (!tcon_devtest(tctx, cli1, share, "FOOBA", NT_STATUS_BAD_DEVICE_TYPE))
537 static bool rw_torture2(struct torture_context *tctx,
538 struct smbcli_state *c1, struct smbcli_state *c2)
540 const char *lockfname = "\\torture2.lck";
545 uint8_t buf_rd[131072];
547 ssize_t bytes_read, bytes_written;
549 torture_assert(tctx, smbcli_deltree(c1->tree, lockfname) != -1,
550 talloc_asprintf(tctx,
551 "unlink failed (%s)", smbcli_errstr(c1->tree)));
553 fnum1 = smbcli_open(c1->tree, lockfname, O_RDWR | O_CREAT | O_EXCL,
555 torture_assert(tctx, fnum1 != -1,
556 talloc_asprintf(tctx,
557 "first open read/write of %s failed (%s)",
558 lockfname, smbcli_errstr(c1->tree)));
559 fnum2 = smbcli_open(c2->tree, lockfname, O_RDONLY,
561 torture_assert(tctx, fnum2 != -1,
562 talloc_asprintf(tctx,
563 "second open read-only of %s failed (%s)",
564 lockfname, smbcli_errstr(c2->tree)));
566 torture_comment(tctx, "Checking data integrity over %d ops\n",
569 for (i=0;i<torture_numops;i++)
571 size_t buf_size = ((uint_t)random()%(sizeof(buf)-1))+ 1;
573 if (torture_setting_bool(tctx, "progress", true)) {
574 torture_comment(tctx, "%d\r", i); fflush(stdout);
578 generate_random_buffer(buf, buf_size);
580 if ((bytes_written = smbcli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
581 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(c1->tree));
582 torture_comment(tctx, "wrote %d, expected %d\n", (int)bytes_written, (int)buf_size);
587 if ((bytes_read = smbcli_read(c2->tree, fnum2, buf_rd, 0, buf_size)) != buf_size) {
588 torture_comment(tctx, "read failed (%s)\n", smbcli_errstr(c2->tree));
589 torture_comment(tctx, "read %d, expected %d\n", (int)bytes_read, (int)buf_size);
594 torture_assert_mem_equal(tctx, buf_rd, buf, buf_size,
595 "read/write compare failed\n");
598 torture_assert_ntstatus_ok(tctx, smbcli_close(c2->tree, fnum2),
599 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(c2->tree)));
600 torture_assert_ntstatus_ok(tctx, smbcli_close(c1->tree, fnum1),
601 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(c1->tree)));
603 torture_assert_ntstatus_ok(tctx, smbcli_unlink(c1->tree, lockfname),
604 talloc_asprintf(tctx, "unlink failed (%s)", smbcli_errstr(c1->tree)));
606 torture_comment(tctx, "\n");
613 static bool run_readwritetest(struct torture_context *tctx,
614 struct smbcli_state *cli1,
615 struct smbcli_state *cli2)
617 torture_comment(tctx, "Running readwritetest v1\n");
618 if (!rw_torture2(tctx, cli1, cli2))
621 torture_comment(tctx, "Running readwritetest v2\n");
623 if (!rw_torture2(tctx, cli1, cli1))
630 test the timing of deferred open requests
632 static bool run_deferopen(struct torture_context *tctx, struct smbcli_state *cli, int dummy)
634 const char *fname = "\\defer_open_test.dat";
642 nsec = torture_setting_int(tctx, "sharedelay", 1000000);
644 sec = ((double)nsec) / ((double) 1000000);
647 torture_comment(tctx, "failed to connect\n");
651 torture_comment(tctx, "Testing deferred open requests.\n");
658 tv = timeval_current();
659 fnum = smbcli_nt_create_full(cli->tree, fname, 0,
661 FILE_ATTRIBUTE_NORMAL,
662 NTCREATEX_SHARE_ACCESS_NONE,
663 NTCREATEX_DISP_OPEN_IF, 0, 0);
667 if (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION)) {
668 double e = timeval_elapsed(&tv);
669 if (e < (0.5 * sec) || e > ((1.5 * sec) + 1)) {
670 torture_comment(tctx,"Timing incorrect %.2f violation 1 sec == %.2f\n",
675 } while (NT_STATUS_EQUAL(smbcli_nt_error(cli->tree),NT_STATUS_SHARING_VIOLATION));
678 torture_comment(tctx,"Failed to open %s, error=%s\n", fname, smbcli_errstr(cli->tree));
682 torture_comment(tctx, "pid %u open %d\n", (unsigned)getpid(), i);
686 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
687 torture_comment(tctx,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
693 if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
694 /* All until the last unlink will fail with sharing violation
695 but also the last request can fail since the file could have
696 been successfully deleted by another (test) process */
697 NTSTATUS status = smbcli_nt_error(cli->tree);
698 if ((!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION))
699 && (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND))) {
700 torture_comment(tctx, "unlink of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
705 torture_comment(tctx, "deferred test finished\n");
710 Try with a wrong vuid and check error message.
713 static bool run_vuidtest(struct torture_context *tctx,
714 struct smbcli_state *cli)
716 const char *fname = "\\vuid.tst";
719 time_t c_time, a_time, m_time;
724 smbcli_unlink(cli->tree, fname);
726 fnum = smbcli_open(cli->tree, fname,
727 O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
729 orig_vuid = cli->session->vuid;
731 cli->session->vuid += 1234;
733 torture_comment(tctx, "Testing qfileinfo with wrong vuid\n");
735 if (NT_STATUS_IS_OK(result = smbcli_qfileinfo(cli->tree, fnum, NULL,
736 &size, &c_time, &a_time,
737 &m_time, NULL, NULL))) {
738 torture_fail(tctx, "qfileinfo passed with wrong vuid");
741 if (!NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
742 NT_STATUS_DOS(ERRSRV, ERRbaduid)) &&
743 !NT_STATUS_EQUAL(cli->transport->error.e.nt_status,
744 NT_STATUS_INVALID_HANDLE)) {
745 torture_fail(tctx, talloc_asprintf(tctx,
746 "qfileinfo should have returned DOS error "
747 "ERRSRV:ERRbaduid\n but returned %s",
748 smbcli_errstr(cli->tree)));
751 cli->session->vuid -= 1234;
753 torture_assert_ntstatus_ok(tctx, smbcli_close(cli->tree, fnum),
754 talloc_asprintf(tctx, "close failed (%s)", smbcli_errstr(cli->tree)));
756 smbcli_unlink(cli->tree, fname);
762 Test open mode returns on read-only files.
764 static bool run_opentest(struct torture_context *tctx, struct smbcli_state *cli1,
765 struct smbcli_state *cli2)
767 const char *fname = "\\readonly.file";
768 char *control_char_fname;
777 asprintf(&control_char_fname, "\\readonly.afile");
778 for (i = 1; i <= 0x1f; i++) {
779 control_char_fname[10] = i;
780 fnum1 = smbcli_nt_create_full(cli1->tree, control_char_fname, 0, SEC_FILE_WRITE_DATA, FILE_ATTRIBUTE_NORMAL,
781 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
783 if (!check_error(__location__, cli1, ERRDOS, ERRinvalidname,
784 NT_STATUS_OBJECT_NAME_INVALID)) {
785 torture_comment(tctx, "Error code should be NT_STATUS_OBJECT_NAME_INVALID, was %s for file with %d char\n",
786 smbcli_errstr(cli1->tree), i);
791 smbcli_close(cli1->tree, fnum1);
793 smbcli_setatr(cli1->tree, control_char_fname, 0, 0);
794 smbcli_unlink(cli1->tree, control_char_fname);
796 free(control_char_fname);
799 torture_comment(tctx, "Create file with control char names passed.\n");
801 smbcli_setatr(cli1->tree, fname, 0, 0);
802 smbcli_unlink(cli1->tree, fname);
804 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
806 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
810 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
811 torture_comment(tctx, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
815 if (NT_STATUS_IS_ERR(smbcli_setatr(cli1->tree, fname, FILE_ATTRIBUTE_READONLY, 0))) {
816 torture_comment(tctx, "smbcli_setatr failed (%s)\n", smbcli_errstr(cli1->tree));
817 CHECK_MAX_FAILURES(error_test1);
821 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
823 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
824 CHECK_MAX_FAILURES(error_test1);
828 /* This will fail - but the error should be ERRnoaccess, not ERRbadshare. */
829 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
831 if (check_error(__location__, cli1, ERRDOS, ERRnoaccess,
832 NT_STATUS_ACCESS_DENIED)) {
833 torture_comment(tctx, "correct error code ERRDOS/ERRnoaccess returned\n");
836 torture_comment(tctx, "finished open test 1\n");
838 smbcli_close(cli1->tree, fnum1);
840 /* Now try not readonly and ensure ERRbadshare is returned. */
842 smbcli_setatr(cli1->tree, fname, 0, 0);
844 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY, DENY_WRITE);
846 torture_comment(tctx, "open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
850 /* This will fail - but the error should be ERRshare. */
851 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_ALL);
853 if (check_error(__location__, cli1, ERRDOS, ERRbadshare,
854 NT_STATUS_SHARING_VIOLATION)) {
855 torture_comment(tctx, "correct error code ERRDOS/ERRbadshare returned\n");
858 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
859 torture_comment(tctx, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
863 smbcli_unlink(cli1->tree, fname);
865 torture_comment(tctx, "finished open test 2\n");
867 /* Test truncate open disposition on file opened for read. */
869 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
871 torture_comment(tctx, "(3) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
875 /* write 20 bytes. */
877 memset(buf, '\0', 20);
879 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
880 torture_comment(tctx, "write failed (%s)\n", smbcli_errstr(cli1->tree));
884 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
885 torture_comment(tctx, "(3) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
889 /* Ensure size == 20. */
890 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
891 torture_comment(tctx, "(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
892 CHECK_MAX_FAILURES(error_test3);
897 torture_comment(tctx, "(3) file size != 20\n");
898 CHECK_MAX_FAILURES(error_test3);
902 /* Now test if we can truncate a file opened for readonly. */
904 fnum1 = smbcli_open(cli1->tree, fname, O_RDONLY|O_TRUNC, DENY_NONE);
906 torture_comment(tctx, "(3) open (2) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
907 CHECK_MAX_FAILURES(error_test3);
911 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
912 torture_comment(tctx, "close2 failed (%s)\n", smbcli_errstr(cli1->tree));
916 /* Ensure size == 0. */
917 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
918 torture_comment(tctx, "(3) getatr failed (%s)\n", smbcli_errstr(cli1->tree));
919 CHECK_MAX_FAILURES(error_test3);
924 torture_comment(tctx, "(3) file size != 0\n");
925 CHECK_MAX_FAILURES(error_test3);
928 torture_comment(tctx, "finished open test 3\n");
930 smbcli_unlink(cli1->tree, fname);
933 torture_comment(tctx, "testing ctemp\n");
934 fnum1 = smbcli_ctemp(cli1->tree, "\\", &tmp_path);
936 torture_comment(tctx, "ctemp failed (%s)\n", smbcli_errstr(cli1->tree));
937 CHECK_MAX_FAILURES(error_test4);
940 torture_comment(tctx, "ctemp gave path %s\n", tmp_path);
941 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
942 torture_comment(tctx, "close of temp failed (%s)\n", smbcli_errstr(cli1->tree));
944 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, tmp_path))) {
945 torture_comment(tctx, "unlink of temp failed (%s)\n", smbcli_errstr(cli1->tree));
948 /* Test the non-io opens... */
950 smbcli_setatr(cli2->tree, fname, 0, 0);
951 smbcli_unlink(cli2->tree, fname);
953 torture_comment(tctx, "TEST #1 testing 2 non-io opens (no delete)\n");
955 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
956 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
959 torture_comment(tctx, "test 1 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
960 CHECK_MAX_FAILURES(error_test10);
964 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
965 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
967 torture_comment(tctx, "test 1 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
968 CHECK_MAX_FAILURES(error_test10);
972 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
973 torture_comment(tctx, "test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
976 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
977 torture_comment(tctx, "test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
981 torture_comment(tctx, "non-io open test #1 passed.\n");
983 smbcli_unlink(cli1->tree, fname);
985 torture_comment(tctx, "TEST #2 testing 2 non-io opens (first with delete)\n");
987 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
988 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
991 torture_comment(tctx, "test 2 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
992 CHECK_MAX_FAILURES(error_test20);
996 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
997 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1000 torture_comment(tctx, "test 2 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1001 CHECK_MAX_FAILURES(error_test20);
1005 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1006 torture_comment(tctx, "test 1 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1009 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1010 torture_comment(tctx, "test 1 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1014 torture_comment(tctx, "non-io open test #2 passed.\n");
1016 smbcli_unlink(cli1->tree, fname);
1018 torture_comment(tctx, "TEST #3 testing 2 non-io opens (second with delete)\n");
1020 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1021 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1024 torture_comment(tctx, "test 3 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1025 CHECK_MAX_FAILURES(error_test30);
1029 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1030 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1033 torture_comment(tctx, "test 3 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1034 CHECK_MAX_FAILURES(error_test30);
1038 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1039 torture_comment(tctx, "test 3 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1042 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1043 torture_comment(tctx, "test 3 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1047 torture_comment(tctx, "non-io open test #3 passed.\n");
1049 smbcli_unlink(cli1->tree, fname);
1051 torture_comment(tctx, "TEST #4 testing 2 non-io opens (both with delete)\n");
1053 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1054 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1057 torture_comment(tctx, "test 4 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1058 CHECK_MAX_FAILURES(error_test40);
1062 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1063 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1066 torture_comment(tctx, "test 4 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1067 CHECK_MAX_FAILURES(error_test40);
1071 torture_comment(tctx, "test 4 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1073 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1074 torture_comment(tctx, "test 4 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1078 torture_comment(tctx, "non-io open test #4 passed.\n");
1080 smbcli_unlink(cli1->tree, fname);
1082 torture_comment(tctx, "TEST #5 testing 2 non-io opens (both with delete - both with file share delete)\n");
1084 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1085 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1088 torture_comment(tctx, "test 5 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1089 CHECK_MAX_FAILURES(error_test50);
1093 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1094 NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1097 torture_comment(tctx, "test 5 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1098 CHECK_MAX_FAILURES(error_test50);
1102 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1103 torture_comment(tctx, "test 5 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1107 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1108 torture_comment(tctx, "test 5 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1112 torture_comment(tctx, "non-io open test #5 passed.\n");
1114 torture_comment(tctx, "TEST #6 testing 1 non-io open, one io open\n");
1116 smbcli_unlink(cli1->tree, fname);
1118 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1119 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1122 torture_comment(tctx, "test 6 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1123 CHECK_MAX_FAILURES(error_test60);
1127 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1128 NTCREATEX_SHARE_ACCESS_READ, NTCREATEX_DISP_OPEN_IF, 0, 0);
1131 torture_comment(tctx, "test 6 open 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1132 CHECK_MAX_FAILURES(error_test60);
1136 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1137 torture_comment(tctx, "test 6 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1141 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
1142 torture_comment(tctx, "test 6 close 2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1146 torture_comment(tctx, "non-io open test #6 passed.\n");
1148 torture_comment(tctx, "TEST #7 testing 1 non-io open, one io open with delete\n");
1150 smbcli_unlink(cli1->tree, fname);
1152 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0, SEC_FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
1153 NTCREATEX_SHARE_ACCESS_NONE, NTCREATEX_DISP_OVERWRITE_IF, 0, 0);
1156 torture_comment(tctx, "test 7 open 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1157 CHECK_MAX_FAILURES(error_test70);
1161 fnum2 = smbcli_nt_create_full(cli2->tree, fname, 0, SEC_STD_DELETE|SEC_FILE_READ_ATTRIBUTE, FILE_ATTRIBUTE_NORMAL,
1162 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN_IF, 0, 0);
1165 torture_comment(tctx, "test 7 open 2 of %s SUCCEEDED - should have failed (%s)\n", fname, smbcli_errstr(cli2->tree));
1166 CHECK_MAX_FAILURES(error_test70);
1170 torture_comment(tctx, "test 7 open 2 of %s gave %s (correct error should be %s)\n", fname, smbcli_errstr(cli2->tree), "sharing violation");
1172 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1173 torture_comment(tctx, "test 7 close 1 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1177 torture_comment(tctx, "non-io open test #7 passed.\n");
1181 torture_comment(tctx, "TEST #8 testing one normal open, followed by lock, followed by open with truncate\n");
1183 smbcli_unlink(cli1->tree, fname);
1185 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1187 torture_comment(tctx, "(8) open (1) of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1191 /* write 20 bytes. */
1193 memset(buf, '\0', 20);
1195 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, 20) != 20) {
1196 torture_comment(tctx, "(8) write failed (%s)\n", smbcli_errstr(cli1->tree));
1200 /* Ensure size == 20. */
1201 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1202 torture_comment(tctx, "(8) getatr (1) failed (%s)\n", smbcli_errstr(cli1->tree));
1203 CHECK_MAX_FAILURES(error_test80);
1208 torture_comment(tctx, "(8) file size != 20\n");
1209 CHECK_MAX_FAILURES(error_test80);
1213 /* Get an exclusive lock on the open file. */
1214 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
1215 torture_comment(tctx, "(8) lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
1216 CHECK_MAX_FAILURES(error_test80);
1220 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
1222 torture_comment(tctx, "(8) open (2) of %s with truncate failed (%s)\n", fname, smbcli_errstr(cli1->tree));
1226 /* Ensure size == 0. */
1227 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &fsize, NULL))) {
1228 torture_comment(tctx, "(8) getatr (2) failed (%s)\n", smbcli_errstr(cli1->tree));
1229 CHECK_MAX_FAILURES(error_test80);
1234 torture_comment(tctx, "(8) file size != 0\n");
1235 CHECK_MAX_FAILURES(error_test80);
1239 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
1240 torture_comment(tctx, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1244 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
1245 torture_comment(tctx, "(8) close1 failed (%s)\n", smbcli_errstr(cli1->tree));
1251 torture_comment(tctx, "open test #8 passed.\n");
1253 smbcli_unlink(cli1->tree, fname);
1258 /* FIRST_DESIRED_ACCESS 0xf019f */
1259 #define FIRST_DESIRED_ACCESS SEC_FILE_READ_DATA|SEC_FILE_WRITE_DATA|SEC_FILE_APPEND_DATA|\
1260 SEC_FILE_READ_EA| /* 0xf */ \
1261 SEC_FILE_WRITE_EA|SEC_FILE_READ_ATTRIBUTE| /* 0x90 */ \
1262 SEC_FILE_WRITE_ATTRIBUTE| /* 0x100 */ \
1263 SEC_STD_DELETE|SEC_STD_READ_CONTROL|\
1264 SEC_STD_WRITE_DAC|SEC_STD_WRITE_OWNER /* 0xf0000 */
1265 /* SECOND_DESIRED_ACCESS 0xe0080 */
1266 #define SECOND_DESIRED_ACCESS SEC_FILE_READ_ATTRIBUTE| /* 0x80 */ \
1267 SEC_STD_READ_CONTROL|SEC_STD_WRITE_DAC|\
1268 SEC_STD_WRITE_OWNER /* 0xe0000 */
1271 #define THIRD_DESIRED_ACCESS FILE_READ_ATTRIBUTE| /* 0x80 */ \
1272 READ_CONTROL|WRITE_DAC|\
1273 SEC_FILE_READ_DATA|\
1280 Test ntcreate calls made by xcopy
1282 static bool run_xcopy(struct torture_context *tctx,
1283 struct smbcli_state *cli1)
1285 const char *fname = "\\test.txt";
1288 fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
1289 FIRST_DESIRED_ACCESS,
1290 FILE_ATTRIBUTE_ARCHIVE,
1291 NTCREATEX_SHARE_ACCESS_NONE,
1292 NTCREATEX_DISP_OVERWRITE_IF,
1295 torture_assert(tctx, fnum1 != -1, talloc_asprintf(tctx,
1296 "First open failed - %s", smbcli_errstr(cli1->tree)));
1298 fnum2 = smbcli_nt_create_full(cli1->tree, fname, 0,
1299 SECOND_DESIRED_ACCESS, 0,
1300 NTCREATEX_SHARE_ACCESS_READ|NTCREATEX_SHARE_ACCESS_WRITE|NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_DISP_OPEN,
1302 torture_assert(tctx, fnum2 != -1, talloc_asprintf(tctx,
1303 "second open failed - %s", smbcli_errstr(cli1->tree)));
1308 static bool run_iometer(struct torture_context *tctx,
1309 struct smbcli_state *cli)
1311 const char *fname = "\\iobw.tst";
1318 memset(buf, 0, sizeof(buf));
1320 status = smbcli_getatr(cli->tree, fname, NULL, &filesize, NULL);
1321 torture_assert_ntstatus_ok(tctx, status,
1322 talloc_asprintf(tctx, "smbcli_getatr failed: %s", nt_errstr(status)));
1324 torture_comment(tctx, "size: %d\n", (int)filesize);
1326 filesize -= (sizeof(buf) - 1);
1328 fnum = smbcli_nt_create_full(cli->tree, fname, 0x16,
1329 0x2019f, 0, 0x3, 3, 0x42, 0x3);
1330 torture_assert(tctx, fnum != -1, talloc_asprintf(tctx, "open failed: %s",
1331 smbcli_errstr(cli->tree)));
1336 int i, num_reads, num_writes;
1338 num_reads = random() % 10;
1339 num_writes = random() % 3;
1341 for (i=0; i<num_reads; i++) {
1343 if (ops++ > torture_numops) {
1346 res = smbcli_read(cli->tree, fnum, buf,
1347 random() % filesize, sizeof(buf));
1348 torture_assert(tctx, res == sizeof(buf),
1349 talloc_asprintf(tctx, "read failed: %s",
1350 smbcli_errstr(cli->tree)));
1352 for (i=0; i<num_writes; i++) {
1354 if (ops++ > torture_numops) {
1357 res = smbcli_write(cli->tree, fnum, 0, buf,
1358 random() % filesize, sizeof(buf));
1359 torture_assert(tctx, res == sizeof(buf),
1360 talloc_asprintf(tctx, "read failed: %s",
1361 smbcli_errstr(cli->tree)));
1369 tries variants of chkpath
1371 static bool torture_chkpath_test(struct torture_context *tctx,
1372 struct smbcli_state *cli)
1377 torture_comment(tctx, "Testing valid and invalid paths\n");
1379 /* cleanup from an old run */
1380 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1381 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1382 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1384 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir"))) {
1385 torture_comment(tctx, "mkdir1 failed : %s\n", smbcli_errstr(cli->tree));
1389 if (NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, "\\chkpath.dir\\dir2"))) {
1390 torture_comment(tctx, "mkdir2 failed : %s\n", smbcli_errstr(cli->tree));
1394 fnum = smbcli_open(cli->tree, "\\chkpath.dir\\foo.txt", O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
1396 torture_comment(tctx, "open1 failed (%s)\n", smbcli_errstr(cli->tree));
1399 smbcli_close(cli->tree, fnum);
1401 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir"))) {
1402 torture_comment(tctx, "chkpath1 failed: %s\n", smbcli_errstr(cli->tree));
1406 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dir2"))) {
1407 torture_comment(tctx, "chkpath2 failed: %s\n", smbcli_errstr(cli->tree));
1411 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\foo.txt"))) {
1412 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1413 NT_STATUS_NOT_A_DIRECTORY);
1415 torture_comment(tctx, "* chkpath on a file should fail\n");
1419 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\bar.txt"))) {
1420 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1421 NT_STATUS_OBJECT_NAME_NOT_FOUND);
1423 torture_comment(tctx, "* chkpath on a non existent file should fail\n");
1427 if (NT_STATUS_IS_ERR(smbcli_chkpath(cli->tree, "\\chkpath.dir\\dirxx\\bar.txt"))) {
1428 ret = check_error(__location__, cli, ERRDOS, ERRbadpath,
1429 NT_STATUS_OBJECT_PATH_NOT_FOUND);
1431 torture_comment(tctx, "* chkpath on a non existent component should fail\n");
1435 smbcli_rmdir(cli->tree, "\\chkpath.dir\\dir2");
1436 smbcli_unlink(cli->tree, "\\chkpath.dir\\*");
1437 smbcli_rmdir(cli->tree, "\\chkpath.dir");
1443 * This is a test to excercise some weird Samba3 error paths.
1446 static bool torture_samba3_errorpaths(struct torture_context *tctx)
1448 bool nt_status_support;
1449 struct smbcli_state *cli_nt = NULL, *cli_dos = NULL;
1450 bool result = false;
1452 const char *os2_fname = ".+,;=[].";
1453 const char *dname = "samba3_errordir";
1457 nt_status_support = lp_nt_status_support(tctx->lp_ctx);
1459 if (!lp_set_cmdline(tctx->lp_ctx, "nt status support", "yes")) {
1460 torture_comment(tctx, "Could not set 'nt status support = yes'\n");
1464 if (!torture_open_connection(&cli_nt, tctx, 0)) {
1468 if (!lp_set_cmdline(tctx->lp_ctx, "nt status support", "no")) {
1469 torture_comment(tctx, "Could not set 'nt status support = yes'\n");
1473 if (!torture_open_connection(&cli_dos, tctx, 1)) {
1477 if (!lp_set_cmdline(tctx->lp_ctx, "nt status support",
1478 nt_status_support ? "yes":"no")) {
1479 torture_comment(tctx, "Could not reset 'nt status support = yes'");
1483 smbcli_unlink(cli_nt->tree, os2_fname);
1484 smbcli_rmdir(cli_nt->tree, dname);
1486 if (!NT_STATUS_IS_OK(smbcli_mkdir(cli_nt->tree, dname))) {
1487 torture_comment(tctx, "smbcli_mkdir(%s) failed: %s\n", dname,
1488 smbcli_errstr(cli_nt->tree));
1492 io.generic.level = RAW_OPEN_NTCREATEX;
1493 io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
1494 io.ntcreatex.in.root_fid.fnum = 0;
1495 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1496 io.ntcreatex.in.alloc_size = 1024*1024;
1497 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1498 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
1499 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
1500 io.ntcreatex.in.create_options = 0;
1501 io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
1502 io.ntcreatex.in.security_flags = 0;
1503 io.ntcreatex.in.fname = dname;
1505 status = smb_raw_open(cli_nt->tree, tctx, &io);
1506 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1507 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1508 __location__, nt_errstr(status),
1509 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1512 status = smb_raw_open(cli_dos->tree, tctx, &io);
1513 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1514 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1515 __location__, nt_errstr(status),
1516 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1520 status = smbcli_mkdir(cli_nt->tree, dname);
1521 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1522 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1523 __location__, nt_errstr(status),
1524 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1527 status = smbcli_mkdir(cli_dos->tree, dname);
1528 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRnoaccess))) {
1529 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1530 __location__, nt_errstr(status),
1531 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRnoaccess)));
1537 md.t2mkdir.level = RAW_MKDIR_T2MKDIR;
1538 md.t2mkdir.in.path = dname;
1539 md.t2mkdir.in.num_eas = 0;
1540 md.t2mkdir.in.eas = NULL;
1542 status = smb_raw_mkdir(cli_nt->tree, &md);
1543 if (!NT_STATUS_EQUAL(status,
1544 NT_STATUS_OBJECT_NAME_COLLISION)) {
1546 tctx, "(%s) incorrect status %s should be "
1547 "NT_STATUS_OBJECT_NAME_COLLISION\n",
1548 __location__, nt_errstr(status));
1551 status = smb_raw_mkdir(cli_dos->tree, &md);
1552 if (!NT_STATUS_EQUAL(status,
1553 NT_STATUS_DOS(ERRDOS, ERRrename))) {
1554 torture_comment(tctx, "(%s) incorrect status %s "
1555 "should be ERRDOS:ERRrename\n",
1556 __location__, nt_errstr(status));
1561 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1562 status = smb_raw_open(cli_nt->tree, tctx, &io);
1563 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
1564 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1565 __location__, nt_errstr(status),
1566 nt_errstr(NT_STATUS_OBJECT_NAME_COLLISION));
1570 status = smb_raw_open(cli_dos->tree, tctx, &io);
1571 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS, ERRfilexists))) {
1572 torture_comment(tctx, "(%s) incorrect status %s should be %s\n",
1573 __location__, nt_errstr(status),
1574 nt_errstr(NT_STATUS_DOS(ERRDOS, ERRfilexists)));
1579 /* Test an invalid DOS deny mode */
1580 const char *fname = "test.txt";
1582 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR | O_CREAT, 5);
1584 torture_comment(tctx, "Open(%s) with invalid deny mode succeeded -- "
1585 "expected failure\n", fname);
1586 smbcli_close(cli_nt->tree, fnum);
1589 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1590 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1591 torture_comment(tctx, "Expected DOS error ERRDOS/ERRbadaccess, "
1592 "got %s\n", smbcli_errstr(cli_nt->tree));
1596 fnum = smbcli_open(cli_dos->tree, fname, O_RDWR | O_CREAT, 5);
1598 torture_comment(tctx, "Open(%s) with invalid deny mode succeeded -- "
1599 "expected failure\n", fname);
1600 smbcli_close(cli_nt->tree, fnum);
1603 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1604 NT_STATUS_DOS(ERRDOS,ERRbadaccess))) {
1605 torture_comment(tctx, "Expected DOS error ERRDOS:ERRbadaccess, "
1606 "got %s\n", smbcli_errstr(cli_nt->tree));
1613 * Samba 3.0.23 has a bug that an existing file can be opened
1614 * as a directory using ntcreate&x. Test this.
1617 const char *fname = "\\test_dir.txt";
1619 fnum = smbcli_open(cli_nt->tree, fname, O_RDWR|O_CREAT,
1622 d_printf("(%s) smbcli_open failed: %s\n", __location__,
1623 smbcli_errstr(cli_nt->tree));
1625 smbcli_close(cli_nt->tree, fnum);
1627 io.generic.level = RAW_OPEN_NTCREATEX;
1628 io.ntcreatex.in.root_fid.fnum = 0;
1629 io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
1630 io.ntcreatex.in.alloc_size = 0;
1631 io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
1632 io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ|
1633 NTCREATEX_SHARE_ACCESS_WRITE|
1634 NTCREATEX_SHARE_ACCESS_DELETE;
1635 io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
1636 io.ntcreatex.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
1637 io.ntcreatex.in.impersonation =
1638 NTCREATEX_IMPERSONATION_ANONYMOUS;
1639 io.ntcreatex.in.security_flags = 0;
1640 io.ntcreatex.in.fname = fname;
1641 io.ntcreatex.in.flags = 0;
1643 status = smb_raw_open(cli_nt->tree, tctx, &io);
1644 if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_A_DIRECTORY)) {
1645 torture_comment(tctx, "ntcreate as dir gave %s, "
1646 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1651 if (NT_STATUS_IS_OK(status)) {
1652 smbcli_close(cli_nt->tree, io.ntcreatex.out.file.fnum);
1655 status = smb_raw_open(cli_dos->tree, tctx, &io);
1656 if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,
1657 ERRbaddirectory))) {
1658 torture_comment(tctx, "ntcreate as dir gave %s, "
1659 "expected NT_STATUS_NOT_A_DIRECTORY\n",
1664 if (NT_STATUS_IS_OK(status)) {
1665 smbcli_close(cli_dos->tree,
1666 io.ntcreatex.out.file.fnum);
1669 smbcli_unlink(cli_nt->tree, fname);
1672 if (!torture_setting_bool(tctx, "samba3", false)) {
1676 fnum = smbcli_open(cli_dos->tree, os2_fname,
1677 O_RDWR | O_CREAT | O_TRUNC,
1680 torture_comment(tctx, "Open(%s) succeeded -- expected failure\n",
1682 smbcli_close(cli_dos->tree, fnum);
1686 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_dos->tree),
1687 NT_STATUS_DOS(ERRDOS, ERRcannotopen))) {
1688 torture_comment(tctx, "Expected DOS error ERRDOS/ERRcannotopen, got %s\n",
1689 smbcli_errstr(cli_dos->tree));
1693 fnum = smbcli_open(cli_nt->tree, os2_fname,
1694 O_RDWR | O_CREAT | O_TRUNC,
1697 torture_comment(tctx, "Open(%s) succeeded -- expected failure\n",
1699 smbcli_close(cli_nt->tree, fnum);
1703 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli_nt->tree),
1704 NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1705 torture_comment(tctx, "Expected error NT_STATUS_OBJECT_NAME_NOT_FOUND, "
1706 "got %s\n", smbcli_errstr(cli_nt->tree));
1714 if (cli_dos != NULL) {
1715 torture_close_connection(cli_dos);
1717 if (cli_nt != NULL) {
1718 torture_close_connection(cli_nt);
1725 NTSTATUS torture_base_init(void)
1727 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "BASE");
1729 torture_suite_add_2smb_test(suite, "FDPASS", run_fdpasstest);
1730 torture_suite_add_suite(suite, torture_base_locktest(suite));
1731 torture_suite_add_1smb_test(suite, "UNLINK", torture_unlinktest);
1732 torture_suite_add_1smb_test(suite, "ATTR", run_attrtest);
1733 torture_suite_add_1smb_test(suite, "TRANS2", run_trans2test);
1734 torture_suite_add_simple_test(suite, "NEGNOWAIT", run_negprot_nowait);
1735 torture_suite_add_1smb_test(suite, "DIR1", torture_dirtest1);
1736 torture_suite_add_1smb_test(suite, "DIR2", torture_dirtest2);
1737 torture_suite_add_1smb_test(suite, "DENY1", torture_denytest1);
1738 torture_suite_add_2smb_test(suite, "DENY2", torture_denytest2);
1739 torture_suite_add_2smb_test(suite, "DENY3", torture_denytest3);
1740 torture_suite_add_1smb_test(suite, "DENYDOS", torture_denydos_sharing);
1741 torture_suite_add_smb_multi_test(suite, "NTDENY1", torture_ntdenytest1);
1742 torture_suite_add_2smb_test(suite, "NTDENY2", torture_ntdenytest2);
1743 torture_suite_add_1smb_test(suite, "TCON", run_tcon_test);
1744 torture_suite_add_1smb_test(suite, "TCONDEV", run_tcon_devtype_test);
1745 torture_suite_add_1smb_test(suite, "VUID", run_vuidtest);
1746 torture_suite_add_2smb_test(suite, "RW1", run_readwritetest);
1747 torture_suite_add_2smb_test(suite, "OPEN", run_opentest);
1748 torture_suite_add_smb_multi_test(suite, "DEFER_OPEN", run_deferopen);
1749 torture_suite_add_1smb_test(suite, "XCOPY", run_xcopy);
1750 torture_suite_add_1smb_test(suite, "IOMETER", run_iometer);
1751 torture_suite_add_1smb_test(suite, "RENAME", torture_test_rename);
1752 torture_suite_add_suite(suite, torture_test_delete());
1753 torture_suite_add_1smb_test(suite, "PROPERTIES", torture_test_properties);
1754 torture_suite_add_1smb_test(suite, "MANGLE", torture_mangle);
1755 torture_suite_add_1smb_test(suite, "OPENATTR", torture_openattrtest);
1756 torture_suite_add_suite(suite, torture_charset(suite));
1757 torture_suite_add_1smb_test(suite, "CHKPATH", torture_chkpath_test);
1758 torture_suite_add_1smb_test(suite, "SECLEAK", torture_sec_leak);
1759 torture_suite_add_simple_test(suite, "DISCONNECT", torture_disconnect);
1760 torture_suite_add_suite(suite, torture_delay_write());
1761 torture_suite_add_simple_test(suite, "SAMBA3ERROR", torture_samba3_errorpaths);
1762 torture_suite_add_1smb_test(suite, "CASETABLE", torture_casetable);
1763 torture_suite_add_1smb_test(suite, "UTABLE", torture_utable);
1764 torture_suite_add_simple_test(suite, "SMB", torture_smb_scan);
1765 torture_suite_add_suite(suite, torture_trans2_aliases(suite));
1766 torture_suite_add_1smb_test(suite, "TRANS2-SCAN", torture_trans2_scan);
1767 torture_suite_add_1smb_test(suite, "NTTRANS", torture_nttrans_scan);
1768 torture_suite_add_1smb_test(suite, "CREATEX_ACCESS", torture_createx_access);
1769 torture_suite_add_2smb_test(suite, "CREATEX_SHAREMODES_FILE", torture_createx_sharemodes_file);
1770 torture_suite_add_2smb_test(suite, "CREATEX_SHAREMODES_DIR", torture_createx_sharemodes_dir);
1771 torture_suite_add_1smb_test(suite, "MAXIMUM_ALLOWED", torture_maximum_allowed);
1773 torture_suite_add_simple_test(suite, "BENCH-HOLDCON", torture_holdcon);
1774 torture_suite_add_simple_test(suite, "BENCH-READWRITE", run_benchrw);
1775 torture_suite_add_smb_multi_test(suite, "BENCH-TORTURE", run_torture);
1776 torture_suite_add_1smb_test(suite, "SCAN-PIPE_NUMBER", run_pipe_number);
1777 torture_suite_add_1smb_test(suite, "SCAN-IOCTL", torture_ioctl_test);
1778 torture_suite_add_smb_multi_test(suite, "SCAN-MAXFID", run_maxfidtest);
1780 suite->description = talloc_strdup(suite,
1781 "Basic SMB tests (imported from the original smbtorture)");
1783 torture_register_suite(suite);
1785 return NT_STATUS_OK;